Web API 401重定向Azure Active Directory OpenIdConnect

时间:2015-03-04 21:54:29

标签: c# asp.net-web-api azure-active-directory openid-connect

我遇到401响应导致重定向(302)到登录页面时遇到问题。我的应用程序使用MVC和Web 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);

当Web API调用生成401时,我希望将该状态返回给客户端。我已经阅读了很多文章,例如hereherehere,但我一直无法找到合适的解决方案。我可以返回404,如最后一个链接中的回复所示,但是我不想这样做。任何人都可以建议一种方法吗?

1 个答案:

答案 0 :(得分:2)

为MVC(如在Web UX中)和Web API混合身份验证需要特别小心。有关如何将两者结合起来的示例,请参阅here。 我知道你已经阅读了很多关于这背后的理论,但你想要另一个(不是必需的,上面的样本应该解锁你)背景你可以浏览this