Search code examples
azuremicrosoft-graph-apiazure-ad-msalmsal.js

Why can scopes for AuthorizationCodeRequest and AuthorizationCodeUrlRequest be different even though the docs say otherwise?


I'm just starting to explore the MS identity platform and came across this example repo for a node web app. In it under App > routes > auth.js the /aquireToken route sets the authCodeUrlRequestParams and authCodeRequestParams. This includes the scopes for the request dont in the redirectToAuthCodeUrl() function. I wondered about how these two parameter object work and came across this page where it says

Ensure that values for redirectUri and scopes in AuthorizationCodeUrlRequest and AuthorizationCodeRequest are the same

Naturally, I tried this without the same scopes and noticed that it still works. When adding another scope to the authCodeUrlRequestParams object of the /aquireToken route (e.g. Calendars.Read) but not authCodeRequestParams, the app still works and I get access to the data protected by this scope. When switching the scopes the request fails (which makes sense, as the auth URL doesn't include the missing scope). But why does it work when the scopes are included in the auth URL but not the request object?


Solution

  • Like we know, authCodeUrlRequestParams is used to generate an auth code and we can use auth code to generate access token using AAD auth code flow.

    And I had a test before, like you can see Files.ReadWrite.All is a scope which doesn't require Admin consent.

    enter image description here

    So after added this API permission without admin consent, and I didn't add this scope when generate auth code, but added it when generate access token, it gave me an error.

    enter image description here

    But if I added Files.ReadWrite.All when generating auth code, since this scope doesn't have admin consent, I would see a user consent popup after I signed in with my account which let me consent this app to have some permissions. And I consent the permissions and got an auth code, then I used this code I can get an access token which containing Files.ReadWrite.All in scp claim.

    enter image description here

    By the way, in screenshot above, you can see I only set User.Read in the request, but the what scopes I get are far more than a single User.Read, other scopes are from the auth code. I set scope profile email openid offline_access for generateing auth code.

    So my opinion is, we have to contain the scope which doesn't require admin consent and hasn't got admin consent but we required in authCodeUrlRequestParams, so that we can give user consent for this scope, and we can use the code to generate an access token containing this scope even we don't set it in authCodeRequestParams.

    If the scope we required is already got consent by admin no matter it required admin consent or not, we don't need to add it in authCodeUrlRequestParams and only need to add it in authCodeRequestParams and we can get correct access token. Screenshot below, the Group.Read.All has got admin consent.

    enter image description here

    These are all based on my test.