3
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.

ASP.NET CoreのJWT認証メモ

Last updated at Posted at 2020-06-01

.NET CoreのJWT認証メモ

Jwtを使った認証周りのメモです。主にソースです。
認証そのもののメモはこちら

調べたバージョンはASP.NET Core 3.1

使い方については他で検索したら出てくるのでここでは詳しく書きません。

パッケージの準備

Microsoft.AspNetCore.Authentication.JwtBearer を追加します。
バージョンは3.1.4を使用しました。

コードのメモ

こんな感じで使います。

startup.cs
public void ConfigureServices(IServiceCollection services)
{
    //中略

    services.
        AddAuthentication(option =>
        {
            option.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
        })
        .AddJwtBearer(option =>
        {

            //JwtSecurityTokenHandler.ValidateTokenPayloadを通すためにいろいろいるみたい。
            //検証はMicrosoft.IdentityModel.Tokens.Validatorsっていう静的クラスがある

            //audienceの検証
            option.TokenValidationParameters.ValidAudiences = new string[] { "sandbox" };

            //issuerの検証
            option.TokenValidationParameters.ValidIssuers = new string[] { "epsilon" };

            //デフォルトは5分になってて、期限過ぎてもしばらくは検証を合格してしまう。
            option.TokenValidationParameters.ClockSkew = TimeSpan.Zero;

            //とりあえずテキトーな鍵
            byte[] key = Encoding.UTF8.GetBytes("1234567890123456");
            SymmetricSecurityKey securityKey = new SymmetricSecurityKey(key);
            option.TokenValidationParameters.IssuerSigningKey = securityKey;
        });
}

発行側

//payloadに含めるクレーム一覧
List<Claim> claims = new List<Claim>
{
    new Claim(ClaimTypes.Name, "Taro")
};
ClaimsIdentity claimsIdentity = new ClaimsIdentity(claims);

//署名用のキー
//TokenValidationParameters.RequireSignedTokensをfalseにすれば、署名なしでも使用可能になるがセキュリティ的にダメ
byte[] key = Encoding.UTF8.GetBytes("1234567890123456");
SymmetricSecurityKey securityKey = new SymmetricSecurityKey(key);
SigningCredentials cred = new SigningCredentials(securityKey, "HS256");

JwtSecurityTokenHandler th = new JwtSecurityTokenHandler();
JwtSecurityToken jst = th.CreateJwtSecurityToken(
    issuer: "epsilon",
    audience: "sandbox",
    subject: claimsIdentity,
    notBefore: null,//nullのときは現在時刻が使われるようだ
    expires: DateTime.Now.AddMinutes(5),//とりあえず短め
    issuedAt: null,//nullのときは現在時刻が使われるようだ
    signingCredentials: cred
    );
//このtokenをクライアントに返す
string token = th.WriteToken(jst);

登場するクラスメモ

依存しているSystem.IdentityModel.Tokens.JwtAzureAD 側で管理されているようだ

リポジトリはこちら

JwtBearerHandler

ソースはこちら

認証周りのポイントであるIAuthenticationHandler のJwtの場合の実装クラスです。

  • SingIn
  • SingOut

は実装されていないのでトークンの発行はHttpContext 経由ではなく自身で行う必要があります。

HandleAuthenticateAsync メソッド

認証情報を取り出している部分です。

イベントのMessageReceived を経由することでAuthorization ヘッダー以外からでもトークンを取り出すことができるようです。(ajaxではなくformをsubmitするような場合に使うのかな?)

イベントのリスナー登録は JwtBearerOptions から可能なはず。(試していません。)

Authorization ヘッダーが存在した場合、Bearer 以降の文字列をトークンとして扱うようです。
もしトークンが取得できなかった場合は認証情報を復元しないようです。

その後はトークンの検証が行われます。検証についてのバリデーションの設定はJwtBearerOptions.SecurityTokenValidators で行います。
デフォルトではJwtSecurityTokenHandlerのみがセットされています。

JwtSecurityTokenHandler

ソースはここ

ポイントとなるクラスかなと個人的には思っています。

  • JwtBearerHandler からは 検証、復元のために ValidateToken メソッドが呼ばれています。
  • トークンの生成のためには CreateJwtSecurityToken, WriteToken などを使用します。

ValidateToken メソッド

トークンの検証およびClaimsPrincipal の返却を行います。

トークンをピリオドで分割した後のパート数によってJWE かどうかの判別をしているようです。

署名部分の検証をValidateSignatureで行い、ペイロード部分の復元、検証をValidateTokenPayloadで行っています。

ValidateTokenPayload では文字通りペイロード部分の検証を行います

多くのものはValidatorsクラスのstaticメソッドに処理を委譲しています。

また検証の際のオプションはJwtBearerOptions.TokenValidationParametersで設定することができます。

CreateJwtSecurityToken メソッド

JwtSecurityToken を作るためのメソッドです。
いくつかオーバーロードされているので使いたいものを選べばよいと思います。

SigningCredentials を省略した場合、署名なしのトークンが作られますが、さすがにそれはセキュリティ的にアウトだと思います。

まだ私もどれが適切なのか判断できていません。

これ以外にもトークンを作るメソッドはあります。

WriteToken メソッド

JwtSecurityTokenstring にするためのメソッド

TokenValidationParameters

ソースはこちら

トークンの検証/復元において

  • 検証そのものの有効化/無効化
  • 「有効な値」と判断するものの設定

などをすることができます。

一部の物しか試せていませんが一つだけ紹介します。

ClockSkew プロパティ

TimeSpan型のプロパティでデフォルトは5分に設定されています。

Validators.ValidateLifetimeメソッドで使用されており

時間計算の際に時刻をずらすために使われているようです。

なので例えばexpires の時間を過ぎてもすぐにはトークンは無効とはならず。このClockSkewの期間だけ猶予があるようです。

終わりに

他にもたくさんのクラスが用意されているので、まだまだいろいろすることができそうです。

MSのドキュメントが見当たらないのでもしよければコメントで教えてください。

3
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
3
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?