1. ホーム
  2. c#

[解決済み] ASP.NET Coreのトークンベース認証

2022-04-23 05:34:05

質問

ASP.NET Coreアプリケーションで作業しています。私はトークンベース認証を実装しようとしていますが、新しい セキュリティシステム を使用します。 私は 事例 クッキー認証や外部認証(GitHub、Microsoft、Twitter)を使っているようですが、あまり役に立ちませんでした。

私のシナリオは、angularjs アプリケーションが /token urlにユーザー名とパスワードを渡します。WebApiはユーザーを認証し access_token これは、次のリクエストでangularjsアプリによって使用されます。

現在のASP.NETのバージョンで私が必要とするものを正確に実装している素晴らしい記事を見つけました -。 ASP.NET Web API 2、Owin、およびIdentityを使用したトークン・ベース認証 . しかし、ASP.NET Coreで同じことを行う方法は私には明らかではありません。

私の質問は、ASP.NET Core WebApi アプリケーションがトークンベース認証で動作するように構成する方法ですか?

どのように解決するのですか?

.Net Core 3.1へのアップデートを行いました。

David Fowler (ASP .NET Core チームのアーキテクト) は、信じられないほどシンプルなタスクアプリケーションのセットをまとめました。 JWTのデモを行うシンプルなアプリケーション . この記事には、彼のアップデートとシンプルなスタイルを近々取り入れる予定です。

.Net Core 2に対応したアップデートを行いました。

この回答の以前のバージョンでは、RSA を使用していました。トークンを生成する同じコードがトークンの検証も行うのであれば、これは本当に必要ではありません。しかし、もしあなたが責任をもって配布しているのであれば、おそらくまだ Microsoft.IdentityModel.Tokens.RsaSecurityKey .

  1. 後で使用する定数をいくつか作成します。

    const string TokenAudience = "Myself";
    const string TokenIssuer = "MyProject";
    
    
  2. Startup.csに以下を追加してください。 ConfigureServices . これらの設定にアクセスするには、後で依存性注入を使用することになります。 私が想定しているのは、あなたの authenticationConfigurationConfigurationSection または Configuration オブジェクトを作成し、デバッグ用と本番用で異なる設定をすることができます。鍵は安全に保管するようにしましょう! 任意の文字列を指定できます。

    var keySecret = authenticationConfiguration["JwtSigningKey"];
    var symmetricKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(keySecret));
    
    services.AddTransient(_ => new JwtSignInHandler(symmetricKey));
    
    services.AddAuthentication(options =>
    {
        // This causes the default authentication scheme to be JWT.
        // Without this, the Authorization header is not checked and
        // you'll get no results. However, this also means that if
        // you're already using cookies in your app, they won't be 
        // checked by default.
        options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
    })
        .AddJwtBearer(options =>
        {
            options.TokenValidationParameters.ValidateIssuerSigningKey = true;
            options.TokenValidationParameters.IssuerSigningKey = symmetricKey;
            options.TokenValidationParameters.ValidAudience = JwtSignInHandler.TokenAudience;
            options.TokenValidationParameters.ValidIssuer = JwtSignInHandler.TokenIssuer;
        });
    
    

    他の回答では、他の設定を変更しているのを見ましたが、例えば ClockSkew デフォルトは、時計が正確に同期していない分散環境でも動作するように設定されています。変更する必要があるのは、これらの設定だけです。

  3. Authentication(認証)を設定します。を必要とするミドルウェアの前に、この行を記述する必要があります。 User のような情報 app.UseMvc() .

    app.UseAuthentication();
    
    

    この場合、トークンが SignInManager などがあります。あなたのJWTを出力するための独自のメカニズムを提供する必要があります - 下記を参照してください。

  4. を指定したい場合があります。 AuthorizationPolicy . これにより、Bearerトークンのみを認証として許可するコントローラやアクションを [Authorize("Bearer")] .

    services.AddAuthorization(auth =>
    {
        auth.AddPolicy("Bearer", new AuthorizationPolicyBuilder()
            .AddAuthenticationTypes(JwtBearerDefaults.AuthenticationType)
            .RequireAuthenticatedUser().Build());
    });
    
    
  5. ここからが厄介なところです。トークンを構築するのです。

    class JwtSignInHandler
    {
        public const string TokenAudience = "Myself";
        public const string TokenIssuer = "MyProject";
        private readonly SymmetricSecurityKey key;
    
        public JwtSignInHandler(SymmetricSecurityKey symmetricKey)
        {
            this.key = symmetricKey;
        }
    
        public string BuildJwt(ClaimsPrincipal principal)
        {
            var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
    
            var token = new JwtSecurityToken(
                issuer: TokenIssuer,
                audience: TokenAudience,
                claims: principal.Claims,
                expires: DateTime.Now.AddMinutes(20),
                signingCredentials: creds
            );
    
            return new JwtSecurityTokenHandler().WriteToken(token);
        }
    }
    
    

    そして、トークンが必要なコントローラで、以下のようなものを作成します。

    [HttpPost]
    public string AnonymousSignIn([FromServices] JwtSignInHandler tokenFactory)
    {
        var principal = new System.Security.Claims.ClaimsPrincipal(new[]
        {
            new System.Security.Claims.ClaimsIdentity(new[]
            {
                new System.Security.Claims.Claim(System.Security.Claims.ClaimTypes.Name, "Demo User")
            })
        });
        return tokenFactory.BuildJwt(principal);
    }
    
    

    ここでは、すでにプリンシパルを持っていることを想定しています。Identity を使用している場合は IUserClaimsPrincipalFactory<> を変換するために UserClaimsPrincipal .

  6. テストするために : トークンを取得し、以下のフォームに入力します。 jwt.io . 上で紹介した手順では、署名の検証に設定から得たsecretを使用することも可能です

  7. .Net 4.5のベアラのみの認証と組み合わせてHTMLページの部分ビューでレンダリングしていた場合は ViewComponent を実行します。ほとんど上のController Actionのコードと同じです。