Reputation: 331
We are using Identity Server 4 with a custom login page. We've been testing what happens when the cookie expires or the token is manually modified (part of hardening).
The application wants to redirect us to https://localhost:44349/signin-oidc, and returns a 302 redirect, but /signin-oidc doesn't exist. We'd like to throw a 401 and redirect them to /home.
I've found where I can capture the events
options.Events = new OpenIdConnectEvents
{
OnRedirectToIdentityProvider = context => {
var newRedirect = context.ProtocolMessage.RedirectUri.ToString().Replace("signin-oidc", "home");
var builder = new UriBuilder(newRedirect);
builder.Scheme = "https";
context.ProtocolMessage.RedirectUri = builder.ToString();
context.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
return Task.FromResult(0);
}
};
But this doesn't seem to work and we simply throw a 302 error without any way to report back to user what happened.
Upvotes: 5
Views: 6996
Reputation: 1958
MADC0D3R's answer works great, except that the CORS configuration is ignored for some reason.
Wasn't able to find out why, but I came up with a workaround:
OnRedirectToIdentityProvider = async context => {
if (context.Request.Path != "/Account/Login") {
context.Response.Clear();
context.Response.StatusCode = 401;
// Global CORS middleware does not work here, need to add the headers manually
await ManuallyAddCorsHeaders(context.HttpContext, context.Response);
context.HandleResponse();
}
}
Implementation of ManuallyAddCorsHeaders
:
private static async Task ManuallyAddCorsHeaders(HttpContext httpContext, HttpResponse response) {
var corsService = httpContext.RequestServices.GetRequiredService<ICorsService>();
var corsPolicyProvider = httpContext.RequestServices.GetRequiredService<ICorsPolicyProvider>();
var defaultPolicy = await corsPolicyProvider.GetPolicyAsync(httpContext, new CorsOptions().DefaultPolicyName);
if (defaultPolicy == null)
return;
var result = corsService.EvaluatePolicy(httpContext, defaultPolicy);
corsService.ApplyResult(result, response);
}
I'm putting this here in case someone else is struggling with it, took me a bit to figure it out. Also grateful for alternative approaches.
Upvotes: 1
Reputation: 331
Found this little gem here
OnRedirectToIdentityProvider = ctx =>
{
if (ctx.Request.Path.StartsWithSegments("/api"))
{
if (ctx.Response.StatusCode == (int)HttpStatusCode.OK)
{
ctx.Response.StatusCode = 401;
}
ctx.HandleResponse();
}
return Task.CompletedTask;
}
It does exactly what I need, which is to return a 401. The trick was in the HandleResponse().
Upvotes: 18