user4266661
user4266661

Reputation:

Configuring Azure AD B2C ApiScopes and ApiUrl

I'm having trouble configuring an AspNet Core 2.1 website to use Azure AD B2C for authentication. I've got this example to work, but when I try to adapt it to my own AD B2C tenant I get an invalid operation exception in the following code:

   private async Task OnAuthorizationCodeReceived(AuthorizationCodeReceivedContext context)
    {
        var clientCredential = new ClientCredential(context.Options.ClientSecret);
        var userId = context.Principal.FindFirst(ClaimTypes.NameIdentifier).Value;
        var tokenCache = new SessionTokenCache(context.HttpContext, userId);

        var confidentialClientApplication = new ConfidentialClientApplication(
            context.Options.ClientId,
            context.Options.Authority,
            _options.RedirectUri,
            clientCredential,
            tokenCache.GetInstance(),
            null);

        try
        {
            // this next line throws the exception
            var authenticationResult = await confidentialClientApplication.AcquireTokenByAuthorizationCodeAsync(context.ProtocolMessage.Code, _options.ApiScopes.Split(' '));
            context.HandleCodeRedemption(authenticationResult.AccessToken, authenticationResult.IdToken);
        }
        catch (Exception ex)
        {
            // TODO: Handle
            throw;
        }
    }

The exception detail is:

Microsoft.Identity.Client.MsalServiceException HResult=0x80131500
Message=AADSTS50049: Unknown or invalid instance. Trace ID: 1391c6be-c8f7-4c05-a575-b4998f79d800 Correlation ID: 8b83a695-000f-44c2-99c1-d779725342da Timestamp: 2018-09-27 02:05:02Z
Source=Microsoft.Identity.Client StackTrace: at Microsoft.Identity.Client.Internal.OAuth2.OAuth2Client.CreateErrorResponse(HttpResponse response, RequestContext requestContext) at Microsoft.Identity.Client.Internal.OAuth2.OAuth2Client.CreateResponse[T](HttpResponse response, RequestContext requestContext, Boolean addCorrelationId)
at Microsoft.Identity.Client.Internal.OAuth2.OAuth2Client.d__91.MoveNext() at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.Identity.Client.Internal.OAuth2.OAuth2Client.<DiscoverAadInstanceAsync>d__7.MoveNext() at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.Identity.Client.Internal.Instance.AadAuthority.<GetOpenIdConfigurationEndpointAsync>d__4.MoveNext() at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.Identity.Client.Internal.Instance.Authority.<ResolveEndpointsAsync>d__45.MoveNext() at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.Identity.Client.Internal.Requests.RequestBase.<ResolveAuthorityEndpointsAsync>d__37.MoveNext() at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.Identity.Client.Internal.Requests.RequestBase.<PreTokenRequestAsync>d__36.MoveNext() at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.Identity.Client.Internal.Requests.RequestBase.<RunAsync>d__33.MoveNext() at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.Identity.Client.ConfidentialClientApplication.<AcquireTokenByAuthorizationCodeCommonAsync>d__17.MoveNext() at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.Identity.Client.ConfidentialClientApplication.<AcquireTokenByAuthorizationCodeAsync>d__4.MoveNext() at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter
1.GetResult() at RideMonitorSite.AzureADB2COpenIdConnectOptionsConfigurator.d__5.MoveNext() in C:\Programming\RideMonitorServer\RideMonitorSite\AzureADB2COpenIDConnectOptionsConfigurator.cs:line 58

From examining the arguments passed to the function that throws the exception, I noticed that _options.ApiScopes is set to:

https://ridemonitor.onmicrosoft.com/api/user.read

which is as I configured it in the app. The tenant app configuration has the api url set to the "folder" of that Url (i.e., everything excluding the user.read)...but I'm not sure what other configuration I should be doing in the tenant app. How does it know what user.read means?

If someone can point me to some introductory material on how AD B2C should be set up, that would be appreciated. The stuff I've found so far presumes a level of knowledge that I clearly don't have.

Upvotes: 1

Views: 938

Answers (1)

Chris Padgett
Chris Padgett

Reputation: 14704

If you are using the your-tenant-name.b2clogin.com domain with MSAL, then (at the time of this writing) you must:

  1. Ensure Authority contains the /tfp path because this is how MSAL infers it is interacting with an Azure AD B2C tenant.
  2. Set the ValidateAuthority to false.

Upvotes: 2

Related Questions