7
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

初芋3分(本圓は12分)でAuth0を䜿ったOIDCログむンを実装するたで

7
Last updated at Posted at 2021-08-07

完党に初心者の趣味です。勀務先や所属する団䜓の掻動ずは関係ありたせん。

tl;dr

  • OpenID Connect(OIDC) でログむンする、Single Page App(SPA) もどきをNode.jsで䜜りたした。
  • 䜜ったSPAもどきで、Auth0を利甚しおみたした。サむンアップから、Auth0を䜿ったログむン完了たで、初芋で12分で終わりたした。
  • 䞀応利甚芏玄も簡単に目を通した。
  • 䞀番迷ったのは無料サむンアップたでのルヌト。
  • 䜜ったSPAもどきの解説は埌半です。
  • Google IDでログむンするための蚭定も最埌に。

詊しおみる

Google IDログむンですが、Glitchにもサンプルをアップしたした。

たずは実際に動かしおみる

Node.jsがlocalhostで動く環境が前提です。localhostじゃないずきはlocalhostっお曞いおある郚分を適圓に倉えおください

Auth0のサむンアップ

Google怜玢で「Auth0」ず入れお、広告の䞋のリンクをクリックしたす。
Google-auth0.png

広告のリンクをクリックするず、サむンアップペヌゞにたどり着きたせん。

右䞊の「無料トラむアル」をクリックしお、GitHubでも、Googleでも、奜きなアカりントでサむンアップしたす。
そういえば自分の名前すら入力しおいない気がする。

Auth0-trial.png

サむンアップが終わったら、すぐダッシュボヌドが衚瀺されたす。
右䞊の、「Create Application」をクリックしたす。

Auth0-createApp.png

適圓にアプリ名を考えおから、今回は「Regular Web Applications」を遞択したす。
倚分、ここは䜕を遞んでも倧䞈倫な気がしたす。
Auth0-createApp2.png

次の画面で、「Quick Start」が出たすが、そこは䜿わず、その隣の「Settings」タブを開き、
「Client ID」、「Client Secret」を確認したす。埌でコピペしたす。
Auth0-BasicInfo.png

䞋にスクロヌルしおいっお、「Application URIs」の䞭の、「Allowed Callback URLs」に、 http://localhost:3000/ ず入力したす。
Auth0-AppURI.png

さらに䞋にスクロヌルしおいっお、「Advanced Settings」を開きたす。
䞀番右の「Endpoints」をクリックしたす。
この䞭の、「OAuth Authorization URL」ず、「OAuth Token URL」を、埌でコピペしたす。
Auth0-endpoints.png

Node.js コヌドのダりンロヌドず蚭定

䞋蚘のレポゞトリをチェックアりトしたす。面倒なら、ここから゜ヌスのZIPを盎接ダりンロヌドしたす。

ファむルを解凍したら、タヌミナル、もしくはコマンドプロンプトでnpm install を実行したす。

凊理を埅っおいる間に、.env.exampleを゚ディタで開き、先ほどAuth0の蚭定ペヌゞで芋぀けた、
「OAuth Authorization URL」、「OAuth Token URL」、「Client ID」、「Client Secret」を、それぞれコピペしたら、.envずしお保存したす。

Auth0-editor.png

起動

node app.js を実行したす。

実際にログむンしおみる

ブラりザで、 http://localhost:3000 にアクセスしたす。

䞊から順に、1、2のボタンを抌しおいくず、Auth0のログむンペヌゞに行きたす。
Auth0-demo1.png

「Sign up」から、eメヌルずパスワヌドを入力しおログむンするこずもできたすし、デフォルトでGoogleログむンが䜿えるように蚭定されおいたす。
Auth0-demo2.png

「Accept」を抌すず、元のペヌゞに戻っおきたす。
Auth0-demo3.png

(3)を抌すず、Node.js経由で、Auth0のサヌバから、ナヌザ情報いわゆるIDトヌクンを取埗しお、その䞭身をデコヌドしお衚瀺したす。
Auth0-demo5.png

ここたで実枬12分で終わっおしたいたした。。始めたずきは、タむムアタックする぀もりなんおなかったので、終わっおから時蚈を芋おびっくりしたした。最初のサむンアップペヌゞに迷ったり、利甚芏玄を読んだりしなければ、本圓に3分で終わったんじゃないかず思いたす。

SPAもどきの䜜り方

䜜った理由

いわゆる普通のWebサむトで、GoogleやFacebook,Twitterなどを䜿った゜ヌシャルログむンを実珟する䟋はよく芋るのですが、ネむティブアプリでの゜ヌシャルログむンは、各サヌビスがSDKを提䟛しおいるため、仕組みがよくわからず、ブラックボックスになっおしたっおいる気がしたした。
なので、ネむティブアプリを䜜るのはちょっず難易床高いですが、静的なHTML+JavaScriptで、サヌバずはREST APIで通信しお、ネむティブアプリっぜく振る舞う、SPAもどきを䜜るこずで、仕組みを理解しようず思いたした。

参考にしたサむト

日本におけるOpenID Connectの重鎮のお二方のブログを参考にアヌキテクチャを考えたした。い぀もお䞖話になっおおりたす。

アヌキテクチャ

REST APIっぜく䜜りたかったので、簡単にできるNode.js + Express構成を䜿いたす。
SPA郚分は、JavaScriptも含めお1぀のHTMLファむルにしおいたす。
䜜り始めたずきは、䞀郚動的な郚分があるかなず、ejsを䜿いたしたが、結果的に完党に静的なペヌゞになっおいたす。

OpenID ConnectでSPAを䜜る堎合、むンプリシットフロヌやハむブリッドフロヌで、SPAが盎接IDトヌクンを取埗するパタヌンがよく玹介されおいる蚳ですが、IDトヌクンにもそれなりに個人情報が含たれる堎合があるこずず、実装をシンプルにするために、サヌバ、SPA間はセッションIDで管理するこずにしたした。

ログむンのフロヌはこんな感じです。(1)から(3)は、それぞれ実際のSPAもどきを䜿うずきに抌すボタンに察応しおいたす。

Auth0-OIDC-flow.png

通垞Webサむトであれば、ナヌザのログむン状態はセッションIDをCookieに保存するこずで管理したす。
ですが、ネむティブアプリを想定しお、セッションIDはAuthorizationヘッダヌに入れるこずにしたした。ブラりザ内ではlocalStorageに保存したす。

こういう蚭蚈で本圓に問題ないのかは、識者のアドバむスを頂戎したいずころです。私は初心者なので。

各凊理の解説

(1) ログむンリク゚スト

SPAは静的なHTMLで、サむトを開いた時点ではセッションIDは付䞎しおいたせん。
Ajaxで、サヌバに察しお、セッションIDの払いだしず、IDP(ID Provider:認蚌サヌバ、ここではAuth0)にログむンするためのAuthorization゚ンドポむントのURLや、パラメヌタを取埗したす。
※ ここでAuthorization゚ンドポむントのURLを取埗しおいるので、䟋えばIDPをAuth0からGoogleに切り替える堎合も、サヌバ偎の蚭定を切り替えるだけで、SPA(HTML/JavaScript)偎の修正は䞍芁になりたす。
぀いでに、SPA偎でも、CSRFから防埡するため、stateずいう乱数を生成しおおきたす。

サヌバ偎では、ここでセッションIDを払い出し、ログむンのためのPKCEコヌドを生成しお、各皮パラメヌタずずもにSPAに返华したす。
PKCEに぀いおの説明はこちら

サヌバから返っおきたセッションIDは、埌で䜿うのでlocalStorageに保存しおおきたす。
今回䜜ったSPAでは、デモ甚にセッションIDを衚瀺しおいたすが、通垞は隠しおおくべきです。

(2) ログむンペヌゞに接続

(1)でサヌバから返っおきた Authorization゚ンドポむントのURLずパラメヌタに、SPAで生成したStateをくっ぀けお、アクセスしたす。
ネむティブアプリであれば、倖郚ブラりザやCustomTab, SFSafariViewControllerやASWebAuthenticationSessionを䜿いたすが、今回はブラりザなので単玔にlocation.hrefで移動するこずにしたす。

遷移先で無事ログむンが成功するず、元のペヌゞに、ク゚リパラメヌタ「code」ず「state」が付属しお返っおきたす。
ネむティブアプリであれば、Android App LinksやUniversalLinksを䜿っおアプリに凊理を戻すこずが掚奚されたす。詳现はBCP212/RFC8252を参照しおください。
今回䜜ったSPAでは、゚ラヌ凊理は省略しおいたす。

(3) 認可コヌドずセッションID送信

SPAに認可コヌドcode )ずstateが返っおきたので、たず、stateが事前に保存しおおいた倀ず䞀臎するかを怜蚌したす。もし䞀臎しなかったら、悪意ある人からの攻撃の可胜性がありたす。
※ ずいっおも、PKCEを䜿っおいる限り、その先の凊理が成功しないのでナヌザ情報の流出などの可胜性は䜎いですが、stateを䜿わずに、codeが戻っおきたら自動でサヌバに送信しおログむンを詊みるような凊理をしおいるず、勝手にログアりトされちゃったりしかねないので、怜蚌凊理を入れおおいた方がいいず思いたす。

state が䞀臎しおいるようなら、サヌバに、認可コヌドを送信したす。その際、(1)で保存しおおいたセッションIDを、Authorizationヘッダヌに付䞎したす。

今回䜜ったSPAでは、デモのために、(3)の凊理を手動で行うようにしおいたすが、本来であれば、認可コヌドがIDPから戻っおきおから、Stateを比范し、サヌバに送る䞀連の凊理は自動で行うべきです。

認可コヌドを受信したサヌバは、セッションIDず玐付けお保存しおおいたPKCEコヌドず、クラむアントID/クラむアントシヌクレット、認可コヌドをIDP(Auth0)に察しお送信したす。
するず、IDPから、IDトヌクンが返っおきたす。

IDトヌクンをデコヌドするず、ナヌザIDsub倀)がわかるので、サヌバの䞭では、sub倀をキヌにしおナヌザを管理したす。
サヌバ内で、セッションIDず、sub倀を玐付けおデヌタベヌスに保存したら、ログむン完了です。

SPAでは、デモのため、IDトヌクンの䞭身を返华しおいたす。

(4) セッションIDの利甚

今たでの凊理で、セッションIDずナヌザが玐付いたので、セッションIDが安党に管理されおいる限り、セッションIDの送り䞻そのナヌザであるずいうこずを前提にサヌビスを提䟛したす。
今回䜜ったSPAでは、セッションIDを送るこずで、ログむン時にサヌバに保存したナヌザ情報を取埗するこずができるようにしおみたした。
詊しにブラりザをリロヌドしお、(4)のボタンを抌しおみおください。(3)を実行したずきず同じ情報が返っおくるこずが確認できたす。

Google IDでログむンしおみる。

今床は、Auth0を䜿わずに、盎接Google IDでログむンできるようにしおみたす。

Google ログむンの蚭定

Google IDでOIDCログむンを行うための蚭定は、Auth0に比べるず、少し倧倉です。
たず、Google Cloud Platformで新しいプロゞェクトを䜜りたす。

そしお、「認蚌情報」を開き、「認蚌情報を䜜成」から、「OAuthクラむアントID」を遞択したす。

GCP-createOAuth.png

するず、先に同意画面を蚭定しろず蚀われおしたいたした。蚀われたずおり、「同意画面を蚭定」をクリックしたす。
GCP-consenterror.png

User Typeは、䌁業ナヌザなどでない限り、「倖郚」しか遞択できたせん。
GCP-consent.png

アプリ名など、必芁な情報を適宜入力したす。
GCP-consent-appinfo.png

スコヌプを遞択するよう求められたすので、最䜎限```openid``だけは指定したす。
次の画面で、テストナヌザを登録するよう求められたすが、登録しなくおもログむンだけはできるようです。
GCP-scope.png

仕切り盎しお、「認蚌情報」を開き、「認蚌情報を䜜成」から、「OAuthクラむアントID」を遞択したす。

アプリケヌションの皮類は「りェブ アプリケヌション」ずしたした。
承認枈みのリダむレクトURIに、http://localhost:3000 を远加したす。
GCP-createClientID.png

「䜜成」を抌すず、「クラむアントID」ず「クラむアント シヌクレット」が衚瀺されたす。
これを、先ほどダりンロヌドしおきた、app.jsにコピペしたす。
GCP-clientsecret.png

ドキュメントを芋おも、Googleの「OAuth Authorization URL」、「OAuth Token URL」の蚭定はどこなのか、サンプル電文以倖で芋぀けるこずができたせんでした。おそらく、OIDC仕様に準拠しお、OpenID Configurationを芋ろずいうこずなんだず思いたす。(GitHubの゜ヌスコヌドは、元からGoogleの蚭定にしおありたすので、Auth0をただ詊しおみおいない堎合は、そのたたで倧䞈倫です。

GCP-editor.png

app.js
const OIDC_AUTH_ENDPOINT = "https://accounts.google.com/o/oauth2/v2/auth"
const OIDC_TOKEN_ENDPOINT = "https://www.googleapis.com/oauth2/v4/token"

Google IDでログむンしおみる。

蚭定が終わったら、node app.jsをCtrl+Cで終了しおから再起動しお、新しいタブを開いお 、http://localhost:3000に再床アクセスしお芋おください。
(1),(2),(3)ず順番にボタンを抌しおいけば、今床はGoogleのIDトヌクンの䞭身が取埗できたした。

GCP-userinfo.png

ちなみに、「新しいタブを開いお」ずお願いした理由は、冒頭で取埗したAuth0のセッションが残っおいれば、
そっち偎のセッションもちゃんず有効で、Auth0で取埗したナヌザ情報を取埗するこずができたす。
GoogleずAuth0で、iss倀が異なるのがわかるず思いたす。

Auth0-userinfo.png

セッションDBの䞭身

今回䜜ったSPAはデモなので、1぀のテヌブルですべおのデヌタを管理しおいたす。PKCEコヌドずか、ログむン終わったら消しおもいいんですけどね。
あず、DBの䞭を盎接芋お気づいたんですが、Auth0のsub倀には、|(瞊棒) が含たれおたすね。いたどきいないず思いたすが、SQLを生でいじるような人は芁泚意ですね。

% sqlite3 oidc_db.sqlite ".schema"              
CREATE TABLE session (session_id TEXT UNIQUE NOT NULL, pkce_code TEXT, subject_id TEXT, user_info TEXT, active INTEGER NOT NULL DEFAULT 1, created_at TEXT NOT NULL DEFAULT (DATETIME('now', 'localtime')));

% sqlite3 oidc_db.sqlite "select * from session"
C2WRrorCttmBOuY9g6FXbw|jp(äž­ç•¥)Gv|auth0|610e48bed3fd1200687bb379|{(äž­ç•¥)"iss":"https://oidc-for-spa.jp.auth0.com/",(äž­ç•¥)}|0|2021-08-07 18:38:58
6DvaFpPv5rVUioruwnBXxw|QU(äž­ç•¥)6L|113688351101139242200|{"iss":"https://accounts.google.com",(äž­ç•¥)}|1|2021-08-07 21:49:40

感想

OAuth / OpenID Connect ずいう暙準に準拠しお各瀟がサヌビスを提䟛しおくれおいるおかげで、最䜎限の蚭定倉曎で、各瀟のIDaaSを䜿っお、Webやアプリでのログむンが実珟できるこずがわかりたした。暙準化バンザむ。

7
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?