Microsoft-authentication-library-for-dotnet: Cannot acquire token in web app context.

Created on 9 May 2018  路  12Comments  路  Source: AzureAD/microsoft-authentication-library-for-dotnet

I am running a web app hosted in iis express at http://localhost:52419/ and the calls get stuck in token generation forever. But when I test the method from console, it all works fine : there is no problem with token generation (await daemonClient.AcquireTokenForClientAsync(new[] {msGraphScope});.

  <add key="AuthorityFormat" value="https://login.microsoftonline.com/{0}/v2.0" />
<add key="RedirectUri" value="https://localhost:44316/" />
<add key="MsGraphScope" value="https://graph.microsoft.com/.default" />
public static GraphServiceClient GetAuthenticatedClient(ApplicationIdentity applicationIdentity,
            string tenantId)
        {
            var authorityFormat = ConfigurationManager.AppSettings["AuthorityFormat"];
            var redirectUri = ConfigurationManager.AppSettings["RedirectUri"];
            var msGraphScope = ConfigurationManager.AppSettings["MsGraphScope"];

            var graphClient = new GraphServiceClient(
                new DelegateAuthenticationProvider(
                    async requestMessage =>
                    {
                        var daemonClient =
                            new ConfidentialClientApplication(applicationIdentity.Id,
                                string.Format(authorityFormat, tenantId), redirectUri,
                                new ClientCredential(applicationIdentity.Secret),
                                null, new TokenCache());
                        var authResult =
                            await daemonClient.AcquireTokenForClientAsync(new[] {msGraphScope}); // When run application as web then the call gets stuck here forever.

                        // Append the access token to the request.
                        requestMessage.Headers.Authorization =
                            new AuthenticationHeaderValue("bearer", authResult.AccessToken);
                    }));
            return graphClient;
        }

Most helpful comment

glad to read it did, @sameerkattel, and thanks for the update!
@jennyf19 : we need to be explicit about this in the conceptual documentation (in the Client Creds section, add a paragraph for ASP.NET controllers that need to be async, and a troubleshooting FAQ for MT.

All 12 comments

@sameerkattel - Did you set two redirect uri's, as noted in the sample you linked?
The base URL for https://localhost:44316/, as well as https://localhost:44316/Account/GrantPermissions

@jennyf19 Yes I have linked it. The token generation is working when run from console but it is not working when run as web app.

@sameerkattel - I don't see where you are doing anything with the authorization header, like in the sample

@sameerkattel sorry, indeed i read your comment too quickly. Client Creds is fine
Did you declare your asp.net web app as supporting async? for instance using an AsyncController ?

https://docs.microsoft.com/en-us/aspnet/web-forms/overview/performance-and-caching/using-asynchronous-methods-in-aspnet-45

@jennyf19 : It's being set but that only matters to make graph api calls. But I am not able to acquire the token itself. The token generation part is blocking forever.

 // Append the access token to the request.
                        requestMessage.Headers.Authorization =
                            new AuthenticationHeaderValue("bearer", authResult.AccessToken);

And again it's working when called from console app. It's only not working in web context.

@jmprieur : These methods are called from ApiController. Not sure what do I need to do to enable async calls. Do I need to add any configuration to enable async calls?

```
[HttpGet]
public HttpResponseMessage GetUserDetails()
{
var tentantId = Database.GetTenantId();
var appIdentity = Database.GetApplicationIdentity();
var graphClient = GetAuthenticatedClient(appIdentity, tentantId);

        // Make graph api calls

         var user=graphServiceClient.Me.Request().GetAsync().Result;

         // Do further processing
    }

```

@sameerkattel. I suspect you are experiencing a MT issue. I don't think that you should use .Result(). See Reminder: Do not call ADAL or MSAL async methods synchronously from the UI thread

I'd advise you change your controller action to be async and return Task<HttpResponseMessage>, and then change the following line to:

var user = await graphServiceClient.Me.Request().GetAsync();

GetAuthenticatedClient() does not seem async by itself so I think it's ok.
HTH

@jmprieur : I never read that part :) . Turning methods to async did the trick.

glad to read it did, @sameerkattel, and thanks for the update!
@jennyf19 : we need to be explicit about this in the conceptual documentation (in the Client Creds section, add a paragraph for ASP.NET controllers that need to be async, and a troubleshooting FAQ for MT.

@jmprieur Sounds good, I will update the docs.
@sameerkattel Glad you got it figured out

Was this page helpful?
0 / 5 - 0 ratings