-
Notifications
You must be signed in to change notification settings - Fork 1.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
AllowedScopes does not match string array in JWT scope claim #913
Comments
Hi, @fsmullinslc @marctalary will this feature be supported in upcoming versions? |
Hi @jords1987 @marctalary, I am not part of the development team that manages the pull requests. I worked around the issue by using dependency injection. I added a function that is called from protected void CustomizeOcelot(IServiceCollection services)
{
services.RemoveAll<IScopesAuthoriser>();
services.TryAddSingleton<IScopesAuthoriser, DelimitedScopesAuthorizer>();
} Here is the source to the class that will parse the delimited scopes. Hopefully this helps you. using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using Ocelot.Authorisation;
using Ocelot.Infrastructure.Claims.Parser;
using Ocelot.Responses;
namespace MyGateway.Custom.Claims
{
public class DelimitedScopesAuthorizer : IScopesAuthoriser
{
private readonly IClaimsParser _claimsParser;
private readonly string _scope = "scope";
private readonly string _msScope = "http://schemas.microsoft.com/identity/claims/scope";
public DelimitedScopesAuthorizer(IClaimsParser claimsParser)
{
_claimsParser = claimsParser;
}
public Response<bool> Authorise(ClaimsPrincipal claimsPrincipal, List<string> routeAllowedScopes)
{
if (routeAllowedScopes == null || routeAllowedScopes.Count == 0)
{
return new OkResponse<bool>(true);
}
var values = _claimsParser.GetValuesByClaimType(claimsPrincipal.Claims, _msScope);
if (!values.IsError && !values.Data.Any())
{
values = _claimsParser.GetValuesByClaimType(claimsPrincipal.Claims, _scope);
}
if (values.IsError)
{
return new ErrorResponse<bool>(values.Errors);
}
List<string> userScopes = new List<string>();
foreach (var item in values.Data)
{
if (item.Contains(' '))
{
var scopes = item.Split(' ').ToList();
userScopes.AddRange(scopes);
}
else
{
userScopes.Add(item);
}
}
var matchesScopes = routeAllowedScopes.Intersect(userScopes).ToList();
if (matchesScopes.Count == 0)
{
return new ErrorResponse<bool>(
new ScopeNotAuthorisedError($"no one user scope: '{string.Join(",", userScopes)}' match with some allowed scope: '{string.Join(",", routeAllowedScopes)}'"));
}
return new OkResponse<bool>(true);
}
}
} |
@fsmullinslc thanks for sharing, I decided to just live with it and put single allowed scope and an allowed scope that reflects how the token looks but this may be another option. Maybe @TomPallister would know if this feature will be merged? |
I have exactly the same problem. I get the following error message from ocelot:
I looked into ScopesAuthoriser.cs and it looks like Ocelot doesn't split the scopes claim and so just compares the whole string. Therefore I forked ScopesAuthoriser locally and changed: To let ocelot use my ScopesAuthoriser i added the following line to the startup But I hope it gets fixed upstream and I can delete my modified implementation. |
"AuthenticationOptions": { but values.Data is empty !! |
Expected Behavior / New Feature
Expected AllowedScopes to parse scope claim and match one or more values in string array similar to RouteClaimsRequirement. For example JWT scope claim value has two scopes, space delimited by whitespace:
Values.Read Values.Write
Actual Behavior / Motivation for New Feature
ScopesAuthoriser
compares the entire claim value to the AllowedScopes array causing it to fail to match either scope. It looks like you addressed a similar issue in RouteClaimsRequirement. Is that the workaround for this issue? Or, can AllowedScopes be modified to use that behavior?Steps to Reproduce the Problem
Specifications
The text was updated successfully, but these errors were encountered: