Asp.Net Core 2 oidc 中间件在代理请求后不挑战 returns 401
Asp.Net Core 2 oidc middleware does not challenge after proxy request returns 401
我正在尝试构建一个集中式代理,它将拦截所有请求并使用 openidconnect 处理身份验证。
目前代理的请求只是 returns 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"))
);
}
}
有什么想法吗?
查看源码发现Asp.NetCore 2中的Authentication中间件在响应returns 401状态码后并没有挑战,所以干脆returnHttpUnauthorizedResult
不再工作了。 Authorize
属性起作用的原因是它 return 是一个 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);
}
}
我正在尝试构建一个集中式代理,它将拦截所有请求并使用 openidconnect 处理身份验证。
目前代理的请求只是 returns 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"))
);
}
}
有什么想法吗?
查看源码发现Asp.NetCore 2中的Authentication中间件在响应returns 401状态码后并没有挑战,所以干脆returnHttpUnauthorizedResult
不再工作了。 Authorize
属性起作用的原因是它 return 是一个 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);
}
}