简体   繁体   中英

Add custom claims from stored in database on startup

I have the following ClaimsTransformer class that works very well for assigning custom claims on startup, but I need to also be able to retrieve claims that are stored in a database and add them to the user identity. Unfortunately, I haven't found a way to access the database from within this class. My assumption was that I would be able to inject my database class using DI, but I'm unable to do so because it will no longer accommodate the constructor for IClaimsTransformation .

public class ClaimsTransformer : IClaimsTransformation
{
    public Task<ClaimsPrincipal> TransformAsync(ClaimsPrincipal principal)
    {
        var identity = principal.Identity as ClaimsIdentity;

        var claims = new List<Claim>();

        using (var context = new PrincipalContext(ContextType.Domain))
        {
            if (identity != null)
            {
                var user = UserPrincipal.FindByIdentity(context, identity.Name);
                if (user != null) claims.Add(new Claim(CustomClaimType.DisplayName.ToString(), user.DisplayName));
            }
        }

        claims.AddRange(identity?.Claims);

        //var newIdentity = new ClaimsIdentity(claims, identity?.AuthenticationType);
        var newIdentity = new ClaimsIdentity(claims, "Kerberos");
        return Task.FromResult(new ClaimsPrincipal(newIdentity));
    }
}

You can take a look at the code of the PolicyServer for some inspiration. From the code :

// this sets up the PolicyServer client library and policy provider -
// configuration is loaded from appsettings.json
services.AddPolicyServerClient(Configuration.GetSection("Policy"))
    .AddAuthorizationPermissionPolicies();

reads policies from a json file, something like:

"Policy": {
  "claims": [
    {
      "name": "tenantid",
      "value": "44"
    }
  ],
  "roles": [

but that can be any source. In your case it may be a singleton that is filled from the database.

And add the claims using middleware . In your case something like:

// Inject the repository
public async Task Invoke(HttpContext context, IClaimsRepository repository)
{
    if (context.User.Identity.IsAuthenticated)
    {
        // Get claims from (cached) database, singleton.
        var claims = await repository.GetClaimsAsync();
        if (claims.Count > 0)
        {
            var id = new ClaimsIdentity(claims, "MyMiddleware", "name", "role");
            // Add as extra Identity to User.
            context.User.AddIdentity(id);
        }
    }
    await _next(context);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM