SNSログイン機能(oauth認証)を実装しようと思ってハマった話。【google編】

##今回の目的
- 簡単にログインできる機能を作りたかった
- 久しぶりにSNSログイン機能の実装について復習しようと思った

軽い気持ちで実装を始めたら信じられないぐらいハマったので共有しておきます。
ちなみに紹介するのは、ログイン機能全てではありません。
ページにアクセスして認証ダイヤログから「認証ボタン」を押すと自分のIDや名前などの情報が画面に表示されるミニマムなものになりますのでご了承ください。

###■ アプリに登録する
まず、 [https://code.google.com/apis/console/](https://code.google.com/apis/console/) で新しくプロジェクトを作成します。

ページ上部にある「プロジェクトを作成」をクリックします。
すると下記のような画面が出てくるのでプロジェクトの名前を入力して「作成」を押してください。

![スクリーンショット 2017-03-31 6.49.21.png](https://qiita-image-store.s3.amazonaws.com/0/146612/bd19f25e-b168-5f3d-47fe-c0082e8db0f3.png)

### ■ 認証情報の作成
認証情報を作成することで情報取得に必要な
- クライアント ID
- クライアント シークレット
を作成することができます。

１.「Oauth同意画面」の設定をします。
サイトの名前などを入力して保存します。

![スクリーンショット 2017-03-31 8.30.34.png](https://qiita-image-store.s3.amazonaws.com/0/146612/e1a0bb86-9cf1-ef08-0a8a-e251a2249796.png)

２. 次に、「認証情報」を押すと「API 認証情報」が画面に出てくるので、「認証情報の作成」を押します。
すると、いくつか項目が出てきますので「OAuth クライアント ID」を選択して次に進みましょう。

![スクリーンショット 2017-03-31 6.58.31.png](https://qiita-image-store.s3.amazonaws.com/0/146612/49c01c6b-ccfa-02cb-86c4-e37673199427.png)

３. アプリケーションの種類について聞かれるので「ウェブアプリケーション」を選択します。
googleに情報を取得し、サイト側に返ってきた際に表示するページのURLを下記の赤い部分に入力します。

![スクリーンショット-2017-03-31-7.16.56.png](https://qiita-image-store.s3.amazonaws.com/0/146612/b7211f02-362d-8c34-ebff-c5cbbc4d28fd.png)

入力をして、「作成」を押すと下記のように「クライアント ID」と「クライアント シークレット」が作成されるのでメモしておきましょう。

![スクリーンショット 2017-03-31 7.24.37.png](https://qiita-image-store.s3.amazonaws.com/0/146612/c5cadfc6-20c9-cb47-cd2f-81c33c939c02.png)

「OK」を押すと初めの画面に戻ります。
再び確認や編集を行いたいときは、作成した認証情報がリストとして表示されているので、選択することで編集等が可能になります。

###■ 認証ページに情報を送る
実際に認証ページに先ほど取得した「クライアント ID」と「クライアント シークレット」を送信し、情報を取得しましょう。

**CONSUMER_KEY**の箇所に先ほど取得した「クライアント ID」を入力し、
**CALLBACK_URL**には情報を取得してた時に返ってくるページのURLを入力します。
（認証情報を作成する際に承認済みのリダイレクトURIに入力したURLです）

```php:index.php
<?php
// アプリケーション設定
define('CONSUMER_KEY', 'クライアント ID');
define('CALLBACK_URL', '情報を取得して返ってくるページのURL');

// URL
define('AUTH_URL', 'https://accounts.google.com/o/oauth2/auth');


$params = array(
  'client_id' => CONSUMER_KEY,
  'redirect_uri' => CALLBACK_URL,
  'scope' => 'https://www.googleapis.com/auth/userinfo.profile',
  'response_type' => 'code',
);

// 認証ページにリダイレクト
header("Location: " . AUTH_URL . '?' . http_build_query($params));
?>
```

これで実際サイトのURLに接続すると下記のように表示されるはずです。

![スクリーンショット 2017-03-31 7.40.30.png](https://qiita-image-store.s3.amazonaws.com/0/146612/7c8a13c4-764d-ec06-050d-697431ba8bb0.png)

「許可」を押すと画面が遷移して、していしたサイトページ常に自分の情報が取得できます。

![スクリーンショット 2017-03-31 8.00.02.png](https://qiita-image-store.s3.amazonaws.com/0/146612/7706a1d2-5133-c7af-009a-115fac2f1dba.png)

###■ 情報を取得する

```php:oauth.php
<?php
// アプリケーション設定
define('CONSUMER_KEY', 'クライアント ID');
define('CONSUMER_SECRET', 'クライアント シークレット');
define('CALLBACK_URL', '情報を取得して返ってくるページのURL');

define('TOKEN_URL', 'https://accounts.google.com/o/oauth2/token');
define('INFO_URL', 'https://www.googleapis.com/oauth2/v1/userinfo');

$params = array(
  'code' => $_GET['code'],
  'grant_type' => 'authorization_code',
  'redirect_uri' => CALLBACK_URL,
  'client_id' => CONSUMER_KEY,
  'client_secret' => CONSUMER_SECRET,
);

$params = http_build_query($params, "", "&");

$header = array(
  'Content-Type: application/x-www-form-urlencoded',
  'Content-Length: ' .strlen($params)
);

// POST送信
$options = array('http' => array(
  'method' => 'POST',
  'header' => implode("\r\n", $header),
  'content' => $params
));

// アクセストークンの取得
$res = file_get_contents(TOKEN_URL, false, stream_context_create($options));

// レスポンス取得
$token = json_decode($res, true);
if(isset($token['error'])){
  echo 'エラー発生';
  exit;
}

$access_token = $token['access_token'];

$params = array('access_token' => $access_token);

// ユーザー情報取得
$res = file_get_contents(INFO_URL . '?' . http_build_query($params));

//表示
echo $res;
?> 
```

上記のコードは修正済みのものになりますが実際は、
**Notice: file_get_contents(): Content-type not specified assuming application/x-www-form-urlencoded**
というエラーが表示されました。
調べると「ヘッダーの情報がない」というエラーのようなので下記を追加したら直りました。

```php:oauth.php
$header = array(
  'Content-Type: application/x-www-form-urlencoded',
  'Content-Length: ' .strlen($params)
);
```

▼修正前

```php:oauth.php
// POST送信
$options = array('http' => array(
  'method' => 'POST',
  'content' => http_build_query($params)
));
```

▼修正後

```php:oauth.php
$params = http_build_query($params, "", "&");

$header = array(
  'Content-Type: application/x-www-form-urlencoded',
  'Content-Length: ' .strlen($params)
);

// POST送信
$options = array('http' => array(
  'method' => 'POST',
  'header' => implode("\r\n", $header),
  'content' => $params
));
```

以上です。
SNSログインの実装でお役に立てれば幸いです。