atobrandon
atobrandon

Reputation: 43

Using the Authorize attribute with Azure Active Directory

I'm trying to use [Authorize(Roles="test")] and/or call User.IsInRole("test") on a testing app and it's not working for me. In the app configuration in the Azure Management Portal I've enabled the SecurityGroup claim in the app manifest and also set the delegated permissions to allow for "Read all groups" and "Read directory data". After doing this I'm able to see the SID for the test group in (ClaimsPrincipal.Current.Identity as ClaimsIdentity).FindAll("groups"), but the Authorize attribute and call to IsInRole are not working. Is anything else necessary to allow this to work?

Upvotes: 2

Views: 5559

Answers (2)

Dawid Rutkowski
Dawid Rutkowski

Reputation: 2756

In ASP.NET 5 and MVC 6 all you need to do is a proper configuration. Here is code which works like a charm for me:

public void ConfigureApplication(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
    {
        ...

        app.UseIISPlatformHandler();
        app.UseStaticFiles();

        app.UseCookieAuthentication(options =>
        {
            options.AutomaticAuthenticate = true;
        });            

        app.UseOpenIdConnectAuthentication(options =>
        {
            options.AutomaticChallenge = true;
            options.ClientId = Configuration.Get<string>("Authentication:AzureAd:ClientId");
            options.Authority = Configuration.Get<string>("Authentication:AzureAd:AADInstance") + "Common";
            options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;

            options.TokenValidationParameters = new TokenValidationParameters
            {
                ValidateIssuer = false,
                RoleClaimType = "roles"
            };
            options.Events = new OpenIdConnectEvents
            {
                OnAuthenticationValidated = (context) => Task.FromResult(0),
                OnAuthenticationFailed = (context) =>
                {
                    context.Response.Redirect("/Home/Error");
                    context.HandleResponse(); // Suppress the exception
                    return Task.FromResult(0);
                },
                OnRemoteError = (context) => Task.FromResult(0)
            };
        });

        app.UseMvc(routes =>
        {
            routes.MapRoute(name: "default", template: "{controller=Dashboard}/{action=Index}/{id?}");                
        });

        DatabaseInitializer.InitializaDatabaseAsync(app.ApplicationServices).Wait();
    }

Upvotes: 2

vibronet
vibronet

Reputation: 7394

Azure AD does not send groups in the Role claim, and it does not send the name of groups (in a multitenant system, that would not mean much: "admin" in contoso might have a completely different semantic from "admin" in fabrikam). Azure AD has a new construct which represents actual roles, as opposed to group. If you want to check access against the name of a role, see https://github.com/Azure-Samples/active-directory-dotnet-webapp-roleclaims/blob/master/WebApp-RoleClaims-DotNet for a sample using application roles. If you want to check authorization against a group instead, you need to assign the group claim type as RoleClaimType (in https://github.com/Azure-Samples/active-directory-dotnet-webapp-roleclaims/blob/master/WebApp-RoleClaims-DotNet/App_Start/Startup.Auth.cs you can see how it's done for app roles) so that ASP.NET will know it's the claim to verify when Authorize and IsInRole come into play. Also, given that you don;t get the group's name you need to perform the check against the group's objectId. If you want to use groups AND check against group names, it gets complicated. You need to call the graph API to translate the group's ObjectId into its name and augment the incoming claims collection accordingly.

Upvotes: 4

Related Questions