mrochon / b2csamples

MIT License
132 stars 41 forks source link

No access_token from token endpoint #55

Closed codepic closed 1 year ago

codepic commented 1 year ago

I have tried my best to follow the instructions in MultiTenant Sample and I can log in to the SPA application but cannot get the members.

My guess is that the issue lies in the App registrations in the B2C.

Could you share more details on how to configure the app registrations? More specifically how the API Permissions, Certificates and Secrets and Authentication sections are configured in the demo application?

The issue is that when I go to members, the /b2c_1a_v2signin/oauth2/v2.0/token token endpoint returns only id_token. Therefore the API request /tenant/oauth2/members fails.

Below is the request for sample React SPA application

NOTE: Body has been formatted for readability

URL https://b2cmultitenant.b2clogin.com/{tenantId}/b2c_1a_v2signin/oauth2/v2.0/token
{
    "credentials": "omit",
    "headers": {
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:107.0) Gecko/20100101 Firefox/107.0",
        "Accept": "*/*",
        "Accept-Language": "en-US,en;q=0.5",
        "content-type": "application/x-www-form-urlencoded;charset=utf-8",
        "Sec-Fetch-Dest": "empty",
        "Sec-Fetch-Mode": "cors",
        "Sec-Fetch-Site": "cross-site",
        "Pragma": "no-cache",
        "Cache-Control": "no-cache"
    },
    "referrer": "https://b2cmultitenantv2.z22.web.core.windows.net/",
    "body": "
    client_id=c84a01bb-4f19-4eef-9941-4ab537922039
    scope=openid profile https://b2cmultitenant.onmicrosoft.com/mtrest/User.Invite https://b2cmultitenant.onmicrosoft.com/mtrest/User.ReadAll offline_access
    grant_type=refresh_token
    client_info=1
    x-client-SKU=msal.js.browser
    x-client-VER=2.16.0
    x-client-OS=
    x-client-CPU=
    x-ms-lib-capability=retry-after,h429
    x-client-current-telemetry=5|61,0,,,|@azure/msal-react,1.0.1
    x-client-last-telemetry=5|0|||0,0
    client-request-id=184306fa-1441-42aa-92a5-ca1d10c611a1
    refresh_token=eyJraWQiOiJ6a0hnRXNIQ0xZVDV2N0dyczRhLUo1WldpZXdoOVpJVzVWTDREODJqWE...
    X-AnchorMailbox=Oid:f91f6134-5da3-45d1-b3f1-9dcafecfead1-b2c_1a_v2signin@d06b10f6-c712-40c1-9617-cec9c7d02390",
    "method": "POST",
    "mode": "cors"
}

And below the response (with tokens truncated...):

{
  "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIs...",
  "id_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIs...",
  "token_type": "Bearer",
  "not_before": 1669196431,
  "expires_in": 3600,
  "expires_on": 1669200031,
  "resource": "8c8fefff-0743-499c-a26f-f5cf9f68b197",
  "client_info": "eyJ1aWQiOiJmOTFmNjEzNC01ZGEzLTQ1ZDE...",
  "scope": "https://b2cmultitenant.onmicrosoft.com/mtrest/User.Invite https://b2cmultitenant.onmicrosoft.com/mtrest/User.ReadAll",
  "refresh_token": "eyJraWQiOiJ6a0hnRXNIQ0xZVDV2N0dyczR...",
  "refresh_token_expires_in": 86355
}

Request with our application:

URL: https://{tenantName}.b2clogin.com/{tenantId}/b2c_1a_v2signin/oauth2/v2.0/token

{
    "credentials": "omit",
    "headers": {
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:107.0) Gecko/20100101 Firefox/107.0",
        "Accept": "*/*",
        "Accept-Language": "en-US,en;q=0.5",
        "content-type": "application/x-www-form-urlencoded;charset=utf-8",
        "Sec-Fetch-Dest": "empty",
        "Sec-Fetch-Mode": "cors",
        "Sec-Fetch-Site": "cross-site",
        "Pragma": "no-cache",
        "Cache-Control": "no-cache"
    },
    "referrer": "http://localhost:3000/",
    "body": "
    client_id=605b9c05-f7af-4131-9948-1b62a340433f
    scope=openid profile https://jamixg6b2cweu.onmicrosoft.com/mtrest/User.Invite https://jamixg6b2cweu.onmicrosoft.com/mtrest/User.ReadAll offline_access
    grant_type=refresh_token
    client_info=1
    x-client-SKU=msal.js.browser
    x-client-VER=2.31.0
    x-ms-lib-capability=retry-after, h429
    x-client-current-telemetry=5|61,0,,,|@azure/msal-react,1.4.10
    x-client-last-telemetry=5|0|||0,0
    client-request-id=39268f43-0dc4-4477-92c9-b85d41d0273b
    refresh_token=eyJraWQiOiJNNzNVVkh5TjBxX19lTUpTcjFDaHpxeWx0em8tNF9WTEdKR3dUY1d...",
    "method": "POST",
    "mode": "cors"
}

and the response:

{
  "id_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUz...",
  "token_type": "Bearer",
  "not_before": 1669206154,
  "client_info": "eyJ1aWQiOiJjNzdkYmNlZS0zNzRiLT...",
  "scope": "",
  "refresh_token": "eyJraWQiOiJNNzNVVkh5TjBxX19lTU...",
  "refresh_token_expires_in": 86274
}
codepic commented 1 year ago

Turns out I need to:

  1. Open the SPA Application Registration in B2C App Registrations
  2. Click API Permissions
  3. Click Add a permission
  4. In the opening blade, select My APIs tab
  5. Select the B2C API application registration from the list
  6. Tick all permissions you want to generate an access token for
  7. Click Add permissions

If the api permissions listed in scopes of the request in tenant.jsx are not mapped to the application (clientId) requesting the access token, the token endpoint will not return access token. Nor any error will be produced.

mrochon commented 1 year ago

Sorry for your troubles and thanks for your comments. Your solution is correct, though seems to be missing one more step: Grant admin consent for B2C...: in B2C all API scopes have to be pre-consented by the administrator, you cannot ask for them at run-time and have the user consent then (like you can in AAD enterprise). Therefore, in B2C you have to assign API permissions to the client through the portal and consent to them before requesting tokens at runtime. I have added some more details to the documentation.