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

B2C does not always issue access token but TokenResponse assumes there is an access token resulting in a JSON parse error #140

Closed
alex-mason-by opened this issue Dec 7, 2019 · 13 comments
Assignees
Labels
Service Issue Issue is in some other part of the Identity platform, outside of MSAL Java itself Work-around Provided Issue has a known work-around, which could one day be integrated into MSAL Java
Milestone

Comments

@alex-mason-by
Copy link

Using MSAL4J library with B2C can result in a JSON parse error due to an assumption in TokenResponse that doesn't always hold with B2C and that assumption is that an access token is always returned. The refresh token has the same assumption although perhaps that is fine? In the case where MSAL4J is used for a server-side application login that needs no custom scope then no access token is returned and this code should not blow up on that scenario.

https://github.com/AzureAD/microsoft-authentication-library-for-java/blob/dev/src/main/java/com/microsoft/aad/msal4j/TokenResponse.java#L48
final AccessToken accessToken = AccessToken.parse(jsonObject);
final RefreshToken refreshToken = RefreshToken.parse(jsonObject);

@sangonzal
Copy link
Contributor

@alex-mason-jdas Acknowledged, I am able to reproduce this error. Discussing possible solutions with the team, will update this issue once we have a ETA for a fix.

@sangonzal sangonzal added the Bug Something isn't working, needs an investigation and a fix label Dec 12, 2019
@navyasric navyasric added this to the MSAL Java 1.3 milestone Dec 17, 2019
@sangonzal sangonzal added this to To do in MSAL Java Board Dec 20, 2019
@sangonzal sangonzal moved this from To do to In progress in MSAL Java Board Jan 7, 2020
@sangonzal sangonzal self-assigned this Jan 7, 2020
@sangonzal
Copy link
Contributor

@alex-mason-jdas Can you please share details about the scenario where you are trying to acquire just an Id token and no access token or refresh token? Is there any reason why are not requesting the access/ refresh tokens?

@alex-mason-by
Copy link
Author

That is the default behavior of B2C if there is no custom scope requested, so it would be a scenario that is just a sign in scenario (monolithic app perhaps). You can see indication in the provided link. I myself don't really agree with the implementation of B2C and think it ought to always return an access token, but it does not if there is no custom scope meaning that this application does not need to call some other web API resource. As far as refresh token, well that really depends on whether the nature of the application needs a longer life or not, doesn't it? In any case, I think you really need to discuss with the B2C team. I am just reporting the behavior since MSAL4J claims to support B2C and this is kind of a basic error. Perhaps the resolution is on the B2C side but it's one of the two and should not really be put back on the user of MSAL nor B2C.

https://docs.microsoft.com/en-us/azure/active-directory-b2c/active-directory-b2c-reference-oidc

@sangonzal
Copy link
Contributor

@alex-mason-jdas Thanks for expanding.

I've had a chance to dig in a bit deeper and chat with the B2C team. They should be returning access tokens on all successful token responses. This is a bug on their end which they are now aware of.

We won't make any changes to MSAL. While they fix this problem, you can workaround this issue by including the client id of the application as a scope, which will cause B2C to then return an access token. I will leave this issue open until B2C fixes so if anybody else runs into this they can see the workaround.

@sangonzal sangonzal added Service Issue Issue is in some other part of the Identity platform, outside of MSAL Java itself Work-around Provided Issue has a known work-around, which could one day be integrated into MSAL Java and removed Bug Something isn't working, needs an investigation and a fix labels Jan 10, 2020
@sangonzal sangonzal moved this from In progress to Done in MSAL Java Board Jan 10, 2020
@psidnell
Copy link

psidnell commented May 6, 2020

Hi, Thanks for the workaround, it instantly fixed the issue.

However, I'd like to suggest mentioning this issue prominently in the README, I downloaded the sample code days ago and and have been looking for errors in my ADD+B2C instance that didn't exist.

I have a couple of operational questions:

  1. Is it known if this fix is a benign in the future - i.e. will it continue to work when the underlying B2C bug is fixed?
  2. Does anyone have a reference to the underlying B2C bug so we can track it?

Thanks

@sangonzal
Copy link
Contributor

@psidnell We will add a snippet to the README.

  1. Yes I expect using client id will always work, otherwise it would break everyone who is doing so now.
  2. I'm not aware of any other places where this is being tracked. I will continue to check up with the B2C team and update this issue accordingly.

@bpossolo
Copy link

Just ran into this exact same issue and have been debugging the MSAL code for hours trying to understand what I'm doing wrong. Finally decided to check the Github Issues tab and I saw this!
+1 to mentioning this somewhere on the website docs until it gets fixed.

I'm not providing any scopes beyond "openid profile" (although i noticed under the hood it always adds "offline_access" on top of the ones i specified (which might be a separate bug).

Here's an example of what im getting back from the authorization code -> token exchange (I obfuscated my id/refresh tokens and client info for security).

{
   "id_token":"blah",
   "token_type":"Bearer",
   "not_before":1591770872,
   "client_info":"blah",
   "scope":"",
   "refresh_token":"blah",
   "refresh_token_expires_in":1209600
}

@bpossolo
Copy link

this issue also exists when using the MSAL.js 2.0 (https://github.com/AzureAD/microsoft-authentication-library-for-js/tree/dev/lib/msal-browser).
I got around it by doing the same thing, including client-id as a scope:

const config = { ... msal config };
const auth = new msal.PublicClientApplication(config);
const params = {
  scopes: [clientId],
};
auth.loginRedirect(params);

@cserratore-av
Copy link

cserratore-av commented Sep 14, 2021

I've been struggling to get the msal-b2c-web-sample working for a while due to this issue and even the stated workaround isn't resolving the problem for me.

you can workaround this issue by including the client id of the application as a scope, which will cause B2C to then return an access token

I've tried every combination of the scopes below (I've temporary disabled the external API scope, which also didn't resolve the issue):

      String redirectUrl = authority.replace("/tfp", "") + "oauth2/v2.0/authorize?" +
                "response_type=code&" +
                "response_mode=query&" +
                "redirect_uri=" + URLEncoder.encode(authHelper.configuration.redirectUri, "UTF-8") +
                "&client_id=" + authHelper.configuration.clientId +
                "&scope=" + URLEncoder.encode("openid offline_access profile f1e4d28b-fa28-b734-b70b-3ae6a1caf972 " /* +
                authHelper.configuration.apiScope */, "UTF-8") +
                (StringUtils.isEmpty(claims) ? "" : "&claims=" + claims) +
                "&prompt=select_account" +
                "&state=" + state
                + "&nonce=" + nonce;

I can see in the debugger that the JSON response object from B2C being parsed does not include an access token, similar to what @bpossolo reported, resulting in the JSON parse exception.

I have both ID and Access tokens enabled in the B2C configuration of my client application:

Select the tokens you would like to be issued by the authorization endpoint:
X Access tokens (used for implicit flows)
X ID tokens (used for implicit and hybrid flows)

What am I missing that others commenting in this issue seem to overcome?

@inventivejon
Copy link

Would be interested in the answer too. Having the same issue...

@bpossolo
Copy link

bpossolo commented Jan 24, 2022

@inventivejon @cserratore-av include the client application's Client ID in the list of scopes.
In Azure B2C, the Client ID and Application ID are synonymous (visible under Azure AD B2c -> App Registrations in Azure Portal)

@bpossolo
Copy link

bpossolo commented Feb 24, 2022

This appears to be expected behavior as it's now documented in Azure B2C.

The OpenID Connect standard specifies several special scope values. The following scopes represent the permission to access the user's profile:

  • openid - Requests an ID token.
  • offline_access - Requests a refresh token using Auth Code flows.
  • 00000000-0000-0000-0000-000000000000 - Using the client ID as the scope indicates that your app needs an access token that can be used against your own service or web API, represented by the same client ID.

If the response_type parameter in an /authorize request includes token, the scope parameter must include at least one resource scope other than openid and offline_access that will be granted. Otherwise, the /authorize request fails.

@siddhijain
Copy link
Contributor

Closing this as it is now documented and is an expected behaviour.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Service Issue Issue is in some other part of the Identity platform, outside of MSAL Java itself Work-around Provided Issue has a known work-around, which could one day be integrated into MSAL Java
Projects
Archived in project
MSAL Java Board
  
Done (in next release)
Development

No branches or pull requests

9 participants