Django django-rest-auth + Nuxt.js auth-module で作る SPA JWT OAuth ログインシステム その1
2020.06.07
この記事は最終更新日から1年以上が経過しています。
どもです。
今回は、Django(django-rest-auth)と、Nuxt.jsを使って、SPAサイト(マイクロサービス)における、OAuth認可の仕組みを使ってJWTログインの仕組みを作って行きましょう。
という事で、どういう事?と思っている方も少なくないかと思われますので、端的に説明させて頂きます。
まずフロント、サーバー等の構成は以下の様な感じとなります。
SPAなどマイクロサービスにおけるよくある構成かと思います。
フロントエンドにNuxt.js、サーバーサイドにdjango、OAuthプロバイダーサーバーと言った構成となります。
これは、フロントエンドがReactでもAngularでも、バックエンドサーバがRailsでも、SpringBootでも違いはありません。
OAuth認証認可フレームワークを用いた、ソーシャルログインを実装しようとすると、色んな形がありますが、上記の様な構成の場合は、OAuth2.0、OIDC(Open ID Connect)での、マルチプルレスポンスタイプである、ハイブリッドフローでの実装が最適なOAuthグラントタイプだと考えます。
OAuth 2.0 Multiple Response Type Encoding Practices
https://openid.net/specs/oauth-v2-multiple-response-types-1_0.html
モノリシックな構成の時とは異なり、SPA構成ではフロント側での画面遷移の処理が行われます。
フロントエンド側にOAuthログインの為、コンフィデンシャルであるプロバイダーのシークレットキー等を保持することは、安易にシークレット情報漏洩させる形となりますので、コンフィデンシャルクライアントであるdjango側にシークレットキーを保持し、フロント、サーバーと両方で認証(検証)を行う形となります。
今回は、このSPAとコンフィデンシャルクライアント構成の場合、最適と思われるハイブリッドフローを用いて、認証認可にJWTを用いて実装を行っていきたいと思います。
ここで、軽く OAuthフロー等をまとめてみたいと思います。
OAuthおさらい
OAuth ロール
名称 | 概要 |
---|---|
リソースオーナー(ユーザー) | ユーザーのデータの所有者。
サービス上で、画像や動画アップロード後、閲覧編集できるユーザー。 |
クライアント | 上記の保護されたリソースにアクセスできるアプリケーション。web、ネイティブアプリ問わず。 |
認可サーバー | リソースオーナーの認証、クライアントのリソースアクセスの許可、アクセストークン発行などを担う。 |
リソースサーバー | 画像や動画などの機能を提供するサービス。
リソースオーナーがアクセスを許可し、主にアクセストークンを用いてリソースにアクセスする。 |
OAuthのロール(登場人物)は主に4つ。
詳細は割愛させてもらいます。
グラントタイプ
名称 | 概要 |
---|---|
認可コードグラント | コンフィデンシャルクライアントに最適化されたグラントタイプ。 |
インプリシットグラント | 非推奨。
パブリッククライアントのためのグラントタイプ。 認可コードグラント+PKCEを推奨されている。 |
クライアントクレデンシャルグラント | クライアントと認可サーバー間だけのやり取りのグラントタイプ。 |
リソースオーナーパスワードクレデンシャルグラント | リソースサーバー及び認可サーバーとクライアンと提供が同じの場合のグラントタイプ。 |
ハイブリッドフロー | インプリシットフローと認可コードフローのハイブリッドなフロー。 |
ここで、まず注目するところは「インプリシットグラント」でしょう。
パブリッククライアント。つまりwebアプリケーションやネイティブアプリケーション向けのためのグラントタイプではありますが、非推奨となっております。
非推奨となった理由としまして、アクセストークンがリダイレクトでクライアントに受け渡されるため、漏洩や置き換えのリスクが生じるのが主な理由となってます。
そのため、置き換えを防ぐためSender-Constrainedアクセストークンを用いる方法も提示されていますが、webやネイティブアプリなどクライアントIDやクライアントシークレットをセキュアに保存できない、パブリッククライアントには適応できず、認可コードグラント+PKCEを用いたフローが推奨されております。
OAuth 2.0 Security Best Current Practice
PKCE(Proof Key for Code Exchange)は、OAuthの拡張仕様(RFC7636)で、定義されている仕様で、パブリッククライアント、ネイティブアプリでのOAuthを利用する場合の脆弱性を防ぐ仕組みとなっております。
PKCEは、code_verifierやcode_challengeを用いて検証するフローとなりますが、詳細に関しては他の有志たちなどがネットなどにアッ
プされていて、多くの解説もあることと、今回OAuth認証フローの解説ではなく実装に関する解説ということもあって割愛させて頂きます。
それと、今回Djangoでのサーバーサイドがあり、コンフィデンシャルクライアントが存在するのもあって、別のフローを検討していきます。
OpenID connect(OIDC)
という訳で、OAuth認証に関して見てきましたので、OpenID connect(OIDC)も見ていきたいと思います。
OpenID connect(OIDC)は、OAuthの拡張されたもので、IDトークンとUserInfoエンドポイントが加えられた仕組みとなります。
OpenID connect(OIDC) ロール
名称 | 概要 |
---|---|
エンドユーザー | OAuthでのリソースオーナーに相当。
OIDCでは、リソースの概念がないので単にエンドユーザーとなる。 |
リライング・パーティー | OAuthでのクライアントに相当。 |
IDプロバイダ | OAuthでの認可サーバーに相当。
OIDCでは、IDトークン、アクセストークンを発行するものはIDプロバイダとなる。 |
UserInfoエンド | OAuthでのリソースサーバーに相当。
OIDCで提供されるリソースはプロフィール情報のみとなるため、UserIfoエンドポイントが定義されている。 |
scopeに「openid」を指定することによって、OIDCでのシーケンスを開始することを宣言します。
よって、OIDCではscopeにopenidの指定が必須となります。
フロー
名称 | 概要 |
---|---|
認可コードフロー | コンフィデンシャルクライアントに最適化されたフロー。 |
インプリシットフロー | パブリッククライアントのためのフロー。 |
ハイブリッドフロー | インプリシットフローと認可コードフローのハイブリッドなフロー。 |
OpenID connect(OIDC)では、グラントタイプと呼ばれていたものがフローとして呼ばれております。
また、クライアントクレデンシャルグラントや、リソースオーナーパスワードクレデンシャルグラントなどに該当するものがなく3つとなっております。
と、OAuthグラントタイプでもあった「ハイブリッドフロー」について見ていきます。
ここで、ようやく冒頭のOAuth 2.0 Multiple Response Typeに関してのお話となります。
OAuth 2.0 Multiple Response Type Encoding Practices
https://openid.net/specs/oauth-v2-multiple-response-types-1_0.html
GET /authorize? response_type=id_token%20token &client_id=s6BhdRkqt3 &redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb &state=af0ifjsldkj HTTP/1.1 Host: server.example.com
ハイブリッドフローとは?
ハイブリッドフローはインプリシットフローと認可コードフローのハイブリッドなフローてとなります。
パブリッククライアント(今回でいうとNuxt.js)とコンフィデンシャルクライアント(今回でいうとDjango)の両方で構成されているクライアントに主に利用されます。
フローの切り替えは認証リクエストに含まれる「response_type」の値として「code」「token」「id_token」を複数指定することによって切り替えることができ、認証レスポンスに含まれるトークンも変化されます。
指定方法と、フローの切り替えは以下の通りとなります。
response_type とフロー
response_type | フロー |
---|---|
code | 認可コードフロー |
id_token | インプリシットフロー |
id_token token | インプリシットフロー |
code id_token | ハイブリッドフロー |
code token | ハイブリッドフロー |
code id_token token | ハイブリッドフロー |
実装するresponse_type とフローとシーケンス
と、言うわけで、ざっくりとOAuthとOIDCに関しておさらいをしてきました。
そこで、今回実装するresponse_typeとフローは、上記の表の
「code token」のハイブリッドフロー となります。
フロントエンドにNuxt.js、サーバーサイドにdjangoを用いた簡易なシーケンスは以下の通りとなります。
こうすることによって、シークレット情報漏洩させることなくSPAサイトでのOAuth認証ログインの仕組みが作れそうです。
と、ちょっと長くなりそうなので、続きは次回にしたいと思います。
まず、次回はDjango側の実装から進めて行きたいと思います。
ではではぁ。
続きはこちら、
Django django-rest-auth + Nuxt.js auth-module で作る SPA JWT OAuth ログインシステム その2