Reputation: 505
Assume I have 2 endpoints like this
In case 1., I pass above array to RouteClaimsRequirement like below
"RouteClaimsRequirement": {
"order_perm": ["order_create", "order_edit"]
}
but it crashes when app starts, and in case 2. I setup like this
"RouteClaimsRequirement": {
"order_perm": ""
}
but user has claim "order_perm": "create_order" fails authorization.
Does RouteClaimsRequirement support these use cases? If so how can I do that?
Upvotes: 4
Views: 2828
Reputation: 75
I know this an old question, I recently got stuck on the same thing, after a lot googling I found this solution on github. I changed a few things to make it work for me as I'm using Ocelot 16.0.1. ocelot.json file
{
"DownstreamPathTemplate": "/api/{everything}/{everything}",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": "80"
}
],
"UpstreamPathTemplate": "/web/{everything}/{everything}",
"UpstreamHttpMethod": [ "GET" ],
"AuthenticationOptions": {
"AuthenticationProviderKey": "Authkey",
"AllowedScopes": []
},
"RouteClaimsRequirement": {
"Role": "Admin , SuperAdmin"
},
"SwaggerKey": "myapi"
},
Configure method
public async void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
//your code here
var configration = new OcelotPipelineConfiguration
{
AuthorisationMiddleware=async (ctx, next) =>
{
if (this.Authorize(ctx))
{
await next.Invoke();
}
else
{
ctx.Items.SetError(new UnauthorisedError($"Fail to authorize"));
}
}
};
//your code here
await app.UseOcelot(configration);
}
Authorize method
private bool Authorize(HttpContext ctx)
{
if (ctx.Items.DownstreamRoute().AuthenticationOptions.AuthenticationProviderKey == null) return true;
else
{
bool auth = false;
Claim[] claims = ctx.User.Claims.ToArray<Claim>();
Dictionary<string, string> required = ctx.Items.DownstreamRoute().RouteClaimsRequirement;
Regex reor = new Regex(@"[^,\s+$ ][^\,]*[^,\s+$ ]");
MatchCollection matches;
Regex reand = new Regex(@"[^&\s+$ ][^\&]*[^&\s+$ ]");
MatchCollection matchesand;
int cont = 0;
foreach (KeyValuePair<string, string> claim in required)
{
matches = reor.Matches(claim.Value);
foreach (Match match in matches)
{
matchesand = reand.Matches(match.Value);
cont = 0;
foreach (Match m in matchesand)
{
foreach (Claim cl in claims)
{
if (cl.Type == claim.Key)
{
if (cl.Value == m.Value)
{
cont++;
}
}
}
}
if (cont == matchesand.Count)
{
auth = true;
break;
}
}
}
return auth;
}
}
Upvotes: 5