Skip to content
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

[Question] RequiredScope doesn't work (for web APIs called by daemon apps) #1571

Closed
1 task
Anakael opened this issue Dec 30, 2021 · 17 comments
Closed
1 task
Labels
answered question Further information is requested

Comments

@Anakael
Copy link

Anakael commented Dec 30, 2021

Which version of Microsoft Identity Web are you using?

1.21.1

Where is the issue?

  • Web API
    • Protected web APIs (validating scopes)

Is this a new or an existing app?

This is a new app or an experiment.

Repro

[Route("api/[controller]")]
    [ApiController]
    [Authorize]
    public class SomeController : ControllerBase
    {
        [RequiredScope("myScopeName")]
        public async Task CreateSomething()
        {
              return Task.CompletedTask();
        }
    }

Expected behavior

Request finished with 403 code when pass scope myScopeNameM2M.

Actual behavior

Request finishes with 200 code

Additional context / logs / screenshots / link to code

HttpContext.VerifyUserHasAnyAcceptedScope("myScopeName");

Works as expected.

@jennyf19
Copy link
Collaborator

@Anakael I cannot repro:
image

Can you share what you have in your Startup.cs? Thanks.

@Anakael
Copy link
Author

Anakael commented Dec 31, 2021

I did nothing special for it except the authentication by jwt token. Did I miss something?

@jennyf19
Copy link
Collaborator

I would need more information from your Startup.cs. Do you have the same content as when you do dotnet new webapi --auth SingleOrg?

@spacattac
Copy link

I've run into this issue as well, repro'd in 2 different projects. What's interesting is it works/doesn't work as follows:

  • works: for access_tokens that are on-behalf-of-the-user via the authorization_code flow the RequiredScope attrib is working as expected
  • doesn't work: for access_tokens via client_credentials flow the RequiredScope attribute does not work (should return Forbidden when scope is missing), but using "HttpContext.VerifyUserHasAnyAcceptedScope(scopeRequiredByApi);" does work

https://docs.microsoft.com/en-us/azure/active-directory/develop/scenario-protected-web-api-verification-scope-app-roles?tabs=aspnetcore

So for now i'm using the VerifyUserHasAnyAcceptedScope method but would prefer to use the attribute

@jmprieur
Copy link
Collaborator

jmprieur commented Jan 5, 2022

Thanks for the explanation, @spacattac. This is by design (and to follow the protocol), but I realize that the design might not be very good, so I'm tempted to start a discussion with the group to simplify things

What happens is:

  • Web APIs called on behalf of users need to verify the Scopes.
  • Web APIs called on behalf of an app (a daemon app) need to verify app roles

But from the point of view of the client app, in both cases you request scopes (you are exposed to app roles when you do the app registration though).

This is all explained in Protected web API: Verify scopes and app roles

Question for you:

  • what behavior would you expect for the API (given the article above)
  • how can we make things more discoverable?

@jmprieur jmprieur added answered question Further information is requested and removed more info needed no repro labels Jan 5, 2022
@jmprieur jmprieur changed the title [Bug] RequiredScope doesn't wok [Bug] RequiredScope doesn't work (for web APIs called by daemon apps) Jan 5, 2022
@jmprieur jmprieur changed the title [Bug] RequiredScope doesn't work (for web APIs called by daemon apps) [Question] RequiredScope doesn't work (for web APIs called by daemon apps) Jan 5, 2022
@spacattac
Copy link

Thanks @jmprieur . i had read that msft docs link and i didn't really understand why the daemon app couldn't/wouldn't use the scope the same way and didn't understand what an app role is/was. in reading more about Azure AD last night i did learn about the app registration and that app role designation is part of that registration. that explains why i didn't/don't really know what it is - i'm not actually using Azure AD and instead am using Okta for OIDC+OAuth and the daemon app registration doesn't have an app role. i can use Access Policies on the Okta auth server to grant the scopes to an app using client_credentials just like i can to an app acting on behalf of the user with authorization_code flow.

@jmprieur
Copy link
Collaborator

jmprieur commented Jan 5, 2022

Thanks for the explanation, @spacattac.
RequiredScopes just checks at the scp or http://schemas.microsoft.com/identity/claims/scope claims. If Okta generates these, you should be good.

@spacattac
Copy link

Thanks @jmprieur - yes, okta does generate the scope (scp) claim. i don't understand why the call to HttpContext.VerifyUserHasAnyAcceptedScope(scopeRequiredByApi); works for me but [RequiredScopes(scopeRequiredByApi)] does not. It seems to me there should be parity with these.

@jmprieur
Copy link
Collaborator

jmprieur commented Jan 5, 2022

I guess we'd need to see the structure of the token to understand this question? Are you using app.UseAuthorization? Did you customize the Authorization policies?

@spacattac
Copy link

@jmprieur i'll grab some code and/or screen snippets to share/show ...

@spacattac
Copy link

spacattac commented Jan 5, 2022

here's a snippet of scope check working as expected via the method but not the attribute.

image

i am using app.UseAuthorization. and in this project i do have 1 policy added but it's not used in the endpoint/method in this example. also, the other project where i've repro'd this same behavior does not have any additional policies.

services.AddAuthorization(options => { options.AddPolicy("AccessPersonPolicy", policy => policy.Requirements.Add(new IsAnAccessPersonRequirement())); });
and here are the User.Claims and you can see the scope claim has "access_token" but not "documents.read".

image

@jmprieur
Copy link
Collaborator

jmprieur commented Jan 6, 2022

@spacattac : in the claims, the scope provided by Okta (item 7) has a value "access_token", whereas you want "documents.read". That's the reason.

@spacattac
Copy link

@jmprieur - not exactly .... what i'm showing you above is i've intentionally left out the documents.create scope and i'm showing you how the [RequiredScopes("documents.create")] attribute did NOT block the call yet the VerifyUserHasAnyAcceptedScope("documents.create") DID block and returns Forbidden. why is there not parity between these two?

@Pieter-1337
Copy link

same issue here I have an access_token which I retieve through a Client from AD, then the client calls my WebAPI.

Currently my access_token has a "scp" attribute of "access_api" however when I add an [RequiredScope("access_api_admin")] decorator on a controller action (controller has [Authorize]) and I call the endpoint with the "access_api" scope the action gets executed.

Expected behavior would be an Unauthorized..., yet I am gettin the data which I should not be getting...

The token
image

The endpoint with requiredScope "access_api_admin"
image

I feel this should block the request I am making with my access_token since the scope "access_api_admin" is not present in the token...

@gurry
Copy link

gurry commented Mar 15, 2022

RequiredScope used to work as expected in this issue until version 1.17.0 of Microsoft.Identityt.Web. It got broken in 1.18.0. See these issues: #1609 #1002.

In my case adding builder.Services.AddRequiredScopeAuthorization() statement to Program.cs made the RequiredScope attribute work.

@jmprieur
Copy link
Collaborator

Closing this one:

  • We released RequiredScopeOrAppPermissionAttribute in Microsoft.Identity.Web 1.25.0
  • @gurry : you are right, it requires to use app.AddAuthorization(). However, AddRequiredScopeAuthorization is called in AddMicrosoftIdentityWebApi. Did you use that method?

@gurry
Copy link

gurry commented Aug 24, 2022

@jmprieur Yes, I peeked inside Microsoft's code and saw 'AddRequiredScopeAuthorization() being used there and simply mimicked that. It may well have been AddMicrosoftIdentityWebApi() that I peeked into (don't exactly remember now).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
answered question Further information is requested
Projects
None yet
Development

No branches or pull requests

6 participants