microsoft-authentication-library-for-dotnet: [Question] Using ROPC flow in Azure AD B2C AcquireTokenByUsernamePassword returning bad request

Which Version of MSAL are you using ? MSAL 4.9.0

Platform netcore3.1

What authentication flow has the issue?

  • Desktop / Mobile
    • Interactive
    • Integrated Windows Auth
    • [ ] Username Password
    • Device code flow (browserless)

Other?

Is this a new or existing app? new library i’m writing

Expected behavior When calling AcquireTokenByUsernamePassword then expect a success response back.

Actual behavior Get a response back saying “AADB2C90057: The provided application is not configured to allow the OAuth Implicit flow.”

 at Microsoft.Identity.Client.OAuth2.OAuth2Client.ThrowServerException(HttpResponse response, RequestContext requestContext)
   at Microsoft.Identity.Client.OAuth2.OAuth2Client.CreateResponse[T](HttpResponse response, RequestContext requestContext, Boolean addCorrelationId)
   at Microsoft.Identity.Client.OAuth2.OAuth2Client.ExecuteRequestAsync[T](Uri endPoint, HttpMethod method, RequestContext requestContext, Boolean expectErrorsOn200OK)
   at Microsoft.Identity.Client.OAuth2.OAuth2Client.GetTokenAsync(Uri endPoint, RequestContext requestContext)
   at Microsoft.Identity.Client.OAuth2.TokenClient.SendHttpMessageAsync(String tokenEndpoint)
   at Microsoft.Identity.Client.OAuth2.TokenClient.SendTokenRequestAsync(IDictionary`2 additionalBodyParameters, String scopeOverride, String tokenEndpointOverride, CancellationToken cancellationToken)
   at Microsoft.Identity.Client.Internal.Requests.RequestBase.SendTokenRequestAsync(String tokenEndpoint, IDictionary`2 additionalBodyParameters, CancellationToken cancellationToken)
   at Microsoft.Identity.Client.Internal.Requests.UsernamePasswordRequest.ExecuteAsync(CancellationToken cancellationToken)
   at Microsoft.Identity.Client.Internal.Requests.RequestBase.RunAsync(CancellationToken cancellationToken)
   at Microsoft.Identity.Client.ApiConfig.Executors.PublicClientExecutor.ExecuteAsync(AcquireTokenCommonParameters commonParameters, AcquireTokenByUsernamePasswordParameters usernamePasswordParameters, CancellationToken cancellationToken)
   at SkuVault.Access.AzureB2CTokenService.AcquireTokenByUsernamePasswordAsync(String userName, String password) in C:\Git\sv-ms-graph\SkuVault.Access\SkuVault.Access\AzureB2CTokenService.cs:line 43
   at SkuVault.Access.Tests.AzureB2CTokenServiceTests.Test1() in C:\Git\sv-ms-graph\SkuVault.Access\SkuVault.Access.Tests\AzureB2CTokenServiceTests.cs:line 35
   at NUnit.Framework.Internal.TaskAwaitAdapter.GenericAdapter`1.BlockUntilCompleted()
   at NUnit.Framework.Internal.MessagePumpStrategy.NoMessagePumpStrategy.WaitForCompletion(AwaitAdapter awaitable)
   at NUnit.Framework.Internal.AsyncToSyncAdapter.Await(Func`1 invoke)
   at NUnit.Framework.Internal.Commands.TestMethodCommand.RunTestMethod(TestExecutionContext context)
   at NUnit.Framework.Internal.Commands.TestMethodCommand.Execute(TestExecutionContext context)
   at NUnit.Framework.Internal.Execution.SimpleWorkItem.PerformWork()

Additional context/ Logs / Screenshots Having issue finding information about this particular error message. I don’t have the implict flow configured and am using the Username Password flow so I’m not sure what the error message is referring too. Was wondering if anyone else has seen this behavior. I followed this article for guidlines on using the flow https://docs.microsoft.com/en-us/azure/active-directory-b2c/configure-ropc?tabs=applications.

Client Creation:

var clientApp = PublicClientApplicationBuilder.Create(<ClientId>)
.WithB2CAuthority("https://<Tenant>.b2clogin.com/tfp/<Tenant>.onmicrosoft.com/B2C_1_ROPC_AUTH").Build();

Where AcquireTokenByUsernamePassword is called

_scopes = new List<string> {"https://graph.microsoft.com/User.ReadWrite.All" };
try
{
        result = await _app.AcquireTokenSilent(_scopes,
	accounts.FirstOrDefault()).ExecuteAsync(_token);
}
catch (MsalUiRequiredException ex)
{
	result = await _app.AcquireTokenByUsernamePassword(_scopes, userName, securePassword).ExecuteAsync(_token);
}

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Reactions: 1
  • Comments: 15 (8 by maintainers)

Most upvoted comments

Happy to discuss any issues you encounter.

I don’t think this works as well as you would hope. I took my working B2C WinUI application and ripped the authentication code out, place the authentication code in a simple console application, and ran it. I got an embedded Web Browser to pop up, but it had nothing in it. Same Public Client Application id, same scope, same URI callback, empty login dialog.

I’ve decided that this console application (it loads data into the shared data model) is a confidential application as it’s function is closer to a daemon than an end-user application. I’m switching to a Confidential Client Application and having better luck.

Thanks for the philosophical justification that allowed me to investigate the Confidential Client App for this feature.

An app registered in azure ad b2c tenant doesn’t support the use of the mircosoft graph api permissions set on the registered application attached to the tenant?

  • Azure AD B2C Application registrations cannot request any tokens for Microsoft APIs, or Microsoft Services.

  • You can create Azure AD Application Registrations within your AAD B2C tenant. These can request any tokens for Microsoft APIs, or Microsoft Services (that don’t require a licensed).

  • Azure AD B2C Application registrations can request any tokens for your own APIs and their corresponding Application Registrations, by passing in their identifierURI and Scope in the Scopes parameter in MSAL.

  • Your own APIs can request tokens to Microsoft APIs, or Microsoft Services by leveraging AAD App Registrations within your AAD B2C directory. This works just like having a normal Azure AD (client_credentials flow).

Unfortunately, our doc has a bug, when using the Application Registration (preview) menu to register an Azure AD B2C Application Registration, you must enable Implicit Flow (access token), for ROPC to work properly. This was being done for the Azure AD B2C application registrations automatically in the old menu. I don’t know why this is, but we are looking into it and the Doc fix will go out very shortly.

To fix your scenario:

  1. Register an AAD B2C App Reg to represent your backend API. And have this App registration expose “scopes”. Have the App Reg that represents the front end app consume these scope. This is all explained here.

The identifier URI of the backend App Registration and scope name are concatenated to obtain the scope used in the next step.

  1. In modify your application code as follows:
_scopes = new List<string> {"<identifier URI/scopename>" };
try
{
        result = await _app.AcquireTokenSilent(_scopes,
	accounts.FirstOrDefault()).ExecuteAsync(_token);
}
catch (MsalUiRequiredException ex)
{
	result = await _app.AcquireTokenByUsernamePassword(_scopes, userName, securePassword).ExecuteAsync(_token);
}
  1. In the front end application registration, open the manifest through the Application Registraion (preview) menu and set: "oauth2AllowImplicitFlow": true

  2. When the user authenticates to your application using ROPC, they will get an Id_token for the front end app reg, and an access_token with the scope to call the backend API.

If the user wants to interact with MS Graph API for example, you need to:

  1. Protect your API with Azure AD B2C authentication. Sample here.

  2. Create an Azure AD Application Registration inside your AAD B2C tenant, and provide Application permissions to Microsoft Graph API.

  3. Generate a Secret Key on the Application Registration.

  4. Use MSAL within your API to authenticate and obtain tokens to MS Graph API using the client_credentials.

Now the user uses their access token to call your API. Your API then gets a token using MSAL to MS Graph API (purely an Azure AD operation). API makes the call to Graph API then returns the data to the user.

@jmprieur I might be missing something but will try and sum up my experience trying to resolve this issue. I would appreciate any additional guidance you can give.

An app registered in azure ad b2c tenant doesn’t support the use of the mircosoft graph api permissions set on the registered application attached to the tenant?

I tried removing the ms graph scope and only supplying the openid and offline_access scope of my registered application’s “Application ID URI” i.e. https://<Tenant>.onmicrosoft.com/<AppIDURI>/ openid and https://<Tenant>.onmicrosoft.com/<AppIDURI>/offline_access and and am still getting back the same error response.

I’m not sure this is correct because it seems the openid and offline_access scope live off of the https://graph.microsoft.com/ permissions endpoint i.e. https://graph.microsoft.com/offline_access and https://graph.microsoft.com/openid. Do I need to create these two scopes myself as custom scopes in my App Registration then add the permissions to my app registration “Configured permissions”?

How do I make ROPC sign-in flow work in azure ad b2c work properly using AcquireTokenByUsernamePassword call in MSAL? Is this possible using MSAL library? Or do I need to construct the request myself by hand via https://docs.microsoft.com/en-us/azure/active-directory-b2c/configure-ropc?tabs=app-reg-preview based on examples of request in the article.

It looked possible that MSAL could support this given that there are methods like WithB2CAuthority and AcquireTokenByUsernamePassword and in the documentation for this repo https://github.com/AzureAD/microsoft-authentication-library-for-dotnet/wiki/AAD-B2C-specifics#resource-owner-password-credentials-ropc-with-b2c it looks like it should be supported.

The error message mentioned below getting returned from azure is useless in determining anything. I already know i’m not configured to use the OAuth implicit flow I’m trying to use a different flow intentionally so this message makes no sense.

{"error":"unauthorized_client","error_description":"AADB2C90057:` The provided application is not configured to allow the OAuth Implicit flow.\r\nCorrelation ID: a2c7c5c7-6e8b-4807-a0bc-2822bd640ed7\r\nTimestamp: 2020-03-19 19:21:24Z\r\n"}