MS_OAuthExternalLoginResearch - NetDevInfraWGinOSSConsortium/NetDevInfraWiki GitHub Wiki
- 戻る(OAuth 2.0)
- OAuthによる外部ログイン(認証)の研究
- ASP.NET Identityの外部ログイン
- OAuth 2.0 セキュリティ関連トピック
- 外部ログイン(認証)の仕様の調査。
- 前提知識に、OAuth 2.0 の知識を要する。
外部ログインは、OAuth 2.0「Authorization Code グラント種別」の拡張仕様になる。
-
通常、OAuth 2.0では、Redirect エンドポイントには、仲介コードが返り、
仲介コードをサーバ側で Access Token に変換した後、Resources Server へアクセスし、
必要な Resources(ここでは認証されたユーザのクレーム)を取り出して返すと言う流れになる。 -
しかし、外部ログインでは、Redirect エンドポイントに直接、このクレームが返る
(外部ログイン・ライブラリ上で、仲介コード → Access Token → クレームへの変換処理をしている)。
補足(「直接返る」ように見える理由): 正確には、
ライブラリが Redirect エンドポイントの内部で
仲介コード → Access Token → クレームまで一気に処理しているため、
アプリケーション側のコールバックから見ると
「クレームが直接返ってきた」ように見える、という意味である。
プロトコル上の往復が省略されているわけではない。
動作を分析した所、
-
実際の Redirect エンドポイントは、
http://localhost:nnnnn/signin-microsoft -
アプリケーションの Callback のエンドポイントが、
/Account/ExternalLoginCallback
となっている。
HTTPS のため、仲介コード → Access Token の、Response を確認できず、
OpenID Connectで実装されてる可能性もあると考えたが、
scope パラメタに「openid」の値を確認できなかったので、
OAuth 2.0 拡張と思われる。
補足(現在は OpenID Connect): 本調査の当時(ASP.NET Identity +
Microsoft.Owin.Security.MicrosoftAccount)は、Microsoft アカウントの
外部ログインが OAuth 2.0 ベースで実装されていた。
現在の ASP.NET Core(Microsoft.AspNetCore.Authentication.MicrosoftAccount、
および Microsoft Entra ID 向けのMicrosoft.Identity.Web)は
OpenID Connect ベースで、scopeにopenidを含み、
ID トークンを受け取って検証する。
「openidが無いので OAuth 2.0 拡張と思われる」という本文の推論は、
当時の実装については妥当である。
仲介コード → Access Token → クレームへの変換処理を行っている模様。
-
GET http://localhost:nnnnn/signin-microsoft?code=AAAAA&state=BBBBB HTTP/1.1 -
Cookie:
ASP.NET_SessionId=XXXXX__RequestVerificationToken=YYYYY.AspNet.Correlation.Microsoft=ZZZZZ1
この時点で情報は全て、.AspNet.ExternalCookie に同梱されるもよう。
(恐らく、クレームなどの情報の露見を防ぐためと思われる)
-
GET http://localhost:nnnnn/Account/ExternalLoginCallback HTTP/1.1 -
Cookie:
ASP.NET_SessionId=XXXXX__RequestVerificationToken=YYYYY.AspNet.ExternalCookie=ZZZZZ2
認証後、遷移元へ遷移した後には、外部ログインの形跡は綺麗に消えている。
-
GET http://localhost:nnnnn/ HTTP/1.1 -
Cookie:
ASP.NET_SessionId=XXXXX__RequestVerificationToken=YYYYY.AspNet.TwoFactorRememberBrowser=ZZZZZ3.AspNet.ApplicationCookie=ZZZZZ4
補足(Cookie の役割): 上記 3 段で現れる Cookie は、それぞれ役割が異なる。
Cookie 役割 寿命 .AspNet.Correlation.<Provider>stateの検証用(CSRF 対策)認可リクエスト〜Redirect の間 .AspNet.ExternalCookie外部 IdP から得たクレームの一時受け渡し Callback 〜 サインインの間 .AspNet.ApplicationCookie自アプリのサインイン状態 セッション/永続 「遷移後、直ちに削除している」のは上 2 つで、
最終的に残るのは自アプリの.AspNet.ApplicationCookieだけになる。
以下をライブラリ内で処理することで、セキュリティを高くしている。
-
外部ログインを、ライブラリ内部で処理して、
- ユーザの実装ミスによる仲介コード、Access Token 等の露見を防いでいる。
- 長目の RequestVerificationToken 値を使用している。
-
Redirect エンドポイント→ Callback のエンドポイント間で、
- 仲介コード、Access Token 等が露見しないよう、エンドポイントを 2 段構成にしている。
- エンドポイント間のインターフェイスに Cookie(ExternalCookie) を使用し、遷移後、直ちに削除している。
補足(2 段構成の意味):
signin-microsoftを
ライブラリ専用の受け口にしてアプリのコードを一切通さないことで、
仲介コードや Access Token がアプリ側のログ・リファラ・例外画面に
漏れる経路を断っている。
これは OAuth 2.0 Security Best Current Practice の
「HTTP リファラからの code 漏洩」への対策と同じ発想である。
- 本 Wiki 内
Tags: IT国際標準, 認証基盤, ASP.NET Identity, OAuth