title: Windows Authentication Asp.net core 2 database role authorization
body: <p>I am working on an intranet application that will use Asp.Net Core 2.1 and Windows authentication. I am getting the pass through from IIS just fine, but I want to use roles stored in a database for the authorization.</p>
  
  <p>I have an IClaimsTransformeration class that gets the roles from a database based on the LAN Id and adds them to the claims list with the role key.</p>
  
  <pre><code>public class MyClaimsTransformer : IClaimsTransformation
  {
      private readonly IUnitOfWorkMtuSecurity _unitOfWork;
  
      public MyClaimsTransformer(IUnitOfWorkMtuSecurity unitOfWork)
      {
          _unitOfWork = unitOfWork;
      }
  
      // Each time HttpContext.AuthenticateAsync() or HttpContext.SignInAsync(...) is called the claims transformer is invoked. So this might be invoked multiple times. 
      public async Task&lt;ClaimsPrincipal&gt; TransformAsync(ClaimsPrincipal principal)
      {
          var identity = principal.Identities.FirstOrDefault(x =&gt; x.IsAuthenticated);
          if (identity == null) return principal;
  
          //var user = await _userManager.GetUserAsync(principal);
          var user = identity.Name;
          if (user == null) return principal;
  
          //Get user with roles from repository.
          var dbUser = _unitOfWork.UserInformations.GetUserWithRoles(user);
  
          // Inject DbRoles into Claims list
          foreach (var role in dbUser.UserInformationUserRoles.Select((r=&gt;r.UserRole)))
          {
              var claim = new Claim(ClaimTypes.Role, role.Name);
              identity.AddClaim(claim);
          }
  
          return new ClaimsPrincipal(identity);
      }  
  }
  </code></pre>
  
  <p>I added the IClaimsTransformation to my services in the startup.cs</p>
  
  <pre><code>services.AddScoped&lt;IClaimsTransformation, MyClaimsTransformer&gt;();
  </code></pre>
  
  <p>Then I added the attribute to my controller </p>
  
  <pre><code>[Authorize(Roles = "Administrator")]
  </code></pre>
  
  <p>When I run my application I get the following error:</p>
  
  <blockquote>
    <p>An unhandled exception occurred while processing the request.
    InvalidOperationException: No authenticationScheme was specified, and there was no DefaultForbidScheme found.
    Microsoft.AspNetCore.Authentication.AuthenticationService.ForbidAsync(HttpContext context, string scheme, AuthenticationProperties properties)</p>
  </blockquote>
  
  <p>In the startup.cs I added the following to the services</p>
  
  <pre><code>services.AddAuthentication(IISDefaults.AuthenticationScheme);
  </code></pre>
  
  <p>This got rid of the error, but no matter what I get a 403 error.</p>
  
  <blockquote>
    <p>You don't have authorization to view this page.
    HTTP ERROR 403</p>
  </blockquote>
  
  <p>When I watch the return value from MyClaimsTransformer, I can see the role of administrator has been added to the list of claims, but no matter what I get a 403 error. </p>
  
  <p>Does anyone have a suggestion for what I am missing?</p>
  
  <p>If I use the following syntax in my view it works at the view level:</p>
  
  <pre><code> @if (User.HasClaim("http://schemas.microsoft.com/ws/2008/06/identity/claims/role", "Administrator"))
                      {
                  &lt;li&gt;&lt;a asp-area="" asp-controller="UserInformationAdmin" asp-action="Index"&gt;Admin&lt;/a&gt;&lt;/li&gt;
                       } 
  </code></pre>
  
  <p>I have to specify the entire schema url though.</p>