Skip to content

MS_ASPNETIdentitySTSOAuth2

nishi_74322014 edited this page Aug 12, 2026 · 1 revision

ASP.NET IdentityのOAuth2によるSTS実装

概要

ASP.NET Identityの、OAuth 2.0 による
セキュアトークンサービス(STS)の Endpoint 追加実装。

準備

OAuth 2.0 Server、Client 共に以下からダウンロード可能。

  • The ASP.NET Site - OWIN OAuth 2.0 Authorization Server - Download the sample code.

このサンプルは、VS2013・2015 で、そのまま F5 実行可能で非常に便利。

検証

ダウンロードしたサンプルを使用して、以下のシナリオの検証ができる。

  • Authorization Code グラント種別(OAuth
  • Implicit グラント種別
  • Resource Owner Password Credentials グラント種別
  • Client Credentials グラント種別

補足(最新化): Implicit / ROPC は
現在使用してはならないASP.NET IdentityによるSTS実装を参照)。
学習目的でサンプルを動かす分には有用だが、
本番実装のテンプレートにしてはならない

ASP.NET IdentityでOAuth2のRFCに追加されている仕様

RFCに規定のない認証の仕掛け

  • 認証には、(基本的に)ASP.NET Identityを使用する。

  • Bearer Token の発行には、ClaimsIdentity を使用する。

  • ASP.NET MVC アプリケーションの認可エンドポイント上

    • Cookie 認証チケットから ClaimsIdentity を生成できる。

      AuthenticateResult ticket = this.AuthenticationManager
          .AuthenticateAsync(DefaultAuthenticationTypes.ApplicationCookie).Result;
      ClaimsIdentity identity = (ticket != null) ? ticket.Identity : null;
    • 以下の方法で Token を発行する。
      「Authorization Code グラント種別」では仲介トークンを、
      「Implicit グラント種別」では Access Token を生成する。

      this.AuthenticationManager.SignIn(identity);
  • OAuthAuthorizationServerProvider の Token エンドポイント上

    • ユーザ情報を使用して ClaimsIdentity を生成する。

      ClaimsIdentity identity = await userManager.CreateIdentityAsync(
                     user, DefaultAuthenticationTypes.ExternalBearer);
    • 以下の方法で Token を発行する。
      「Resource Owner Password Credentials グラント種別」
      「Client Credentials グラント種別」の両方で Access Token を生成する。

      context.Validated(identity);
  • ClaimsIdentity に Custom の情報を格納する場合、以下の様に Claim を追加する。

    identity.AddClaim(new Claim("urn:oauth:scope", scope));

補足(ここが「RFC に無い」ことの意味): OAuth 2.0 の
RFC 6749 は「トークンをどう作るか」を規定していない。
規定しているのは

  • エンドポイントの URL 構造とパラメタ名
  • グラント種別ごとのやり取りの流れ
  • エラー応答の形式

だけであり、アクセス トークンの中身は不透明(opaque)でよい

したがって「認証をどうやるか」「トークンに何を詰めるか」は
各実装の裁量になる。上記の ClaimsIdentity を使う仕掛けは、
Katana(OWIN)実装のローカル ルールである。

逆に言えば、この部分は移植性が無い
OpenIddict や IdentityServer に移ると、まったく別の書き方になる。

参考(サービス / ミドルウェア毎の仕様の違い)

技術文書中での Shall / Should / May」があるため、
サービス / ミドルウェア毎に仕様は異なってくる。以下が参考になる。

やはり、サービスによって扱いがマチマチなのは、
redirect_uri パラメタと state パラメタであるもよう。

補足(現在は締められた): この「マチマチ」は
セキュリティ上の問題を多発させたため、
RFC 9700(OAuth 2.0 Security BCP)と OAuth 2.1 で規定が厳格化された。

パラメタ 現在の規定
redirect_uri 完全一致(simple string comparison)が必須。ワイルドカード・前方一致・パス以下の可変は不可
state CSRF 対策として必須扱い(PKCE を使う場合は state の役割は遷移先の保持に寄る)
PKCE 全クライアントで必須(機密クライアントも含む)

redirect_uri の部分一致を許すと、

  • オープン リダイレクタと組み合わせて認可コードを奪える
  • サブドメイン乗っ取りで奪える

という攻撃が成立する。必ず完全一致にすること。

Bearer Tokenを暗号化・復号化する秘密鍵

  • 認可サーバ(Authorization Server)とリソースサーバ(Resource Server)が
    同じマシン上に無い場合、
    Bearer Token を暗号化・復号化する秘密鍵を双方のマシン間で一致させる必要がある。

  • これには、以下のように、machineKey を両方の Web.config ファイルに
    追加する必要がある。

<system.web>
    <machineKey decryptionKey="Enter decryption Key here"
        validation="SHA1"
        validationKey="Enter validation Key here" />
</system.web>

machineKey セクションの生成には、以下のツールが使えそう。

補足(この設計の限界): 「共通鍵でトークンを暗号化し、
リソース サーバが復号して中身を読む」という方式には、
次の制約がある。

  • リソース サーバに復号鍵を配る=トークンを偽造できる鍵を配る
    (リソース サーバが 1 つでも侵害されると全体が破れる)
  • リソース サーバが増えるたびに鍵の配布・更新が要る
  • validation="SHA1" は現在の基準では弱い(HMACSHA256 以上にする)

現在の設計では、トークンは JWS(公開鍵署名)にし、
リソース サーバは jwks_uri から公開鍵を取って検証する

のが標準である。復号鍵を配る必要がなくなる。

あるいはトークンを不透明なままにし、
**トークン イントロスペクション(RFC 7662)**で
認可サーバに毎回問い合わせる方式もある。

Bearer TokenをJWTアサーションに変更する方法

JWTとOAuth2.0を参照。

ASP.NET Identity(Identity 2.0)(net45)で通常サポートされないSTS機能

参考

The ASP.NET Site

このコンテンツは以下の様な構成になっている。

  • Download the sample code.
  • Create an Authorization Server.
  • Creating a Resource Server.
  • Create OAuth 2.0 Clients.

Download the sample code.

以下から、サンプル・コードをダウンロードできる。

http://code.msdn.microsoft.com/OWIN-OAuth-20-Authorization-ba2b8783/file/114932/1/AuthorizationServer.zip

Create an Authorization Server.

  • この Authorization Server は OAuth の 4 つのフローをサポートしている。

    • Authorization Code Grant Client
    • Implicit Grant Client
    • Resource Owner Password Credentials Grant Client
    • Client Credentials Grant Client
  • サーバーの設定と実装

    • OWIN Startup class での設定
    • OAuthAuthorizationServerProvider の実装
メソッド 対象グラント種別
ValidateClientRedirectUri Authorization Code, Implicit
ValidateClientAuthentication Resource Owner Password Credentials, Client Credentials
GrantResourceOwnerCredentials Resource Owner Password Credentials
GrantClientCredentials Client Credentials
  • AuthorizeEndpoint の実装(Authorization Code, Implicit グラント種別)

移行メモ: 元ページは GrantClientCredetails と綴られていたが、
正しいメソッド名は GrantClientCredentials である。

Creating a Resource Server.

アクセストークンによって保護された Resource Server の Endpoint を作成。

Create OAuth 2.0 Clients.

.NET クライアント・アプリから HTTP アクセスする際のライブラリとしては、
DotNetOpenAuth.OAuth2
を使用している。

クライアント 実装形態
Authorization Code Grant Client WebApplication として実装
Implicit Grant Client JavaScript で実装
Resource Owner Password Credentials Grant Client コンソール・アプリケーションで実装
Client Credentials Grant Client コンソール・アプリケーションで実装

補足: DotNetOpenAuth開発終了している。
現在の .NET クライアント実装は

  • Microsoft.Identity.Client(MSAL) — Entra ID / MSA 向け
  • IdentityModel(Duende) — 汎用の OAuth / OIDC クライアント
  • Microsoft.AspNetCore.Authentication.OpenIdConnect — Web アプリ

を使う。

関連する情報

補足(invalid_grant の定番原因): この 2 つの質問が示す通り、
Authorization Code フローで invalid_grant になる原因は限られている。

原因 内容
認可コードの二重使用 コードは一度きり。ブラウザの再読込やリトライで再送すると失敗する
redirect_uri の不一致 認可時とトークン要求時で完全に同じ文字列である必要がある(末尾スラッシュ、大文字小文字も)
コードの有効期限切れ 通常 30 秒〜数分
クライアント認証の失敗 client_secret の不一致、送信方法(Basic / body)の相違
machineKey の不一致 認可コード自体が暗号化されており、復号できない

その他のサイト

実装方法の調査で参照にしたサイト。


Tags: 移行, .NET開発, ASP.NET, ASP.NET MVC, ASP.NET Identity, OAuth, 認証基盤, セキュリティ

NetDevInfraWiki

マイクロソフト系技術情報 Wiki
Open 棟梁 Wiki

(未着手)

開発基盤部会 Wiki

移行管理: DONETODO

Clone this wiki locally