代理请求返回401后,Asp.Net Core 2 oidc中间件不会发出挑战

时间:2018-04-19 14:26:05

标签: authentication asp.net-core-2.0 openid-connect http-proxy http-status-code-401

我正在尝试构建一个集中式代理,它将拦截所有请求并使用openidconnect处理身份验证。

目前代理请求只返回401,因此中间件假设要挑战并将我重定向到登录页面。问题是使用.Net Core 1.1的实现,但它似乎不适用于.Net Core 2.

我已经简化了代码但是这样做了,我被重定向到google的登录页面。

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddAuthentication();
        services.AddProxy();
    }

    public void Configure(IApplicationBuilder app)
    {
        app.UseCookieAuthentication(new CookieAuthenticationOptions
        {
            AutomaticAuthenticate = true,
        });

        app.UseGoogleAuthentication(new GoogleOptions
        {
            AutomaticChallenge = true,
            SignInScheme = "oidc",
            ClientId = "clientId",
            ClientSecret = "clientSecret",
        });

        app.MapWhen(
            context => context.RequestStartsWith("http://www.web1.com"),
            builder => builder.RunProxy(baseUri: new Uri("http://www.proxy1.com"))
        );
    }
}

这不适用于.Net Core 2.0的实现,我得到一个401异常页

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddAuthentication(options =>
        {
            options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
            options.DefaultChallengeScheme = GoogleDefaults.AuthenticationScheme;
        })
        .AddCookie()
        .AddGoogle(options =>
        {
            options.ClientId = "clientId";
            options.ClientSecret = "clientSecret";
        });

        services.AddProxy();
    }

    public void Configure(IApplicationBuilder app)
    {
        app.UseAuthentication();

        app.MapWhen(
            context => context.RequestStartsWith("http://www.web1.com"),
            builder => builder.RunProxy(baseUri: new Uri("http://www.proxy1.com"))
        );
    }
}

有什么想法吗?

1 个答案:

答案 0 :(得分:1)

查看源代码后,发现Asp.Net Core 2中的身份验证中间件在响应返回401状态代码后没有质询,因此只返回HttpUnauthorizedResult不再起作用。 Authorize属性有效的原因是它返回ChallengeResult,最终会调用ChallengeAsync

解决方法是,我创建了自己的中间件来处理401状态代码

public class ChallengeMiddleware
{
    private readonly RequestDelegate _next;
    private readonly IAuthenticationSchemeProvider _schemes;

    public ChallengeMiddleware(RequestDelegate next, IAuthenticationSchemeProvider schemes)
    {
        _next = next;
        _schemes = schemes;
    }

    public async Task Invoke(HttpContext context)
    {
        context.Response.OnStarting(async () =>
        {
            if (context.Response.StatusCode == 401)
            {
                var defaultChallenge = await _schemes.GetDefaultChallengeSchemeAsync();
                if (defaultChallenge != null)
                {
                    await context.ChallengeAsync(defaultChallenge.Name);
                }
            }
            await Task.CompletedTask;
        });

        await _next(context);
    }
}