使用Azure Active Directory + OWIN将MVC Authorize属性与角色一起使用

时间:2014-08-31 19:34:10

标签: azure asp.net-mvc-5 authorization owin azure-active-directory

我正在构建一个多租户MVC5应用程序,该应用程序非常贴切地遵循示例指南:https://github.com/AzureADSamples/WebApp-MultiTenant-OpenIdConnect-DotNet/

我正在对Azure Active Directory进行身份验证,并拥有自己的角色名称,我在SecurityTokenvalidated事件期间注入了角色声明:

SecurityTokenValidated = (context) =>
                    {
                        // retriever caller data from the incoming principal
                        string upn = context.AuthenticationTicket.Identity.FindFirst(ClaimTypes.Name).Value;
                        string tenantId = context.AuthenticationTicket.Identity.FindFirst("http://schemas.microsoft.com/identity/claims/tenantid").Value;

                        var databaseConnectionString = RoleEnvironment.GetConfigurationSettingValue("DatabaseConnectionString");

                        AppAnalyzerUser appAnalyzerUser = null;

                        using (CloudContext dbContext = new CloudContext(databaseConnectionString))
                        {
                            if (dbContext.Office365Accounts.FirstOrDefault(x => x.AzureTokenId == tenantId) == null)
                                throw new GeneralErrorException("Account not found", "The domain that you used to authenticate has not registered.");

                            appAnalyzerUser = (from au in dbContext.AppAnalyzerUsers
                                .Include(x => x.Roles)
                                where au.UserPrincipalName == upn && au.AzureTokenId == tenantId
                                select au).FirstOrDefault();

                            if (appAnalyzerUser == null)
                                throw new AccountNotFoundException();                                
                        }

                        foreach (var role in appAnalyzerUser.Roles)
                        {
                            Claim roleClaim = new Claim(ClaimTypes.Role, role.RoleName);
                            context.AuthenticationTicket.Identity.AddClaim(roleClaim);                                
                        }

                        return Task.FromResult(0);
                    },

我用Authorize属性装饰了一些方法,如下所示:

    [Authorize(Roles = "SystemAdministrator"), HttpGet]
    public ActionResult Index()
    {
        return View();
    }

并且authorize属性正确检测到用户不在该角色中并将其发送回Azure进行身份验证。

但是我看到的是,用户已经针对Azure AD进行了身份验证并登录到了应用程序。他们没有机会在Azure屏幕上选择新的用户帐户来登录。因此,当它将它们退回到Azure AD时,Azure AD会说“您已经登录”并将它们直接发送回应用程序。 SecurityTokenValidated事件反复发生,一遍又一遍。

但是用户仍然没有该方法所需的角色,因此他们会被退回到Azure进行身份验证,显然我们陷入了循环。

除了编写我自己的Authorize属性实现之外,还有其他方法可以解决这个问题吗?

1 个答案:

答案 0 :(得分:3)

不幸的是,您偶然发现了[授权]的已知问题。有关说明和可能的解决方案,请参阅https://github.com/aspnet/Mvc/issues/634 - 此时编写自定义属性可能是最简化的解决方法。