We have a NET Core 3.1 web application where users are authenticated in Azure AD with the Microsoft.Identity.Web package. We are calling the Microsoft Graph SDK on behalf of the signed in users as described here.
After logging in to the application everything works fine - all calls to Microsoft Graph SDK succeed. However, after about 30-60 minutes (we haven't timed it exactly) users remain authenticated in our application but calls to the Microsoft Graph SDK fail with the following error:
IDW10502: An MsalUiRequiredException was thrown due to a challenge for the user.
And the inner exception has:
Microsoft.Identity.Client.MsalUiRequiredException: No account or login hint was passed to the AcquireTokenSilent call.
Users then need to log out of the application and log back in, after which calls to MS Graph succeed again for 30-60 minutes.
Can anyone shed any light on this?
Our Setup
In appsettings.json :
{
"AzureAd": {
"Instance": "https://login.microsoftonline.com/",
"Domain": "<our-domain-name>",
"TenantId": "<our-tenant-id>",
"ClientId": "<our-client-id>",
"CallbackPath": "/signin-oidc",
"SignedOutCallbackPath ": "/signout-callback-oidc",
"ClientSecret": "<secret>"
},
"GraphBeta": {
"BaseUrl": "https://graph.microsoft.com/beta",
"Scopes": "User.Read Sites.Read.All Files.Read.All Sites.ReadWrite.All Files.ReadWrite.All",
"DefaultScope": "https://graph.microsoft.com/.default"
}
In Startup.cs :
services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp( Configuration.GetSection("AzureAd"))
.EnableTokenAcquisitionToCallDownstreamApi(new string[] { "User.Read","Sites.Read.All","Files.Read.All","Sites.ReadWrite.All","Files.ReadWrite.All" })
.AddMicrosoftGraph(Configuration.GetSection("GraphBeta"))
.AddDistributedTokenCaches();
services.AddDistributedSqlServerCache(options =>
{
options.ConnectionString = Configuration.GetConnectionString("AzureConnection");
options.SchemaName = "dbo";
options.TableName = "TokenCache";
});
The GraphServiceClient is injected into our controllers :
readonly ITokenAcquisition tokenAcquisition;
private readonly GraphServiceClient graphServiceClient;
public SearchController(IConfiguration configuration, ITokenAcquisition _tokenAcquisition,
GraphServiceClient _graphServiceClient) : base(configuration)
{
tokenAcquisition = _tokenAcquisition;
graphServiceClient = _graphServiceClient;
}
And the relevant actions decorated with AuthorizeForScopes :
[AuthorizeForScopes(ScopeKeySection = "GraphBeta:Scopes")]
public async Task<IActionResult> Results(string queryString, int pageNumber, int pageSize)
{
...
}
And then calls are made to MS Graph, for example:
return await graphClient.Search.Query(requests).Request().PostAsync();
We are using
- Microsoft.Identity.Web 1.4.1
- Microsoft.Identity.Web.MicrosoftGraphBeta 1.4.1
- Microsoft.Graph.Beta 0.35.0-preview
- Microsoft.Graph.Auth 1.0.0-preview.6