Auth Infant
Auth Infant

Reputation: 1975

Calling AuthenticationContext.AcquireToken results in "enroll in multi-factor authentication" exception

I am writing a C# .NET app. It is connected to our service on Azure which is configured for using AAD. In turn, our service tries to make calls to Exchange via EWS.

All this used to work just fine for me. However, I just got a new dev box and now the exact same client/service code cannot authentication properly.

Everything seems to run fine up until the point that our service calls AuthenticationContext.AcquireToken. At that point, an AdalException is thrown with this message:

AADSTS50079: Due to a configuration change made by your administrator, or because you moved to a new location, you must enroll in multi-factor authentication to access '00000002-0000-0ff1-ce00-000000000000'. Trace ID: 1bf25608-ed26-477b-a2b4-379e20705260 Correlation ID: 449b5dce-dcb0-4d6a-83f2-dc906bbfd7c7 Timestamp: 2016-11-04 22:48:08Z

I'm not sure what it is about using this new machine that causes that error to occur. How do I 'enroll in multi-factor authentication' ? Why do I only have to do it when running my app on this machine?

Thanks!

Here is some of the auth code I teased out of our application to give a better picture of what is going on:

var bootstrapContext = ClaimsPrincipal.Current.Identities.First().BootstrapContext as System.IdentityModel.Tokens.BootstrapContext;

var upn = ClaimsPrincipal.Current.FindFirst(ClaimTypes.Upn);
var email = ClaimsPrincipal.Current.FindFirst(ClaimTypes.Email);
var userName =  upn != null ? upn.Value : email?.Value;

accessToken = bootstrapContext.Token;

ClientCredential clientCred = new ClientCredential("514b1e66-32af-4e11-a9d4-f9f1f4529dc0", appKey);
UserAssertion assertion = new UserAssertion(_accessToken, "urn:ietf:params:oauth:grant-type:jwt-bearer", userName);
AuthResult = authContext.AcquireToken("https://outlook.office365.com", clientCred, assertion);

Upvotes: 1

Views: 2138

Answers (1)

Auth Infant
Auth Infant

Reputation: 1975

Here is how I eventually fixed the problem: if AcquireToken is throwing an AdalException due to this MFA error, the server should also be sending back JSON content that tells you what claims your token is missing (notably the one for MFA). You can get the claims out of the JSON (How can I retrieve the JSON response from an AdalException?), then send them back to your client (or whatever code is running that the user is interacting with), and feed those missing claims back into the request to get the user token initially.

In my case, that meant getting the claims from the JSON, passing them back to my client, then putting the claims into my WebTokenRequest object that is passed into RequestTokenAsync:

var wtr = new WebTokenRequest(
    provider: m_wap,
    scope: "",
    clientId: m_clientId,
    promptType: promptType);
...
wtr.Properties.Add("claims", ExtraClaimsToRequestWhenAuthenticating);
...
return await WebAuthenticationCoreManager.RequestTokenAsync(wtr)

Now that the call to RequestTokenAsync has the missing claims in the request, it will either return a different token with the MFA claim or it will show the user UI to complete the MFA process then return a different claim (from my experience, showing UI is not always necessary). I then pass this new token back to my service which calls AcquireToken and works without the MFA error.

Upvotes: 1

Related Questions