Identity Server 3 - 401 при вызовах Ajax вместо 302

У меня есть гибридное приложение web api/mvc, и я настроил его на использование проверки подлинности файлов cookie. Это отлично работает для части mvc приложения. Веб-API обеспечивает авторизацию, но вместо возврата 401 - Unauthorised он возвращает 302 - Found и перенаправляет на страницу входа. Я бы предпочел, чтобы он возвращал 401. Я попытался подключиться к делегату CookieAuthenticationProvider.OnApplyRedirect, но, похоже, он не вызывается. Что я пропустил? Моя текущая установка ниже:

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

person ilivewithian    schedule 25.01.2016    source источник


Ответы (2)


В вашем примере UseCookieAuthentication больше не контролирует это, вместо этого UseOpenIdConnectAuthentication делает. Это включает в себя использование свойства Notifications и перехват запросов аутентификации OpenID Connect.

Попробуйте следующее для вдохновения:

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);
        }
    }
});
person Scott Brady    schedule 25.01.2016
comment
Нет ли здесь опечатки? Вы проверяете, является ли статус == Неавторизованным, и если да, то устанавливаете его на Неавторизованный? Разве это не бездействие? - person Gary McGill; 14.04.2020
comment
Вы перехватываете ответы, помеченные как неавторизованные, прежде чем они будут перенаправлены поставщику удостоверений для проверки подлинности. Однако настройка кода состояния, вероятно, избыточна. - person Scott Brady; 14.04.2020

В моем случае IsAjaxRequest не помог. Вместо этого я полагаюсь на то, что все маршруты к WebAPI находятся под «/api», поэтому вместо IsAjaxRequest я делаю:

RedirectToIdentityProvider =  context => {
    if (context.ProtocolMessage.RequestType == OpenIdConnectRequestType.Authentication){
        if (context.Request.Path.StartsWithSegments(new PathString("/api")) && context.Response.StatusCode == (int)HttpStatusCode.Unauthorized){
            context.HandleResponse();
            return Task.CompletedTask;
        }
    }
    return Task.CompletedTask;
}
person Steffen Jørgensen    schedule 15.06.2020