I have recently setup a Azure AD BC2 with two web apis and one native application. I can successfully use the Microsoft.Identity.Client nuget package in a legacy Windows Forms app and get authorization to call one of my apis. When I configure the second api with its appropriate .read and .write scopes I get this error (I've replaced my actual tenant domain with myb2c):
Users:
Error Acquiring Token:
Microsoft.Identity.Client.MsalServiceException: AADB2C90146:
The scope 'https://myb2c.onmicrosoft.com/customerapi/customer.read
https://myb2c.onmicrosoft.com/customerapi/customer.write
https://myb2c.onmicrosoft.com/vendorapi/vendor.read
https://myb2c.onmicrosoft.com/vendorapi/vendor.write offline_access openid profile'
provided in request specifies more than one resource for an access token, which is not supported.
Correlation ID: 8e9e9653-61bd-4a6f-9e42-3abeed814482
Timestamp: 2018-04-18 21:02:08Z
at Microsoft.Identity.Client.Internal.Requests.InteractiveRequest.VerifyAuthorizationResult()
Any ideas on what I'm doing wrong or what I need to do do instead?
the Azure AD V2 endpoint allow you to get a token for only one resource at once, however, you can let the user pre-consent for several resources. Please see How to get consent for several resources.
My impression is that you have two resources here:
https://myb2c.onmicrosoft.com/customerapi (with 2 scopes customer.read and customer.write)https://myb2c.onmicrosoft.com/vendorapi (with 2 scopes vendor.read and vendor.write)therefore you should use an override of AcquireTokenAsync which has the extraScopesToConsent parameter.
For instance:
string[] scopesForCustomerApi = new string[]
{
"https://myb2c.onmicrosoft.com/customerapi/customer.read",
"https://myb2c.onmicrosoft.com/customerapi/customer.write"
};
string[] scopesForVendorApi = new string[]
{
"https://myb2c.onmicrosoft.com/vendorapi/vendor.read",
"https://myb2c.onmicrosoft.com/vendorapi/vendor.write"
};
var result = await app.AcquireTokenAsync(scopesForCustomerApi,
app.Users.FirstOrDefault(),
uiBehavior,
string.Empty,
scopesForVendorApi);
This will get you an access token for the first Web API.
Then when you need to call the second one, you can call AcquireTokenSilentAsync(scopesForVendorApi);
@stumpykilo closing this as I believe I've answered. Feel free to reopen if you still experience the issue after doing what I recommended.
@jmprieur, please re-open. We have exactly the same issue with B2C as OP. What you wrote is right for Azure AD v2. Azure AD v2's authorize endpoint accepts scopes for multiple resources followed by token endpoint calls to get each access token separately. In case of B2C, the same flow will end up with AADB2C90146 error on authorize endpoint (exactly the same exception as OP wrote about).
What we found is working is to call AcquireTokenAsync() few times to get each access token separately. When calling it for second time we can set UIBehaviour to Consent or Never to display browser only for a moment without the need to re-enter credentials. How to do it in a better way, so that we can get both access tokens without additional flashes?
PS: I know that UIBehaviour.Never would cause to hide the browser on Windows, but we need it to work on mobile platforms as well.
Thanks for the additional information @pasn
We'll get back to you and @stumpykilo
This problem still persists with MSAL v2.3.0.
AuthenticationResult authResult = await App.AuthenticationClient.AcquireTokenAsync(
AuthenticationConstants.CustomerScopes,
firstAccount,
UIBehavior.SelectAccount,
string.Empty,
AuthenticationConstants.VendorScopes,
AuthenticationConstants.Authority,
App.UiParent
);
Still causes the AADBC90146 error.
By the way: The authority parameter may not be empty and is not documented.