I've got a C# .NET project setup using Entity Framework, MembershipReboot and IdentityServer3.
I'm looking at the database and I see a UserClaims
table. Inside this table I've added a few claims using the MembershipReboot AddClaim
method.
The claims from the UserClaims
table are somehow added to the ClaimsPrincipal
. I can see this when I send a request to my Controller
. In the controllers ActionResult
method I have the following couple lines of code:
var claimsPrincipal = User as ClaimsPrincipal;
if (claimsPrincipal != null)
{
var userClaims = claimsPrincipal.Claims;
In this example userClaims
will contain the claims from MembershipReboots UserClaims
table.
In a similar fashion I'd like to add some additional claims to the ClaimsPrincipal
without using the UserClaims table. The idea is that if a user is a member of a group then they will inherit claims which are associated with that group. I've created a separate table that I'm storing these group claims in - but I'm having trouble actually adding these claims to the ClaimsPrincipal
.
I've been looking at the SamAuthenticationService
in MembershipReboot however I'm not sure if I'm looking in the right place.
Would someone more familiar with MembershipReboot and IdentityServer be able to point me in the right direction?
After doing some more digging I've discovered where the claims are gathered and added to the ClaimsPrincipal
within MembershipReboot.
The ClaimsPrincipal
is set within the Sign In
method in the AuthenticationService
. The SignIn
method does the following things before creating the ClaimsPrincipal
.
UserClaims
table).UserAccountService.MapClaims
The UserAccountService.MapClaims
method executes a MapClaimsFromAccount<TAccount>
command. It's at this point where you can actually register a handler with MembershipReboot to run a custom claims mapper. Your mapper will be executed and the claims you return will be added to the ClaimsPrincipal
.
It took me a while to find this - but this GitHub Issue helped a lot. I'll copy the code out below.
Essentially what you do is create a CustomMapper
which implements an ICommandHandler<MapClaimsFromAccount<CustomUserAccount>>
. Where CustomUserAccount
is your own class that extends RelationalUserAccount
.
public class CustomClaimsMapper : ICommandHandler<MapClaimsFromAccount<CustomUserAccount>>
{
public void Handle(MapClaimsFromAccount<CustomUserAccount> cmd)
{
cmd.MappedClaims = new System.Security.Claims.Claim[]
{
new System.Security.Claims.Claim(ClaimTypes.GivenName, cmd.Account.FirstName),
new System.Security.Claims.Claim(ClaimTypes.Surname, cmd.Account.LastName),
};
}
}
This is the code you would use to map your own custom claims. The claims given above are just example. These claims can be whatever you need for your application.
public static MembershipRebootConfiguration<CustomUserAccount> config;
static MembershipRebootUserServiceFactory()
{
config = new MembershipRebootConfiguration<CustomUserAccount>();
//Add a handler for the Custom User Account Type
config.AddCommandHandler(new CustomClaimsMapper());
}
This is where you would add a command handler for your custom mapper.
Now when the ClaimsPrincipal
is created it will include any claims you return from your custom mapper.