Role Claims Issue with OpenIdConnect netcore5
-
FA Team, I have been working on a netcore 5 application using FusionAuth with the OpenIdConnect middelware (nearly an exact clone of the demo app found at https://github.com/FusionAuth/fusionauth-example-asp-netcore5). When I inspect the JWT access token that comes back from the token call, I can see the roles in the decrypted token:
However, when it is parsed into user claims by the middleware I'm not seeing the roles:
Even though according to this blog post they should come along for the ride automatically:
https://fusionauth.io/blog/2020/05/27/sharing-custom-oauth-claims-with-a-asp-netcore-app/Has anyone else run into this problem? I think this almost has to be a bug withing fusion auth or a mis-configuration of our deployment because I even pulled the aforementioned demo project and just put our deployment credentials into the appsettings and the roles did not come through either.
-
I did a search briefly and one possibility is that the claims are being modified by the ASP middleware.
This is adjacent, but similar SO post regarding.
I will let you know if I discover anything else.
Thanks,
Josh -
@joshua I tried removing that claim already, but it doesn't appear to be the issue.
-
@joshua So I think I may have stumbled across something... it looks like the claims are being generated off of the security token and not the access token. When I decode the security token, the claims match 1-1 with what is in the token. When I decode the access token, that is where I'm seeing the roles added. Is there a configuration setting inside of fusion auth to attach the roles to the security token?
-
For anyone else that runs into this issue. The resolution was as follows:
I needed to include the following code in my ConfigureServices mehtod:
options.GetClaimsFromUserInfoEndpoint = true; options.ClaimActions.MapAll(); options.ClaimActions.Add(new RoleClaimAction());
The first line brings the roles claim over, but the values are still in a string array, and do not get automatically parsed into the ClaimPrincipal as a claim.
The second line maps all of the JWT properties to claims. This could probably be refactored to only map the roles property if needed.
The third line takes the string array in the "roles" claim and splits them into individual "role" claims so that you can properly use the User.InRole() methods or set up custom auth policies based on user roles.
Here is the code for the custom RoleClaimAction class:
public class RoleClaimAction : ClaimAction { private const string RoleClaimType = "roles"; public RoleClaimAction() : base(RoleClaimType, ClaimValueTypes.String) { } public override void Run(JsonElement userData, ClaimsIdentity identity, string issuer) { //Map array of roles to separate role claims if (userData.TryGetProperty(RoleClaimType, out var roles)) { if (roles.ValueKind == JsonValueKind.Array) { var enumerator = roles.EnumerateArray(); while (enumerator.MoveNext()) { AddRoleClaim(identity, enumerator.Current.ToString(), issuer); } }else if(roles.ValueKind == JsonValueKind.String) { AddRoleClaim(identity, roles.ToString(), issuer); } }; } private void AddRoleClaim(ClaimsIdentity identity, string role, string issuer) { identity.AddClaim(new Claim(ClaimTypes.Role, role, ClaimValueTypes.String, issuer)); } }
-
-
Thanks for sharing this! I'm glad you figured it out. I'll add a note to the sample application pointing to this forum post.
-
-