This looks like the key thing. From what you said, the attributes are being enforced, it's the JWT that is not correct. Have you added the JWT middleware to your server?
That's always a problem, because if I make a simple app it will probably work. Is there an early event where I can intercept the JWT being received? There must be somewhere before the rejection where it would be available? Or on the rejection maybe? Or somewhere in the source to put a break point?
You can put a generic middleware right after the JWT middleware and check if the JWT claim is there correctly set. Use the generic middleware to inspect the request at any point and see if the Authorization header is being sent and the JWT middleware is properly translating the header into the User.Claims property.
Just stepped through the JWT middleware processing and the JWT is received and the claim for scope = administrator is in there and added to User.Claims.
It succeeds on the first one but then carries on and passes back a fail when it assesses the second one and it fails in TScopesRequirement.Check on AvailableScope = TargetScope.
It seems to be caused in as it doesn't exit when a success is found and continues until the failure. Although that is strange as the SCOPE_ADMINUSER has read access and this is a call for List.
function TXDataRequestHandler.HasPermission(User: IUserIdentity;
Requirements: TList<IAuthorizationRequirement>): Boolean;
var
Requirement: IAuthorizationRequirement;
Context: IXDataAuthorizationContext;
ReqResult: IRequirementResult;
begin
if Requirements.Count = 0 then
Exit(True);
Context := TXDataAuthorizationContext.Create(Self);
for Requirement in Requirements do
begin
ReqResult := Requirement.Check(Context);
if not ((ReqResult <> nil) and ReqResult.Succeeded) then
Exit(False);
end;
Result := True;
end;
Ah, indeed, it even confused myself. Security attributes are applied as an "AND" logic. For a permission to be allowed, it has to pass all attributes where it is mentioned. So for Read permission you have to have both SCOPE_ADMIN and SCOPE_ADMINUSER, in your setup there.
so I am accessing as SCOPE_ADMIN which has full access. Surely that should be enough? I shouldn't need to give my scope claim SCOPE_ADMINUSER as well? That's all way too confusing. Surely if the claim is for SCOPE_ADMIN it only has to succeed for that?