Azure AD 应用程序角色

Posted

技术标签:

【中文标题】Azure AD 应用程序角色【英文标题】:Azure AD application roles 【发布时间】:2015-07-17 00:44:59 【问题描述】:

我正在尝试通过 创建受保护的控制器。

这里是 Startup.Auth 的一个豁免,它基本上是由 Visual Studio 模板提供的:

public void ConfigureAuth(IAppBuilder app)
        
            ApplicationDbContext db = new ApplicationDbContext();

            app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);

            app.UseCookieAuthentication(new CookieAuthenticationOptions());

            app.UseOpenIdConnectAuthentication(
                new OpenIdConnectAuthenticationOptions
                
                    ClientId = clientId,
                    Authority = Authority,
                    PostLogoutRedirectUri = postLogoutRedirectUri,

                    Notifications = new OpenIdConnectAuthenticationNotifications()
                    
                        // If there is a code in the OpenID Connect response, redeem it for an access token and refresh token, and store those away.
                       AuthorizationCodeReceived = (context) => 
                       
                           var code = context.Code;
                           ClientCredential credential = new ClientCredential(clientId, appKey);
                           string signedInUserID = context.AuthenticationTicket.Identity.FindFirst(ClaimTypes.NameIdentifier).Value;
                           AuthenticationContext authContext = new AuthenticationContext(Authority, new ADALTokenCache(signedInUserID));
                           AuthenticationResult result = authContext.AcquireTokenByAuthorizationCode(
                           code, new Uri(HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Path)), credential, graphResourceId);

                           return Task.FromResult(0);
                       
                    
                );
        

尝试过具有以下属性的 ApiController:

[Authorize(Roles = "Administrators")]
// GET: api/Questions
[ResponseType(typeof(Question))]
public IHttpActionResult GetQuestions()

    ....

和一个 MVC 控制器:

  [Authorize(Roles = "Administrators")]
    public ActionResult Index()
    
     ....    
    

在 Azure 应用程序清单中定义了以下内容:

  "appRoles": [
       
        "id": "B4531A9A-0DC8-4015-8CE5-CA1DA1D73754",
        "allowedMemberTypes": ["User"], 
        "description": "Administrators",
        "displayName": "Administrators",
        "value": "Administrators",
        "isEnabled": true,
        "origin": "Application"
      
  ]

现在执行/api/Questions 的GET 请求重定向到https://login.microsoftonline.com 并且用户身份验证似乎成功了,此外localhost 和microsoft online 之间存在无限循环的请求。见下文:

我做错了什么?

使用 [Authorize] 效果很好。

【问题讨论】:

你的无限重定向可能是这样的:coding.abel.nu/2014/11/… 【参考方案1】:

原来应该在 Startup.Auth 中添加以下内容:

TokenValidationParameters = new System.IdentityModel.Tokens.TokenValidationParameters
    
        ValidateIssuer = true,
        // map the claimsPrincipal's roles to the roles claim
        RoleClaimType = "roles",
    

它实际上是在配置“角色”声明类型,以便将其映射到默认行为。 优秀的解释可以在: https://samlman.wordpress.com/2015/03/09/using-roles-in-azure-applications/

【讨论】:

ValidateIssuer = true 仅适用于多租户设置 - 而且,这并没有修复我的无限重定向【参考方案2】:

对我来说,上面的解决方案不起作用。相反,我按照https://identityserver.github.io/Documentation/docs/overview/mvcGettingStarted.html 中的描述实现了一个自定义AuthorizeAttribute,以避免无限重定向循环。

这是我的自定义 AuthorizeAttribute 实现代码(同样,主要来自上面的资源):

public class RoleAuthorizeAttribute : AuthorizeAttribute

    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    
        // If the user is authenticated, but we ended up here, it means that
        // the user is not in a role that's allowed to use the controller being called
        if (filterContext.HttpContext.User.Identity.IsAuthenticated)
            filterContext.Result = new HttpStatusCodeResult(HttpStatusCode.Forbidden);
        else
            filterContext.Result = new HttpUnauthorizedResult();
    

PS:我不包括TokenValidationParameters 代码,我可以使用AuthorizeAttribute 指定和不指定Roles。但是,当我指定 Authorize(Roles = "SomeRole") 并且已经过身份验证和授权的用户不在该角色中时,我将面临无限重定向循环。

因此,对于那些我必须使用基于角色的授权的控制器方法,我改用RoleAuthorize(Roles = "SomeRole")。我还有一个自定义 403 错误页面,其样式与应用程序类似,并提供适当数量的详细信息和退出链接,以便用户可以尝试以其他用户身份进行身份验证。

我对该解决方案并不完全满意,因为我觉得内置的AuthorizeAttribute 应该能够处理这种情况。我只是无法让它工作。

【讨论】:

"Instead..." 我认为您的意思是说“除了...”,因为您仍然需要从授权结果中捕获角色。但是您的代码仍然很有用,因为我还有一个无限重定向循环。 不,我的意思是“代替”。我的OpenIdConnectAuthenticationOptions 中实际上没有@Milen 代码。【参考方案3】:
protected override bool AuthorizeCore(HttpContextBase httpContext)
    
        if (httpContext.Request.Url.IsLoopback)
        
            return true;
        

        return base.AuthorizeCore(httpContext);
    

上面的代码旨在消除本地主机调用。希望它对你有用。

【讨论】:

以上是关于Azure AD 应用程序角色的主要内容,如果未能解决你的问题,请参考以下文章

Azure AD 应用程序 - 列出具有角色分配的订阅

Azure AD 身份验证和为应用程序用户分配角色

Azure AD - 令牌中缺少角色声明

Azure AD B2C 单页应用角色

从 Azure AD 发出 JWT 令牌中的角色

Azure AD:访问令牌中缺少角色声明