web-dev-qa-db-ja.com

ASP.NET Core 2.0 JWT検証が「ユーザーの認証に失敗しました:(null)」エラーで失敗する

ASP.NET Core 2.0アプリケーション(Web API)をJWT発行者として使用して、モバイルアプリで消費可能なトークンを生成しています。残念ながら、このトークンはあるコントローラーでは検証できませんが、別のコントローラーでは検証できます(同じasp.netコア2.0アプリ内で同じ検証設定を使用)。

したがって、有効でデコード可能なトークンがあり、必要なクレームとタイムスタンプがすべて含まれています。しかし、あるエンドポイントはそれを受け入れ、別のエンドポイントは401エラーとデバッグ出力を提供します。

Microsoft.AspNetCore.Authorization.DefaultAuthorizationService:情報:ユーザーの認証に失敗しました:(null)。

[40m[32minfo[39m[22m[49m: Microsoft.AspNetCore.Authorization.DefaultAuthorizationService[2]
      Authorization failed for user: (null).
Microsoft.AspNetCore.Authorization.DefaultAuthorizationService:Information: Authorization failed for user: (null).
[40m[32minfo[39m[22m[49m: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[3]
      Authorization failed for the request at filter 'Microsoft.AspNetCore.Mvc.Authorization.AuthorizeFilter'.
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Information: Authorization failed for the request at filter 'Microsoft.AspNetCore.Mvc.Authorization.AuthorizeFilter'.
Microsoft.AspNetCore.Mvc.ChallengeResult:Information: Executing ChallengeResult with authentication schemes ().
[40m[32minfo[39m[22m[49m: Microsoft.AspNetCore.Mvc.ChallengeResult[1]
      Executing ChallengeResult with authentication schemes ().
[40m[32minfo[39m[22m[49m: Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler[12]
      AuthenticationScheme: Bearer was challenged.
Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler:Information: AuthenticationScheme: Bearer was challenged.
[40m[32minfo[39m[22m[49m: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
      Executed action MyController.Get (WebApi) in 72.105ms
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Information: Executed action MyController.Get (WebApi) in 72.105ms
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request finished in 271.077ms 401 
[40m[32minfo[39m[22m[49m: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
      Request finished in 271.077ms 401 

私の検証設定は次のとおりです。

var secretKey = Configuration["Authentication:OAuth:IssuerSigningKey"];
var signingKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(secretKey));
var tokenValidationParameters = new TokenValidationParameters
{
   ValidateIssuerSigningKey = true,
   IssuerSigningKey = signingKey,
   ValidateIssuer = true,
   ValidIssuer = Configuration["Authentication:OAuth:Issuer"],
   ValidateAudience = true,
   ValidAudience = Configuration["Authentication:OAuth:Audience"],
   ValidateLifetime = true,
   ClockSkew = TimeSpan.Zero,
};

services.AddAuthentication(options =>
{
   options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
   options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
   options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(options =>
{
    options.RequireHttpsMetadata = false;
    options.TokenValidationParameters = tokenValidationParameters;
});

これらの2つのエンドポイントは同一であり、異なるコントローラーにのみ存在し、両方ともAuthorize属性でマークされています。

そんなことがあるものか?

37
Alexey Strakh

Configure関数のaddステートメントのシーケンスは重要です。確認してください

app.UseAuthentication();

前に来る

app.UseMvc();

これが問題だったのでしょうか?

90
Ole Lindstad

追加した場合、startup.cs ConfigureServicesメソッドで

services.AddAuthentication(options =>
            {
                options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
            }).AddJwtBearer(options => ...

説明:コントローラで[Authorize]を使用すると、デフォルトで最初の認証システムにバインドされます。

options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;

これにより、デフォルトをJWT Bearer認証に設定します。

さらに追加できます

options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;

この行は、JWTでIdentityを使用するときに404 not foundエラーが発生するのを防ぐ方法です。 IDを使用している場合、DefaultChallengeSchemeはログインページにリダイレクトしようとしますが、存在しない場合は、不正な401ではなく404が見つかりません。 DefaultChallengeSchemeをJwtBearerDefaults.AuthenticationSchemeに無許可で設定することにより、ログインページへのリダイレクトを試行しなくなります。

[Authorize]タグでCookie認証とJWT認証を使用している場合、どのauthenticationSchemeを使用するかを指定できます。例えば

[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
12
Kevin

追加した:

app.UseAuthentication();

Startup.Configure()で、このエラーを解決しました。

参照: Auth 2.0移行のお知らせ

6
spottedmahn

startup.csでこれを試してください

services.AddAuthentication(options =>
        {
            options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
            options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
        }).AddJwtBearer(opts => ...
2
user1508188

認証が次のように追加される場合:

  services.AddAuthentication(options => {
            options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
            options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
            options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
        })
        ....

これは、メソッドまたはコントローラークラスの上に置かれるすべての属性[Authorize]が、デフォルトの認証スキーマ(この場合はJwtBearer)に対して認証を試みることを意味しますAND IT WILL NOT CASCADE DOWN宣言される可能性のある他のスキーマ(Cookieスキーマなど)で認証しようとします。 AuthorizeAttributeをCookieスキーマに対して認証させるには、次のように指定する必要があります

[Authorize(AuthenticationSchemes = CookieAuthenticationDefaults.AuthenticationScheme)]

これは逆の方法でも機能します。つまり、Cookieスキーマがデフォルトの場合、JwtBearerトークン認証が必要なメソッドまたはコントローラーの承認のためにJwtBearerスキーマを宣言する必要があります

[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
0
theCuriousOne

トークンプロバイダーの署名キーエンコーディングを確認します。たとえば、ASCIIではなくUTF8にすることができます。

0
H.Wojtowicz

これは、JWTが正しく検証されない場合に受け取る動作のようです。ヘッダーに「Bearer(JWT)」ではなく「Bearer:(JWT)」と入力した結果、この問題が発生しました。

0
Jon B