Samuel Leung
Samuel Leung

Reputation: 95

Xamarin Forms OAuth 2.0 and Azure Active Directory - error AdalServiceException: AADSTS7000218

I was developing a Xamarin Forms app that require AD Login + MFA to obtain a token from AD. So that my client app can call my WebAPI using this token and WebAPI side can verify this token against Azure before serving the client.

I was using the NuGet extension Microsoft.IdentityModel.Clients.ActiveDirectory (v5.2.0) and the following is some related code for obtaining Azure token.

private static string aadInstance = "https://login.microsoftonline.com/{0}";
private static string tenant = "MY_TENANT_GUID";
private static string clientId = "MY_CLIENT_GUID";
private static Uri redirectUri = new Uri("MY_CLIENT_WEB_REDIRECT_URL");
private static string resourceId = "MY_CLIENT_GUID";
private static string authority = String.Format(CultureInfo.InvariantCulture, aadInstance, tenant);

...

//the line that try to get Azure token...
authContext = new AuthenticationContext(authority);
authResult = await authContext.AcquireTokenAsync(resourceId, clientId, redirectUri, platformParameters);

And I got the following error from Azure

{Microsoft.IdentityModel.Clients.ActiveDirectory.AdalServiceException: AADSTS7000218: The request body must contain the following parameter: 'client_assertion' or 'client_secret'.
Trace ID: ec487fae-628e-4c0a-a174-634f962e1000
Correlation ID: 3db513fc-79ca-417c-b0af-e34c112e77a8
Timestamp: 2019-08-21 02:26:05Z ---> Microsoft.IdentityModel.Clients.ActiveDirectory.AdalServiceException: Response status code does not indicate success: 401 (Unauthorized).
  at Microsoft.Identity.Core.OAuth2.OAuthClient+<GetResponseAsync>d__18`1[T].MoveNext () [0x00108] in D:\a\1\s\src\Microsoft.IdentityModel.Clients.ActiveDirectory\Core\OAuth2\OAuthClient.cs:66 
   --- End of inner exception stack trace ---
  at Microsoft.Identity.Core.OAuth2.OAuthClient+<GetResponseAsync>d__18`1[T].MoveNext () [0x00334] in D:\a\1\s\src\Microsoft.IdentityModel.Clients.ActiveDirectory\Core\OAuth2\OAuthClient.cs:116 
--- End of stack trace from previous location where exception was thrown ---
  at Microsoft.Identity.Core.OAuth2.OAuthClient+<GetResponseAsync>d__17`1[T].MoveNext () [0x00028] in D:\a\1\s\src\Microsoft.IdentityModel.Clients.ActiveDirectory\Core\OAuth2\OAuthClient.cs:45 
--- End of stack trace from previous location where exception was thrown ---
  at Microsoft.IdentityModel.Clients.ActiveDirectory.Internal.Flows.AcquireTokenHandlerBase+<SendHttpMessageAsync>d__75.MoveNext () [0x00053] in D:\a\1\s\src\Microsoft.IdentityModel.Clients.ActiveDirectory\Internal\Flows\AcquireTokenHandlerBase.cs:405 
--- End of stack trace from previous location where exception was thrown ---
  at Microsoft.IdentityModel.Clients.ActiveDirectory.Internal.Flows.AcquireTokenHandlerBase+<SendTokenRequestAsync>d__72.MoveNext () [0x00052] in D:\a\1\s\src\Microsoft.IdentityModel.Clients.ActiveDirectory\Internal\Flows\AcquireTokenHandlerBase.cs:333 
--- End of stack trace from previous location where exception was thrown ---
  at Microsoft.IdentityModel.Clients.ActiveDirectory.Internal.Flows.AcquireTokenHandlerBase+<CheckAndAcquireTokenUsingBrokerAsync>d__62.MoveNext () [0x000f5] in D:\a\1\s\src\Microsoft.IdentityModel.Clients.ActiveDirectory\Internal\Flows\AcquireTokenHandlerBase.cs:266 
--- End of stack trace from previous location where exception was thrown ---
  at Microsoft.IdentityModel.Clients.ActiveDirectory.Internal.Flows.AcquireTokenHandlerBase+<RunAsync>d__60.MoveNext () [0x0070e] in D:\a\1\s\src\Microsoft.IdentityModel.Clients.ActiveDirectory\Internal\Flows\AcquireTokenHandlerBase.cs:241 
--- End of stack trace from previous location where exception was thrown ---
  at Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext+<AcquireTokenCommonAsync>d__42.MoveNext () [0x000a1] in D:\a\1\s\src\Microsoft.IdentityModel.Clients.ActiveDirectory\AuthenticationContext.cs:608 
--- End of stack trace from previous location where exception was thrown ---
  at Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext+<AcquireTokenAsync>d__32.MoveNext () [0x00047] in D:\a\1\s\src\Microsoft.IdentityModel.Clients.ActiveDirectory\AuthenticationContext.cs:407 
--- End of stack trace from previous location where exception was thrown ---
  at ADM.Services.ADService+<ADLogin>d__8.MoveNext () [0x001b1] in C:\Users\[User]\Desktop\Source\[My App]\400 Implementation\ADM\ADM\ADM\Services\ADService.cs:83 
    ErrorCode: invalid_client
    StatusCode: 401}

However if I use ClientAssertion, I won't be able to ask user to use username password login (is that correct?). So I am stuck here.

Notes:

  1. I have actually tried another approach - create a WebAPI app and a native app in Azure app registration, that approach successfully obtain token but it doesn't trigger the MFA flow which my company need that as a security measure.

  2. I was told by other colleagues that native app doesn't support MFA, is that correct?

Any comments or suggestions will be welcome. Thanks in advance!

Upvotes: 1

Views: 535

Answers (1)

Jack Jia
Jack Jia

Reputation: 5549

In oauth2-auth-code-flow, the client secret parameter is required for web apps.

enter image description here

So, you need to add a public client (native) platform.

enter image description here

For the MFA issue, if you apply MFA via Azure Conditional Access Policy , it will apply multifactor authentication on modern app supported clients. Native clients might bypass MFA. But if you enforce MFA (via AzureAD MFA setting) it will enforce Multi factor authentication for all requests.

Here, I enforced MFA for my account: enter image description here

When I use the native app, I will be asked to provide additional verification.

Upvotes: 1

Related Questions