Add multiple claims into RouteClaimsRequirement
#1950
Replies: 5 comments 1 reply
-
Cant you do "RouteClaimsRequirement": {
"Claim": "settings_read",
"Claim": "settings_admin"
}, It seems each value pair is evaluated individually. I haven't tried this, but this would seem to work. |
Beta Was this translation helpful? Give feedback.
-
thanks, I tried it out. It does not work. ocelot.json becomes an invalid json file. Ends up crashing the gateway. |
Beta Was this translation helpful? Give feedback.
-
It is possible to write your own middleware to fix this issue. Startup.cspublic void Configure(IApplicationBuilder app, IWebHostEnvironment env){
// some more code
var configuration = new OcelotPipelineConfiguration
{
AuthorizationMiddleware = async (httpContext, next) =>
{
await OcelotAuthorizationMiddleware.Authorize(httpContext, next);
}
};
app.UseOcelot(configuration);
} OcelotAuthorizationMiddleware.cspublic class OcelotAuthorizationMiddleware
{
public static async Task Authorize(HttpContext httpContext, Func<Task> next)
{
if (ValidateRole(httpContext) && ValidateScope(httpContext))
await next.Invoke();
else
{
httpContext.Response.StatusCode = 403;
httpContext.Items.SetError(new UnauthorizedError($"Fail to authorize"));
}
}
private static bool ValidateScope(HttpContext httpContext)
{
var downstreamRoute = httpContext.Items.DownstreamRoute();
var listOfScopes = downstreamRoute.AuthenticationOptions.AllowedScopes;
if (listOfScopes == null || listOfScopes.Count == 0) return true;
var userClaimsPrincipals = httpContext.User.Claims.ToArray<Claim>();
List<string> listOfClaimTypes = new List<string>();
foreach (var userClaim in userClaimsPrincipals)
listOfClaimTypes.Add(userClaim.Type);
foreach (string scope in listOfScopes)
if (!listOfClaimTypes.Contains(scope)) return false;
return true;
}
private static bool ValidateRole(HttpContext ctx)
{
var downStreamRoute = ctx.Items.DownstreamRoute();
if (downStreamRoute.AuthenticationOptions.AuthenticationProviderKey == null) return true;
//This will get the claims of the users JWT
Claim[] userClaims = ctx.User.Claims.ToArray<Claim>();
//This will get the required authorization claims of the route
Dictionary<string, string> requiredAuthorizationClaims = downStreamRoute.RouteClaimsRequirement;
//Getting the required claims for the route
foreach (KeyValuePair<string, string> requiredAuthorizationClaim in requiredAuthorizationClaims)
{
if (ValidateIfStringIsRole(requiredAuthorizationClaim.Key))
{
//Splitting the required claims as an or condition
foreach (var requiredClaimValue in requiredAuthorizationClaim.Value.Split(","))
{
foreach (Claim userClaim in userClaims)
{
if (ValidateIfStringIsRole(userClaim.Type) && requiredClaimValue.Equals(userClaim.Value))
{
return true;
}
}
}
}
}
return false;
}
private static bool ValidateIfStringIsRole(string role)
{
// The http://schemas.microsoft.com/ws/2008/06/identity/claims/role string is nesscary because Microsoft returns this as role claims in a JWT
// And when directly adding this to the ocelot.json it will crash ocelot
return role.Equals("http://schemas.microsoft.com/ws/2008/06/identity/claims/role") || role.Equals("Role") ||
role.Equals("role");
}
} |
Beta Was this translation helpful? Give feedback.
-
I implemented similar code at previous company. But that is more then 2 years ago and I no longer work there. So I can't check the exact code. The only thing that I rember is that it worked in .Net 5 and .Net 6. |
Beta Was this translation helpful? Give feedback.
-
yes, its working ok. |
Beta Was this translation helpful? Give feedback.
-
At the moment our config on .net core looks like this
Is it possible to add more claims like below.
Otherwise people with admin permissions would end up getting 403 error.
Beta Was this translation helpful? Give feedback.
All reactions