JavaScriptでGoogleアカウントOpenID Connect認証
Node.js+Expressでタスク管理アプリを作りました。
github: bbpink/node-shpapad · GitHub
作った背景
- もともとshpapadというタスク管理アプリを自作して使用していた
- 2015年7月にGAEのMaster/Slave Datastoreがサービス終了し、アクセスできなくなってしまった(shpapadはこれを使っていた)
- GAE特有のスピンアップ時間によるもっさり感がつらかった
- 規模はデカくないしリソースが空いてるVPSにRailsかExpressで速攻作りなおすか → 気分でNode.js+Express
実装の勘所(1) GoogleアカウントでOpenID Connect認証
まずGoogleでデベロッパ登録をしたら、OpenID Connectをするためだけのプロジェクトを作成します。プロジェクト情報を参照して「OAuthクライアントID」と「クライアントシークレット」の2つを入手すれば実装前の準備は完了。(この記事を見ながらやった気がします)
認証の流れは、
- リダイレクト先URLをパラメタに積んだGoogleドメインへのリンクをユーザがポチッ
- 飛んだ先のGoogleドメイン内で、shpapadから要求されている権限をユーザが許可
- 1で通知したリダイレクト先URL(shpapadドメイン)にリダイレクトされる
です。
リダイレクト先URL
shpapadではログイン用のAタグが以下のように書かれています。
非常に長い...........
ここではGoogle公式ドキュメントを参考にして、5つのGETパラメタを設定しました。
- client_id : 前述したOAuthクライアントID
- response_type : "code"を指定します。(requiredなのになぜかcodeしか指定できない)
- scope : ドキュメントを参照。shpapadではOpenID Connect認証をするだけなので"openid"だけを指定しています。
- redirect_uri : 前述したshpapad側に帰ってくるためのリダイレクト先URL。
- state : CSRF対策用の、shpapadサーバで発行したランダム文字列。
ユーザによる権限の承認
飛んだ先のGoogleドメイン内で、ユーザはアプリから要求されている権限が妥当であるか、そして承認するかどうかを判断します。
shpapadでは認証するだけなので"openid"のみを指定していますが、アプリケーションでメールアドレス等が必要な場合、リクエストパラメタのscopeに要求する権限を追加しておくと良いみたいです。
リダイレクトされたら
リダイレクト先URLにパラメタ付きでリクエストが飛んでくるので、サーバ側で受け取ります。
12行目まではリクエストパラメタに渡したstateの値の返却値チェックをしています。
shpapadではセッションに保存してあった値との照合をしています。
14行目からの流れは、
- リダイレクト先URLへのリクエストパラメタを取り出す
- 取り出したパラメタを使ってGoogleへトークンを要求
- 取得したトークンを使ってユーザ情報を取得
です。
shpapadでは、内部のユーザIDを生成するための元データである、Googleのuser_idを取得しています。
ユーザ情報を取得する際、レスポンスボディが少し長い時があって、19行目からの「response.on("data" .....」を使って連結しておかないとしくじる場合がありました。
続く!
P.S. 見たまま編集だとソースコードかけないのね.....