Ocelot doesn't handle correctly RouteClaimsRequirement with a key as an Url
See original GitHub issueWhile creating JWT for a user in my authentication service I use System.Security.Claims.ClaimTypes static class with defined string constants for various claims. So ClaimTypes.Role == “http://schemas.microsoft.com/ws/2008/06/identity/claims/role”:
var claims = new List<Claim>
{
new Claim("ID", user.Id.ToString()),
new Claim(ClaimTypes.Name, user.Username)
};
claims.AddRange(user.Roles.Select(role => new Claim(ClaimTypes.Role, role)));
Then, when for some ReRoute in RouteClaimsRequirement I write: “http://schemas.microsoft.com/ws/2008/06/identity/claims/role” : “Admin”
"RouteClaimsRequirement": {
"http://schemas.microsoft.com/ws/2008/06/identity/claims/role": "Admin"
}
such ReRoute just disappears somewhere in the guts of middleware (I didn’t manage to track down where this happens) and a request results in 404 because a reroute is not found:
Error Code: UnableToFindDownstreamRouteError Message: Unable to find downstream route for path: /api/entities/, verb: POST errors found in ResponderMiddleware. Setting error response for request path:/api/entities/, request method: POST
When I use my own claim type like “Role”, this works fine. So I assume there are some issues with serialization/deserialization of a string containing colons or slashes, basically as any url.
Specifications
- Version: 12.0.1
Issue Analytics
- State:
- Created 5 years ago
- Reactions:8
- Comments:7
If we configure
RouteClaimsRequirement
like this:The real result looks like:
That why claims checking is failed. So my solution is do not use colons. Here is my explain:
ClaimsAuthoriser
. In the methodAuthorise
, we have to preprocessrouteClaimsRequirement
before pass it to real authorizer. For safety, I suggest to clone it and transforming on the copy.IClaimsAuthoriser
is registered in container.Here is pseudocode that I use
/
to replace:
Decorator
Decorate
IClaimsAuthoriser
serviceUpdate ocelot config
I have a similar issue. Even if I don’t use
ClaimTypes.Role
and just try to add claims with the typerole
as string, Ocelot can’t find therole
in the user’s claims and returns403 forbidden
response.After debugging, I found out that the problem is not about Ocelot. The problem occurs becasue of the behavior of
System.IdentityModel.Tokens.Jwt
. When theClaimsIdentity
is creating, claim types is checked and if it’s a well-known type then it is replaced with it’s URI. You can find it here. So if I create a token that has a claim with the typerole
,HttpContext.User
will has a claim with the typehttp://schemas.microsoft.com/ws/2008/06/identity/claims/role
.In order to change this behavior and stop the type replacing I added following line in
ConfigureServices
on myStartup.cs
.JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
After that, I create JWT token with the following
ClaimsIdentity
;Then, I can check this claim in
ocelot.json
as following;Clearing
DefaultInboundClaimTypeMap
may create some bugs but I’m not sure that. The first thing that I noticed is IsInRole method returns alwaysfalse
because it checks the claims with the URIhttp://schemas.microsoft.com/ws/2008/06/identity/claims/role