Identity Server 3 - 401 on Ajax Calls instead of 3

2019-06-17 07:55发布

问题:

I have a web api / mvc hybrid app and I have configured it to use cookie authentication. This works fine for the mvc portion of the application. The web api does enforce the authorization, but instead of returning a 401 - Unauthorised it returns a 302 - Found and redirects to the login page. I would rather it returns a 401. I have attempted to hook into the CookieAuthenticationProvider.OnApplyRedirect delegate, but this doesn't seem to be called. What have I missed? My current setup is below:

AntiForgeryConfig.UniqueClaimTypeIdentifier = Constants.ClaimTypes.Subject;
JwtSecurityTokenHandler.InboundClaimTypeMap = new Dictionary<string, string>();

app.UseCookieAuthentication(new CookieAuthenticationOptions
{
    AuthenticationType = "Cookies",
    ExpireTimeSpan = TimeSpan.FromMinutes(20),
    SlidingExpiration = true,
    CookieHttpOnly = true,
    CookieSecure = CookieSecureOption.Never, //local non ssl-dev only
    Provider = new CookieAuthenticationProvider
    {
        OnApplyRedirect = ctx =>
        {
            if (!IsAjaxRequest(ctx.Request))
            {
                ctx.Response.Redirect(ctx.RedirectUri);
            }
        }
    }
});

app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
{
    Authority = IdentityConfig.Authority,
    ClientId = IdentityConfig.SoftwareClientId,
    Scope = "openid profile roles",
    RedirectUri = IdentityConfig.RedirectUri,
    ResponseType = "id_token",
    SignInAsAuthenticationType = "Cookies"
});

回答1:

In your example the UseCookieAuthentication no longer controls this, instead the UseOpenIdConnectAuthentication does. This involves using the Notifications property and intercepting OpenID Connect authentication requests.

Try out the following for inspiration:

app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
{
    Authority = IdentityConfig.Authority,
    ClientId = IdentityConfig.SoftwareClientId,
    Scope = "openid profile roles",
    RedirectUri = IdentityConfig.RedirectUri,
    ResponseType = "id_token",
    SignInAsAuthenticationType = "Cookies",
    Notifications = new OpenIdConnectAuthenticationNotifications
    {
        RedirectToIdentityProvider = notification =>
        {
            if (notification.ProtocolMessage.RequestType == OpenIdConnectRequestType.AuthenticationRequest)
            {
                if (IsAjaxRequest(notification.Request) && notification.Response.StatusCode == (int)HttpStatusCode.Unauthorized)
                {
                    notification.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
                    notification.HandleResponse();
                    return Task.FromResult(0);
                }
            }
            return Task.FromResult(0);
        }
    }
});