Веб-API 401 Перенаправление Azure Active Directory OpenIdConnect

У меня проблемы с ответом 401, вызывающим перенаправление (302) на страницу входа. Мое приложение использует как MVC, так и веб-API. Я использую OpenID и Azure Active Directory для аутентификации пользователей, моя настройка аутентификации выглядит следующим образом:

private static string clientId = ConfigurationManager.AppSettings["ida:ClientId"];
private static string appKey = ConfigurationManager.AppSettings["ida:AppKey"];
private static string aadInstance = ConfigurationManager.AppSettings["ida:AADInstance"];
private static string tenant = ConfigurationManager.AppSettings["ida:Tenant"];
private static string postLogoutRedirectUri = ConfigurationManager.AppSettings["ida:PostLogoutRedirectUri"];
private static string graphResourceId = ConfigurationManager.AppSettings["ida:GraphResourceId"];
public static readonly string authority = String.Format(CultureInfo.InvariantCulture, aadInstance, tenant);

MvcApplication mvcApplication = HttpContext.Current.ApplicationInstance as MvcApplication;

public void ConfigureAuth(IAppBuilder app)
{
    OpenIdConnectAuthenticationOptions openIdConnectAuthenticationOptions = new OpenIdConnectAuthenticationOptions
    {
        ClientId = clientId,
        Authority = authority,
        PostLogoutRedirectUri = postLogoutRedirectUri,
        AuthenticationMode = AuthenticationMode.Active,
        Notifications = new OpenIdConnectAuthenticationNotifications()
        {
            SecurityTokenValidated = (context) =>
            {
                string userId = context.AuthenticationTicket.Identity.FindFirst(ClaimTypes.Name).Value;

                IUserManager userManager = mvcApplication.CurrentContainer.Resolve<IUserManager>();

                if(!userManager.IsUserEnrolled(userId))
                {
                    string givenName = context.AuthenticationTicket.Identity.FindFirst(ClaimTypes.GivenName).Value;
                    string surname = context.AuthenticationTicket.Identity.FindFirst(ClaimTypes.Surname).Value;

                    userManager.EnrolUser(userId, givenName, surname);

                    Claim groupSuper = context.AuthenticationTicket.Identity.Claims.FirstOrDefault(c => c.Type == "groups" && c.Value.Equals(AADClaimTypes.Super, StringComparison.CurrentCultureIgnoreCase));

                    if(groupSuper != null)
                    {
                        userManager.AddClaim(userId, CharitableClaimTypes.Super, userId);
                    }
                }

                List<Claim> claims = userManager.GetUserClaims(userId);

                if(claims != null && claims.Count() > 0)
                {
                    OpenIdClaimsAuthenticationManager openIdClaimsAuthenticationManager = new OpenIdClaimsAuthenticationManager();

                    openIdClaimsAuthenticationManager.Authenticate(context.AuthenticationTicket.Identity, claims);
                }

                return Task.FromResult(0);
            },
            RedirectToIdentityProvider = (context) =>
            {
                context.ProtocolMessage.RedirectUri = context.Request.Uri.ToString();
                context.ProtocolMessage.PostLogoutRedirectUri = postLogoutRedirectUri;

                return Task.FromResult(0);
            },
            AuthorizationCodeReceived = (context) =>
            {
                Claim objectIdentifierClaim = context.AuthenticationTicket.Identity.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier");

                if(objectIdentifierClaim != null)
                {
                    ClientCredential credential = new ClientCredential(clientId, appKey);
                    string objectIdentifier = objectIdentifierClaim.Value;
                    string code = context.Code;
                    Uri redirectUri = new Uri(HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Path));

                    AuthenticationContext authContext = new AuthenticationContext(authority);//, new NaiveSessionCache(objectIdentifier));
                    AuthenticationResult result = authContext.AcquireTokenByAuthorizationCode(code, redirectUri, credential, graphResourceId);
                }

                return Task.FromResult(0);
            }

        }
    };

    CookieAuthenticationOptions cookieAuthenticationOptions = new CookieAuthenticationOptions()
    {
        AuthenticationType = OpenIdConnectAuthenticationDefaults.AuthenticationType
    };

    app.SetDefaultSignInAsAuthenticationType(OpenIdConnectAuthenticationDefaults.AuthenticationType);// CookieAuthenticationDefaults.AuthenticationType);
    app.UseCookieAuthentication(cookieAuthenticationOptions);
    app.UseOpenIdConnectAuthentication(openIdConnectAuthenticationOptions);

Когда вызов веб-API генерирует 401, я хочу, чтобы этот статус возвращался клиенту. Я прочитал много статей, например здесь, здесь и здесь, однако мне не удалось найти рабочее решение. Я мог бы вернуть 404, как было предложено в ответе в последней ссылке, однако я бы предпочел не делать этого. Кто-нибудь может предложить подход?


person markpirvine    schedule 04.03.2015    source источник


Ответы (1)


Смешивание аутентификации для MVC (как в веб-UX) и веб-API требует особой осторожности. См. здесь, чтобы увидеть пример того, как их можно объединить. Я знаю, что вы уже много читали о теории, лежащей в основе этого, но вам нужен еще один (не обязательный, только приведенный выше пример должен разблокировать вас) справочную информацию, которую вы можете просмотреть this.

person vibronet    schedule 04.03.2015
comment
vibronet спасибо, что нашли время ответить, обе ссылки были очень полезны! - person markpirvine; 05.03.2015