質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.11%

グーグル OAuthについて

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 3,299

shinoda

score 86

お世話になります。

ログイン画面などによく使われるグーグルアカウントでログインというものを実装したいのですが、調べてみても私の知識では少しハードルが高く困っています。
現状クライアントIDを作成するまででつまずいています。

今回の要件を以下に示します。

1.webアプリケーションの認証として使用する
2.アプリケーション側はphpで作成する
3.DBは使用しない

初心者のためコード込みでご教授いただければ幸いです。
以上、宜しくお願い致します。

--------------------------------------------------------------
追記致します
いろいろなサイトを参考にさせていただいて以下の様なコードを作成しましたがエラーを吐きました。正直エラーの意味がよくわからないのでご教授いただければ幸いです。

-------エラー内容-------------
401. That’s an error.

Error: invalid_client

The OAuth client was not found.
Request Details

That’s all we know.
---------------------------------

<?php
// アプリケーション設定
define('CONSUMER_KEY', 'クライアントID
');
define('CALLBACK_URL', 'http://localhost/google_connect_php/callback.php');

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


//--------------------------------------
// 認証ページにリダイレクト
//--------------------------------------
$params = array(
    'client_id' => CONSUMER_KEY,
    'redirect_uri' => CALLBACK_URL,
    'scope' => 'openid profile email',
    'response_type' => 'code',
);

// リダイレクト
header("Location: " . AUTH_URL . '?' . http_build_query($params));

<?php
// アプリケーション設定
define('CONSUMER_KEY', 'クライアントID');
define('CONSUMER_SECRET', 'クライアントシークレット');
define('CALLBACK_URL', 'http://localhost/google_connect_php/callback.php');

// 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,
);

// POST送信
$options = array('http' => array(
    'method' => 'POST',
    'content' => http_build_query($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 "<pre>" . print_r(json_decode($res, true), true) . "</pre>";
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • dojikko

    2015/10/20 02:54

    CONSUMER_KEYとCONSUMER_SECRETはもちろんダミーですよね

    キャンセル

  • shinoda

    2015/10/21 10:54

    返信遅くなって申し訳ありません。
    もちろんダミーデータですが、確かに誤解を生むかもしれませんので修正しておきます。

    キャンセル

回答 2

checkベストアンサー

0

OAuthでPOSTするときにはヘッダに
Content-Type: application/x-www-form-urlencoded
が必要だった記憶があります。

$options = array('http' => array(
    'method' => 'POST',
    'content' => http_build_query($params),
    'header' => implode("\r\n", array(
          'Content-Type: application/x-www-form-urlencoded'
    ))
));
としてみてはいかがでしょうか。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/10/30 21:12

    お世話になっております。
    返信遅くなって申し訳ありません

    ご教授いただいたコードでうまくいきました。

    >//ここマイページなどにリダイレクトする。
    →上記の部分なのですが
    header('Location: http://localhost/google_connect_php/top.html&#039;);
    exit();
    このような感じで良いのでしょうか?

    また、理解度を高めるためにお聞きしたいのですが全体的な流れとしては以下の様な感じでの認識であっていますでしょうか?
    ★印でインラインにご質問を書きます

    1.アプリケーション設定でグーグルAPIコンソールに登録されているか否かの判定

    2.登録されていれば認証ページにリダイレクト

    ★ここで認証ページに渡すのは$paramsの配列という認識でよろしいでしょうか?また、header("Location: " . AUTH_URL . '?' . http_build_query($params));
    この部分なのですが配列を文字列で送るという認識であっていますでしょうか?その際文字列で送ることで不具合はないのでしょうか?(例えば配列の中身がキャッシュ等に残って簡単に取得できてしまうなど。)

    3.渡ってきた配列の中身のIDの整合性チェック

    4.認証成功で任意のページにリダイレクト

    長文になってしまい申し訳ありません。
    以上、お付き合いいただければ幸いです。

    キャンセル

  • 2015/11/04 08:52

    >>//ここマイページなどにリダイレクトする。
    >→上記の部分なのですが
    >このような感じで良いのでしょうか?
    はい。
    念のためですが、リダイレクト先のページでは
    >//ここでsession_start()等で、セッションを作る。
    で作成したセッションを扱えるようにしてください。
    セッションの有効期限の確認等が必要かと思います。

    >1.アプリケーション設定でグーグルAPIコンソールに登録されているか否かの判定
    すみません。こちらの内容が良く分からないのですが、
    「ログインとセキュリティ」にある「アカウントに接続されているアプリ」の事でしょうか?
    訪問者側の設定に、shinoda様のサイトへの接続許可の登録がされていれば
    「○○○(shinoda様のサイト) が次の許可をリクエストしています」という画面が出ないで認証されます。
    初回訪問時はその画面が表示されるはずですが、2回目以降は表示されないはずです。
    また、こちらがその許可の有無を気にする必要はありません。Google側で表示の判断を行ってくれます。

    >2.登録されていれば認証ページにリダイレクト
    >ここで認証ページに渡すのは$paramsの配列という認識でよろしいでしょうか?
    >配列を文字列で送るという認識であっていますでしょうか?
    はい。http_build_query関数は配列をクエリ文字列に変換し、
    URLに付けて送られるようにする関数です。
    http://php.net/manual/ja/function.http-build-query.php

    >その際文字列で送ることで不具合はないのでしょうか?
    >例えば配列の中身がキャッシュ等に残って簡単に取得できてしまうなど。
    取得され悪用される場合を考えますと、CSRF(クロスサイトリクエストフォージェリー)が考えられます。
    この配列にはstateというパラメータも含める事が出来まして、
    その値にセッションに紐づけた乱数を入れておく、というのが一般的かと思います。
    具体的には、
    1、「Googleでログイン」ボタンのある画面でログイン前セッションをスタートします。
    2、「Googleでログイン」ボタンを押下された際に、そのセッションに乱数を紐づけ、その乱数をstateに入れます。
      乱数の生成と文字列への変換には、
      bin2hex(openssl_random_pseudo_bytes(128))
      http://php.net/manual/ja/function.openssl-random-pseudo-bytes.php
      http://php.net/manual/ja/function.bin2hex.php
      あたりを使うと良いかと思います。
    3、「3.渡ってきた配列の中身のIDの整合性チェック」の時に、
      stateも一緒に配列の中に格納されて戻ってくるので、
      stateに値が入っているか、セッションに紐づけた乱数と同一であるか、を確認します。
      ログイン前セッションはここで終了します。
    という順でCSRF対策が出来ると考えられます。

    >3.渡ってきた配列の中身のIDの整合性チェック
    >4.認証成功で任意のページにリダイレクト
    はい。こちらは認識されているとおりです。

    キャンセル

  • 2015/11/06 16:46

    お世話になっております。
    親切丁寧に解説、また参考ページのURLの添付ありがとうございました。

    i50様のおかげで理解することができ、実装に対する不安も減りました。
    本当にありがとうございました。

    ベストアンサーとし、クローズとさせていただきます。

    キャンセル

0

access_tokenの取得に失敗しているとか
以前にfile_get_contentsを使うとaccess_tokenの取得に失敗するような話を聞いた気がしますが..

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/10/21 11:01

    お世話になっております。

    >以前にfile_get_contentsを使うとaccess_tokenの取得に失敗するような話を聞いた気がしますが..

    →そうでしたか。私が調べていた際にそのような事例があることは出てこなかったので、もう少し調べて修正してみます

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.11%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる