web-dev-qa-db-ja.com

AddJwtBearerOnAuthenticationFailedがカスタムエラーを返す

私は Openidict を使用しています。
カスタムステータスコードを含むカスタムメッセージを返そうとしていますが、返せません。 startup.csでの私の構成:

services.AddAuthentication(options =>
            {
                options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
            })
            .AddJwtBearer(o =>
            {
                o.Authority = this.Configuration["Authentication:OpenIddict:Authority"];
                o.Audience = "MyApp";           //Also in Auhorization.cs controller.
                o.RequireHttpsMetadata = !this.Environment.IsDevelopment();
                o.Events = new JwtBearerEvents()
                {
                    OnAuthenticationFailed = context =>
                    {
                        context.Response.StatusCode = HttpStatusCodes.AuthenticationFailed;
                        context.Response.ContentType = "application/json";
                        var err = this.Environment.IsDevelopment() ? context.Exception.ToString() : "An error occurred processing your authentication.";
                        var result = JsonConvert.SerializeObject(new {err});
                        return context.Response.WriteAsync(result);
                    }
                };
            });

しかし、問題はコンテンツが返されないことです。 Chrome開発者ツールレポート

(失敗)

error

ステータスと

応答データのロードに失敗しました

error

応答のため。

私も試しました:

context.Response.WriteAsync(result).Wait();
return Task.CompletedTask;

しかし、結果は同じです。

望ましい動作:
何が悪かったのかというメッセージとともにカスタムステータスコードを返したいのですが。

3
Makla

401応答が返されると、aspnet-contribOAuth2検証とMSFTJWTハンドラーの両方がエラーコード/説明を含むWWW-Authenticate応答ヘッダーを自動的に返すことに注意することが重要です。

enter image description here

標準の動作が十分に便利でないと思われる場合は、イベントモデルを使用して手動でチャレンジを処理できます。例えば:

services.AddAuthentication()
    .AddJwtBearer(options =>
    {
        options.Authority = "http://localhost:54540/";
        options.Audience = "resource_server";
        options.RequireHttpsMetadata = false;
        options.Events = new JwtBearerEvents();
        options.Events.OnChallenge = context =>
        {
            // Skip the default logic.
            context.HandleResponse();

            var payload = new JObject
            {
                ["error"] = context.Error,
                ["error_description"] = context.ErrorDescription,
                ["error_uri"] = context.ErrorUri
            };

            return context.Response.WriteAsync(payload.ToString());
        };
    });
5
Pinpoint

同じ問題に直面していて、Pinpointが提供するソリューションを試しましたが、ASP.NETコア2.0では機能しませんでした。しかし、Pinpointのソリューションといくつかの試行錯誤に基づいて、次のコードが機能します。

var builder = services.AddAuthentication(options =>
        {
            options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
            options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
        }).AddJwtBearer(o =>
        {
            o.Authority = "http://192.168.0.110/auth/realms/demo";
            o.Audience = "demo-app";
            o.RequireHttpsMetadata = false;

            o.Events = new JwtBearerEvents()
            {
                OnAuthenticationFailed = c =>
                {
                    c.NoResult();
                    c.Response.StatusCode = 500;
                    c.Response.ContentType = "text/plain";
                    c.Response.WriteAsync(c.Exception.ToString()).Wait();
                    return Task.CompletedTask;
                },
                OnChallenge = c =>
                {
                    c.HandleResponse();
                    return Task.CompletedTask;
                }
            };
        });
8
Ryan Teh

.net core2.1の以下のコードを確認してください

OnAuthenticationFailed =context =>
                {
                    context.Response.OnStarting(async () =>
                    {
                        context.NoResult();
                        context.Response.Headers.Add("Token-Expired", "true");
                        context.Response.ContentType = "text/plain";
                        context.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
                        await context.Response.WriteAsync("Un-Authorized");
                    });

                    return Task.CompletedTask;                        
                },
0