title: Custom Authorize Attribute on asp.net mvc
body: <p>I have an asp.net mvc app which authorizes with Azure AAD. The app is based on this github example:</p>
  
  <p><a href="https://github.com/dushyantgill/VipSwapper/tree/master/TrainingPoint" rel="nofollow">https://github.com/dushyantgill/VipSwapper/tree/master/TrainingPoint</a></p>
  
  <p>this app has a  custom authorize attribute </p>
  
  <pre><code>  public class AuthorizeUserAttribute : AuthorizeAttribute
    {
          protected override void HandleUnauthorizedRequest(AuthorizationContext ctx)
          {
              if (!ctx.HttpContext.User.Identity.IsAuthenticated)
                  base.HandleUnauthorizedRequest(ctx);
              else
              {
                  ctx.Result = new ViewResult { ViewName = "Error", ViewBag = { message = "Unauthorized." } };
                  ctx.HttpContext.Response.StatusCode = 403;
              }
          }
      }
  </code></pre>
  
  <p>However this seems very odd to me.</p>
  
  <p>I have on a controller something like this:</p>
  
  <pre><code> public class GlobalAdminController : Controller
      {
          // GET: GlobalAdmin
          [AuthorizeUser(Roles = "admin")]
          public ActionResult Index()
          {
              return View();
          }
      }
  </code></pre>
  
  <p>As you can see the custom attribute is used there, but take a deeper look at the code of the custom attribute.
  Apparently on both the if and ELSE the request is not authenticated.</p>
  
  <p>Now take a look at this screenshot.</p>
  
  <p>Makes no sense right?
  <a href="http://screencast.com/t/obqXHZJj0iNG" rel="nofollow">http://screencast.com/t/obqXHZJj0iNG</a></p>
  
  <p>The question, is what should I do to allow the user to execute the controller?</p>
  
  <p>Update 1:
  On my auth flow I have the following</p>
  
  <pre><code>  public void ConfigureAuth(IAppBuilder app)
          {
              // configure the authentication type &amp; settings
              app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
              app.UseCookieAuthentication(new CookieAuthenticationOptions());
  
              // configure the OWIN OpenId Connect options
              app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
              {
                  ClientId = SettingsHelper.ClientId,
                  Authority = SettingsHelper.AzureADAuthority,
                  Notifications = new OpenIdConnectAuthenticationNotifications()
                  {
                      // when an auth code is received...
                      AuthorizationCodeReceived = (context) =&gt; {
                          // get the OpenID Connect code passed from Azure AD on successful auth
                          string code = context.Code;
  
                          // create the app credentials &amp; get reference to the user
                          ClientCredential creds = new ClientCredential(SettingsHelper.ClientId, SettingsHelper.ClientSecret);
                          string userObjectId = context.AuthenticationTicket.Identity.FindFirst(System.IdentityModel.Claims.ClaimTypes.NameIdentifier).Value;
  
                          // use the ADAL to obtain access token &amp; refresh token...
                          //  save those in a persistent store...
                          EfAdalTokenCache sampleCache = new EfAdalTokenCache(userObjectId);
                          AuthenticationContext authContext = new AuthenticationContext(SettingsHelper.AzureADAuthority, sampleCache);
  
                          // obtain access token for the AzureAD graph
                          Uri redirectUri = new Uri(HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Path));
                          AuthenticationResult authResult = authContext.AcquireTokenByAuthorizationCode(code, redirectUri, creds, SettingsHelper.AzureAdGraphResourceId);
  
                          if (GraphUtil.IsUserAADAdmin(context.AuthenticationTicket.Identity))
                              context.AuthenticationTicket.Identity.AddClaim(new Claim("roles", "admin"));
  
                          // successful auth
                          return Task.FromResult(0);
                      },
                      AuthenticationFailed = (context) =&gt; {
                          context.HandleResponse();
                          return Task.FromResult(0);
                      }
                  },
                  TokenValidationParameters = new System.IdentityModel.Tokens.TokenValidationParameters
                  {
                      ValidateIssuer = false
                  }
              });
          }
  </code></pre>
  
  <p>Check specially the IsAADAdmin method call</p>
  
  <pre><code>/// &lt;summary&gt;
          /// The global administrators and user account administrators of the directory are automatically assgined the admin role in the application.
          /// This method determines whether the user is a member of the global administrator or user account administrator directory role.
          /// RoleTemplateId of Global Administrator role = 62e90394-69f5-4237-9190-012177145e10
          /// RoleTemplateId of User Account Administrator role = fe930be7-5e62-47db-91af-98c3a49a38b1
          /// &lt;/summary&gt;
          /// &lt;param name="objectId"&gt;The objectId of user or group that currently has access.&lt;/param&gt;
          /// &lt;returns&gt;String containing the display string for the user or group.&lt;/returns&gt;
          public static bool IsUserAADAdmin(ClaimsIdentity Identity)
          {
              string tenantId = Identity.FindFirst("http://schemas.microsoft.com/identity/claims/tenantid").Value;
              string signedInUserID = Identity.FindFirst(System.IdentityModel.Claims.ClaimTypes.NameIdentifier).Value;
              string userObjectID = Identity.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier").Value;
  
              ClientCredential credential = new ClientCredential(SettingsHelper.ClientId, SettingsHelper.ClientSecret);
  
              // initialize AuthenticationContext with the token cache of the currently signed in user, as kept in the app's EF DB
              AuthenticationContext authContext = new AuthenticationContext(SettingsHelper.AzureADAuthority, new EfAdalTokenCache(signedInUserID));
  
              AuthenticationResult result = authContext.AcquireTokenSilent(
                  SettingsHelper.AzureAdGraphResourceId, credential, new UserIdentifier(userObjectID, UserIdentifierType.UniqueId));
  
              HttpClient client = new HttpClient();
  
              string doQueryUrl = string.Format("{0}/{1}/users/{2}/memberOf?api-version={3}",
                  SettingsHelper.AzureAdGraphResourceId, tenantId,
                  userObjectID, SettingsHelper.GraphAPIVersion);
  
              HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, doQueryUrl);
              request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", result.AccessToken);
              HttpResponseMessage response = client.SendAsync(request).Result;
  
              if (response.IsSuccessStatusCode)
              {
                  var responseContent = response.Content;
                  string responseString = responseContent.ReadAsStringAsync().Result;
                  var memberOfObjects = (System.Web.Helpers.Json.Decode(responseString)).value;
  
                  if (memberOfObjects != null)
                      foreach (var memberOfObject in memberOfObjects)
                          if (memberOfObject.objectType == "Role" &amp;&amp; (
                              memberOfObject.roleTemplateId.Equals("62e90394-69f5-4237-9190-012177145e10", StringComparison.InvariantCultureIgnoreCase) ||
                              memberOfObject.roleTemplateId.Equals("fe930be7-5e62-47db-91af-98c3a49a38b1", StringComparison.InvariantCultureIgnoreCase)))
                              return true;
              }
  
              return false;
          }
  </code></pre>
  
  <p>I am 100% sure the user is in the admin role, because when I debug it returns true and the claim is created</p>
  
  <p><strong>Update 2:</strong>
  At debugging time I checked the User.Claims and the role admin is in there.
  so I am not sure how this authorization per role works with User.IsInRole</p>
  
  <p><a href="http://screencast.com/t/zUbwbpzn55qb" rel="nofollow">http://screencast.com/t/zUbwbpzn55qb</a></p>