Azure-Samples/active-directory-b2c-dotnetcore-webapp

ERROR Account username: Missing from the token response environment login.microsoftonline.com home account id: AccountId: XXXX

mamood opened this issue · 8 comments

Hello,

I receive this message in the API sample code as below:

image

and on further inspection, it shows the Username value to be Missing from the token response:

image

Couldn't find any workarounds but did find the issue documented here at microsoft-authentication-library-for-dotnet:

B2C notes
ADAL does not support B2C and there are no plans to add B2C support. As such, MSAL will not write B2C tokens to the ADAL token cache. In B2C, currently, the displayName (aka username aka preferred username) is null. This is a "bug" in B2C as they should provide a scope for the username. DisplayName should never be null - it would be a schema violation for it to be null. We have code that adds a constant (smth like "Missing from the token response") in these cases.

Not sure there is much that can be done about this for now... any suggestions? Thanks.

@mamood What you found is correct.
This is a known issue w/B2C. The reason is because B2C does not return a value in the IdToken for preferred username because of the limitations with the social accounts. For example, AAD does return a value here because it knows who the user is, but for b2c, because the user can sign in with a local account, FB, Github, etc...there is not a consistent value for them to use for preferred username. Also, some social accounts (like Github) don't require email. So...to unblock MSAL from rolling out cache compatibility with ADAL, we decided to use "Missing from the token response" on our end when dealing with the B2C accounts.
You can, however, use the "name" claim as the preferred username. I believe you can add that in the policy. If you need more information on this, let me know and I'll sync w/B2C. It's generally mentioned in this B2C doc -> "In the Return claim column, choose claims you want returned in the authorization tokens sent back to your application after a successful profile editing experience. For example, select Display Name, Postal Code.”

closing, as this is by design currently, but please tag me if you need more guidance on this.

@jennyf19 Can you please explain the steps to fix the issue. somehow I am not able to do the above-mentioned step to fix the issue.

@tarun00197 what are you trying to do?

Hi jennyf19, I am also trying to get this message not to display. I've been through the articles and I must be missing something. Please could you point me in the direction of a step by step process to get the 'user' or simply clear the message. I've been though the "articleB2C doc" and cant find the solution.

@ryanglenn79 @tarun00197
Not sure if this will help.
In the portal, under the policy you want to target, go to Application Claims blade and make sure Display Name is enabled:
image

When i have this enabled, in the AuthResult, in the idToken, you'll see the name value:
image
If not, you won't see it:
image

You can parse the idToken to get the claims. You can do something like this:

private void DisplayUserInfo(AuthenticationResult authResult)
{
            TokenInfoText.Text = "";
            if (authResult != null)
            {
                JObject user = ParseIdToken(authResult.IdToken);

                TokenInfoText.Text += $"Name: {user["name"]?.ToString()}" + Environment.NewLine;
                TokenInfoText.Text += $"User Identifier: {user["oid"]?.ToString()}" + Environment.NewLine;
                TokenInfoText.Text += $"Street Address: {user["streetAddress"]?.ToString()}" + Environment.NewLine;
                TokenInfoText.Text += $"City: {user["city"]?.ToString()}" + Environment.NewLine;
                TokenInfoText.Text += $"State: {user["state"]?.ToString()}" + Environment.NewLine;
                TokenInfoText.Text += $"Country: {user["country"]?.ToString()}" + Environment.NewLine;
                TokenInfoText.Text += $"Job Title: {user["jobTitle"]?.ToString()}" + Environment.NewLine;

                if (user["emails"] is JArray emails)
                {
                    TokenInfoText.Text += $"Emails: {emails[0].ToString()}" + Environment.NewLine;
                }
                TokenInfoText.Text += $"Identity Provider: {user["iss"]?.ToString()}" + Environment.NewLine;
            }
}

Hi Jenny
Thank you for answering. I have everything already setup as you suggest, and I am receiving "Display Name", however I am still receiving "Account username: Missing from the token response environment"

When executing

IEnumerable<IAccount> accounts = await PCA.GetAccountsAsync();

The this displays in the email field for logging in.

@jennyf19

I am getting the same behavior when calling PCA.GetAccountsAsync() from MSAL .net library. I see in the token that the name property is coming down properly from azure when decoding the token but it doesn't appear to get set on the Account object for the token cache. According to https://docs.microsoft.com/en-us/azure/active-directory/develop/msal-net-aad-b2c-considerations

I believe you mentioned this in above post..

Mitigation for "Missing from the token response"
One option is to use the "name" claim as the preferred username. The process is mentioned in this B2C doc -> "In the Return claim column, choose the claims you want returned in the authorization tokens sent back to your application after a successful profile editing experience. For example, select Display Name, Postal Code.”

I tried following the reference mentioned above to https://docs.microsoft.com/en-us/azure/active-directory-b2c/user-flow-overview but I don't see any mention of the process mentioned above.

I have tried to adding all the application claims that you have shown in your screenshot and still am not getting the username field to populate on the Account object when calling PCA.GetAccountsAsync().

You aren't using that in your example and instead are parsing the token for the claims which is working but that doesn't seem like it would work with the token cache in the MSAL library without getting a username when using local accounts.

I could be misunderstanding something but above are the steps I have taken to try and resolve. I can see a work around by maybe using the oid or sub claim and after acquiring the token and sending to client the first time it can get sent back up in the token and parsed to filter the MSAL Accounts object by oid for token cache account filtering. It would be nice to be able to use the name claim but MSAL doesn't seem to properly work with it. Does that sound correct?

@ryanglenn79 @chris-skuvault Including "name" back in the claims has no impact on the MSAL cache. It will be included in the id_token, so you can filter there and display the user name if you want. You won't be able to get the name from the Account object. Sorry that was not clear.

There is only one cache per user, but each user will have multiple accounts or tokens in the cache, as each B2C policy is a separate IdP, so that's why you have to filter by policy.