皆さん、こんにちは。
最近は、原文で仕様を確認することの大切さを実感している中野です。
今回は、担当するWebアプリでOpenID Connectを使ってユーザー認証に対応することになったが、Webで調査した情報では本質がつかめず、実際に動かして確認したいと考えたエンジニアの方向けの内容です。
準備
今回はYahooさんにお世話になります。
使われるシーンを具体的に再現させるため、YahooIDを2つ作ってください。
既にお持ちであれば、もう一つ追加して作りましょう。
1つ目のYahooIDは、Webアプリ提供者のつもりです。
Yahooディベロッパーにログインし、アプリケーションを登録しましょう。
・アプリケーションの種類:サーバサイド
・サイトURL:http://localhost:3000(任意)
サイトURLは認証が終わって、リダイレクトされるURLになります。
このタイミングで、指定したURLでWebサーバーを起動させましょう。
私はNode.jsのExpressで簡易なWebサーバを作りました。
アプリケーションの登録が終わると、client_idが発行されます。
client_idは後で使用するので、メモしておいて下さい。
OpenIDを認証する
id_tokenを取得する
Yahooの公式ドキュメント:Yahoo! ID連携 v2:Authorizationエンドポイントを参考にブラウザ経由でGETを投げてみましょう。
https://auth.login.yahoo.co.jp/yconnect/v2/authorization? response_type=id_token &client_id={メモしておいたclient_id} &redirect_uri=http://localhost:3000 &state=xxx &scope=openid &nonce=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
GETを投げると、OpenIDの認証(今はYahooへのログイン)が終わっていない場合は、
Yahooのログイン画面が出てきます。
ここでは、2つ目のYahooIDを 入力しましょう。
2つ目のYahooIDはWebアプリの利用者のつもりです。
OpenIDの認証が終わると、アプリケーションの登録時に指定したサイトURLにリダイレクトされ
http://localhost:3000/#state=xxx&id_token=eyJ0eXAiOiJKV1QiL…
という形で、レスポンスが返ってきます。
このままではなんのことやらなので、id_tokenを
JWT形式をデコードをしてくれるサイト:jwt.ioで変換してみましょう。
Encodedの欄に、id_tokenを貼り付けてみましょう。
そうすると、
HEADER { "typ": "JWT", "alg": "RS256", "kid": "0cc175b9c0f1b6a831c399e269772661" } PAYLOAD { "iss": "https://auth.login.yahoo.co.jp/yconnect/v2", "sub": "************************", "aud": [ "*****************************************" ], "exp": 1520434733, "iat": 1518015533, "amr": [ "pwd" ], "nonce": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }
このような情報になっていたことがわかりました。
id_tokenはOpenIDを認証するプロバイダーが、このユーザーはこのような人ですと証明してくれている情報になります。
OpenIDの世界では、PAYLOADのsubが、一意なキーになっており、ユーザ識別子として使用されています。
access_tokenを取得する
id_token以外にOpenIDでは、access_tokenなるものが出てきます。
access_tokenは、プロバイダーへアクセスするための鍵になります。
以下のGETを行って下さい。
https://auth.login.yahoo.co.jp/yconnect/v2/authorization? response_type=token+id_token &client_id={メモしておいたclient_id} &redirect_uri=http://localhost:3000 &state=xxx &scope=openid &nonce=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
そうすると、
http://localhost:3000/#state=xxx&access_token=7CxG8xJkno22k…
という形で、レスポンスが返ってきました。
access_tokenを使用してユーザー情報を取得する
では、取得したaccess_token使用して、ユーザー情報を取得してみましょう。
Yahooの公式ドキュメント:属性取得API(UserInfoAPI)に、仕様が記載されています。
これに従って、以下を投げてみましょう。
https://userinfo.yahooapis.jp/yconnect/v2/attribute? access_token={取得したaccess_token}
そうすると、
{"sub":"************************", "name":"\u4e2d\u91ce\u5065\u4e00", "given_name":"\u5065\u4e00", "given_name#ja-Kana-JP":"\u30b1\u30f3\u30a4\u30c1", "given_name#ja-Hani-JP":"\u5065\u4e00", "family_name":"\u4e2d\u91ce", "family_name#ja-Kana-JP":"\u30ca\u30ab\u30ce", "family_name#ja-Hani-JP":"\u4e2d\u91ce", "gender":"male", "locale":"ja-JP", "birthdate":"1976", "zoneinfo":"Asia\/Tokyo"}
という結果が返ってきました。
これで、Yahooに登録済みのユーザー名称も取得できました。
これにより、Webサービスにログインすると、ユーザー情報を表示することも可能になる訳です。
ここまでの話で、サービス利用者は自身のOpenIDアカウントのみで事足りるようになっている、ということが理解できたのではないでしょうか?
また、サービス提供者にとっては、オンボーディングを成功させるため、OpenID Connectに対応することは必須条件になっていると思います。
ひいては、エンジニアにとっても、ですね。
では、今回はこの辺でー。