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

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

新規登録して質問してみよう
ただいま回答率
85.50%
PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

Q&A

解決済

2回答

5944閲覧

グーグル OAuthについて

shinoda

総合スコア75

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

0グッド

1クリップ

投稿2015/10/19 03:31

編集2015/10/21 01:58

お世話になります。

ログイン画面などによく使われるグーグルアカウントでログインというものを実装したいのですが、調べてみても私の知識では少しハードルが高く困っています。
現状クライアント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.

index.php

1<?php 2// アプリケーション設定 3define('CONSUMER_KEY', 'クライアントID 4'); 5define('CALLBACK_URL', 'http://localhost/google_connect_php/callback.php'); 6 7// URL 8define('AUTH_URL', 'https://accounts.google.com/o/oauth2/auth'); 9 10 11//-------------------------------------- 12// 認証ページにリダイレクト 13//-------------------------------------- 14$params = array( 15 'client_id' => CONSUMER_KEY, 16 'redirect_uri' => CALLBACK_URL, 17 'scope' => 'openid profile email', 18 'response_type' => 'code', 19); 20 21// リダイレクト 22header("Location: " . AUTH_URL . '?' . http_build_query($params));

callback.php

1<?php 2// アプリケーション設定 3define('CONSUMER_KEY', 'クライアントID'); 4define('CONSUMER_SECRET', 'クライアントシークレット'); 5define('CALLBACK_URL', 'http://localhost/google_connect_php/callback.php'); 6 7// URL 8define('TOKEN_URL', 'https://accounts.google.com/o/oauth2/token'); 9define('INFO_URL', 'https://www.googleapis.com/oauth2/v1/userinfo'); 10 11 12//-------------------------------------- 13// アクセストークンの取得 14//-------------------------------------- 15$params = array( 16 'code' => $_GET['code'], 17 'grant_type' => 'authorization_code', 18 'redirect_uri' => CALLBACK_URL, 19 'client_id' => CONSUMER_KEY, 20 'client_secret' => CONSUMER_SECRET, 21); 22 23// POST送信 24$options = array('http' => array( 25 'method' => 'POST', 26 'content' => http_build_query($params) 27)); 28$res = file_get_contents(TOKEN_URL, false, stream_context_create($options)); 29 30// レスポンス取得 31$token = json_decode($res, true); 32if(isset($token['error'])){ 33 echo 'エラー発生'; 34 exit; 35} 36$access_token = $token['access_token']; 37 38 39//-------------------------------------- 40// ユーザー情報を取得してみる 41//-------------------------------------- 42$params = array('access_token' => $access_token); 43$res = file_get_contents(INFO_URL . '?' . http_build_query($params)); 44echo "<pre>" . print_r(json_decode($res, true), true) . "</pre>";

気になる質問をクリップする

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

dojikko

2015/10/19 17:54

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

2015/10/21 01:54

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

回答2

0

ベストアンサー

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

php

1$options = array('http' => array( 2 'method' => 'POST', 3 'content' => http_build_query($params), 4 'header' => implode("\r\n", array( 5 'Content-Type: application/x-www-form-urlencoded' 6 )) 7));

としてみてはいかがでしょうか。

投稿2015/10/21 04:08

i50

総合スコア227

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

shinoda

2015/10/22 10:16

お世話になっております。 ご回答の通りやってみましたが、やはり同じエラーが出ました
i50

2015/10/23 00:00

すみません。エラーをよく見てみますと、 The OAuth client was not found. こちらのエラーは文字通りclient_idが間違っているエラーのようです。 client_idは xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.apps.googleusercontent.com という感じの文字列かと思いますが、最後まで入っていますでしょうか? また、念のためではありますが、 define('CONSUMER_KEY', 'クライアントID '); と、改行が入っているようですが、実際のソースでは改行しないでください。
shinoda

2015/10/23 02:44

お世話になっております。 結果から申しますとうまく動きました。 >また、念のためではありますが、define('CONSUMER_KEY', 'クライアントID ');と、改行が入っているようですが、実際のソースでは改行しないでください。 →クライアントID等は間違えていなかったのでどうやらここが悪さしていたみたいです。 このコードではユーザー情報を配列で返してきていますが、実際に使うときは自分のページのログイン画面に「グーグルアカウントでログイン」のようなボタンを設けて、そちらで認証したら自分のページにリダイレクト(ログイン画面から先のトップ画面)に遷移するというのが自然かと思いますが単純にarray部分を削除すればよいのでしょうか? すごく初歩的なことで申し訳ないのですがご教授いただければ幸いです。
i50

2015/10/23 10:16

>単純にarray部分を削除すればよいのでしょうか? こちらがどの部分を指していらっしゃるか、はっきりつかめませんが //-------------------------------------- // ユーザー情報を取得してみる //-------------------------------------- 以下を削除して、実際のページにリダイレクトとする、 という形になるのではないかと思います。 しかし実装の方針として、 いきなりアクセストークンを使用されようとしてのるのが、若干気になります。 基本的にアクセストークンは、ここでいうGoogleでのプロフィールやメアド等々を取得する為のトークンです。 具体的には、 'scope' => 'openid profile email', このscopeで指定したprofileとemailを取得するためのトークンです。 認証のみでGoogleのサービスを使うなら 'scope' => 'openid', で十分かと思われます。 そうなりますと、scopeで指定したopenidで何をするか?という事になるのですが、 これで認証の最終チェックを行うものと考えています。 この認証の最終チェックをもって認証完了とし、 サイト独自のセッションを発行してサイトへのサービス要求を認可し、 自分のページにリダイレクトさせるという流れになるかと思います。 具体的には、 --------------------------------------------------------------------- // レスポンス取得 $token = json_decode($res, true); if(isset($token['error'])){ echo 'エラー発生'; exit; } $id_token = $token['id_token']; if(!isset($token['id_token'])){ //認証失敗 } $params = array('id_token' => $token['id_token']); $res = file_get_contents('https://www.googleapis.com/oauth2/v1/tokeninfo' . '?' . http_build_query($params), false, null); $tokeninfo = json_decode($res, true); if(!isset($tokeninfo['issuer']) || !isset($tokeninfo['issued_to']) || !isset($tokeninfo['audience']) || $tokeninfo['issuer'] != 'accounts.google.com' || $tokeninfo['issued_to'] != CONSUMER_KEY || $tokeninfo['audience'] != CONSUMER_KEY){ //認証失敗 } //認証成功 //ここでsession_start()等で、セッションを作る。 //ここマイページなどにリダイレクトする。 --------------------------------------------------------------------- こんな感じになるかと思います。
shinoda

2015/10/30 12:12

お世話になっております。 返信遅くなって申し訳ありません ご教授いただいたコードでうまくいきました。 >//ここマイページなどにリダイレクトする。 →上記の部分なのですが header('Location: http://localhost/google_connect_php/top.html'); exit(); このような感じで良いのでしょうか? また、理解度を高めるためにお聞きしたいのですが全体的な流れとしては以下の様な感じでの認識であっていますでしょうか? ★印でインラインにご質問を書きます 1.アプリケーション設定でグーグルAPIコンソールに登録されているか否かの判定 2.登録されていれば認証ページにリダイレクト ★ここで認証ページに渡すのは$paramsの配列という認識でよろしいでしょうか?また、header("Location: " . AUTH_URL . '?' . http_build_query($params)); この部分なのですが配列を文字列で送るという認識であっていますでしょうか?その際文字列で送ることで不具合はないのでしょうか?(例えば配列の中身がキャッシュ等に残って簡単に取得できてしまうなど。) 3.渡ってきた配列の中身のIDの整合性チェック 4.認証成功で任意のページにリダイレクト 長文になってしまい申し訳ありません。 以上、お付き合いいただければ幸いです。
i50

2015/11/03 23: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.認証成功で任意のページにリダイレクト はい。こちらは認識されているとおりです。
shinoda

2015/11/06 07:46

お世話になっております。 親切丁寧に解説、また参考ページのURLの添付ありがとうございました。 i50様のおかげで理解することができ、実装に対する不安も減りました。 本当にありがとうございました。 ベストアンサーとし、クローズとさせていただきます。
guest

0

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

投稿2015/10/19 18:09

dojikko

総合スコア3939

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

shinoda

2015/10/21 02:01

お世話になっております。 >以前にfile_get_contentsを使うとaccess_tokenの取得に失敗するような話を聞いた気がしますが.. →そうでしたか。私が調べていた際にそのような事例があることは出てこなかったので、もう少し調べて修正してみます
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問