11

I have a dotnet core api app with windows app enabled. We have bunch of users which have special permission 'admin' and are stored in database, rest all have default permission 'user'. I want users to have extra claims who all are in database. Also I want to store more information like emailid, employee number(which I have to query from LDAP manually)

What I thought is I will have one api, say api/auth which will capture the current user and add claims based on database and ldap query and other api end points can use it.

But I am not able to get how to add and persist claims between different api end points.

Is it possible, and or is it a good way? I have second option to hit the database on each api call.

Edit 1: I have written a middleware which intercepts all api request and searches LDAP/database, creates an ClaimsIndentity and add it to Users.Identity. Then it is available through rest of the call.

Edit 2: When I am @Ondra Starenko's answer, I am not able to reference IClaimsTransformer or app.UseClaimsTransformation. Is there something else I need to include.

Platform: .NET core 2.1.3

Priyesh Kumar
  • 2,837
  • 1
  • 15
  • 29

2 Answers2

10

In .NET Core 2+ IClaimsTransformer has been deprecated. Instead use IClaimsTransformation:

using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication;

public class ClaimsTransformer : IClaimsTransformation
{ 
    public Task<ClaimsPrincipal> TransformAsync(ClaimsPrincipal principal)
    {
        var ci = (ClaimsIdentity) principal.Identity;
        var c = new Claim(ci.RoleClaimType, "Admin");
        ci.AddClaim(c);
        return Task.FromResult(principal);
    }
}

Also note that you should not use "ClaimTypes.Role". You should use ci.RoleClaimType - Especially if you have Windows Authentication enabled. Under Windows Authentication ci.RoleClaimType evaluates to some string value that will get picked up correctly as a role, whereas ClaimTypes.Role will not.

Finally inject your ClaimsTransformer by adding it to the ConfigureServices method of Startup.cs:

services.AddSingleton<IClaimsTransformation, ClaimsTransformer>();

You should now be able to add Role based Authorization attributes to your Controller methods and these will now be evaluated correctly:

[Authorize(Roles = "Admin")]
[HttpGet("[action]/{id}")]        
public User GetUser([FromRoute] int id)
{
    UserLogic ul = new UserLogic();
    return ul.GetUser(id);
}
Aceofspades25
  • 363
  • 4
  • 9
  • 3
    This works nicely for me, thanks! One question: Is there a way to persist the added claims for a specific user for more than just the current request? – RichieMN Sep 03 '19 at 21:20
  • 1
    I have been looking for a while and this is the simplest and most straightforward outline of how to do this, so thanks! Unfortunately I need to persist the claim as I go from page to page in my app (I only want to add the claim the first time it hits TransformAsync), and it doesn't happen with this approach. That's what I have not been able to figure out. I imagine it involves the identity cookies, but basically all the examples I found are using third parties not basic silent Windows authentication. – EGP Aug 14 '20 at 14:00
5

You can add Claims to windows user in the ClaimsTransformer class.

public class ClaimsTransformer : IClaimsTransformer
{
   public Task<ClaimsPrincipal> TransformAsync(ClaimsTransformationContext context)
   {
      //add new claim
      var ci = (ClaimsIdentity) context.Principal.Identity;
      var c = new Claim(ClaimTypes.Role, "admin");
      ci.AddClaim(c);

      return Task.FromResult(context.Principal);
   }
}

And add this line to Startup:

app.UseClaimsTransformation(o => new ClaimsTransformer().TransformAsync(o));

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
   loggerFactory.AddConsole(LogLevel.Debug);
   loggerFactory.AddDebug();

   app.UseClaimsTransformation(o => new ClaimsTransformer().TransformAsync(o));

   app.UseStaticFiles();

   app.UseMvc();
}

For more information see this: add claims to windows identity.

Ondra Starenko
  • 428
  • 1
  • 6
  • 12
  • hi I am not getting IClaimsTransformer in dotnet core 2.1.3. Is there something else I need to include? – Priyesh Kumar Jun 25 '18 at 16:14
  • IClaimsTransformer is no longer supported with dotnet core 2. Instead you should use IClaimsTransformation. See here: https://stackoverflow.com/questions/45709296/claims-transformation-support-missing-in-asp-net-core-2-0 – Aceofspades25 Nov 29 '18 at 22:00