Search code examples
asp.netcookiesasp.net-mvc-5identityserver3

Identity Server 3 - 401 on Ajax Calls instead of 302


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"
});

Solution

  • 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);
            }
        }
    });