Reputation: 13
I'm having trouble when using the Microsoft Graph API. Whenever I try to get a calendar, I get the following error message:
Exception thrown: 'Microsoft.Graph.ServiceException' in System.Private.CoreLib.dll: 'Code: BadRequest Message: Current authenticated context is not valid for this request
At first, I thought it was similar to this post, but my user is authenticated, so I believe it's not the case.
Here's my code:
EventController.cs
public async Task<Calendar> GetEventInfoAsync()
{
var accessToken = await getAcessTokenAsync();
DelegateAuthenticationProvider delegateAuthenticationProvider = new DelegateAuthenticationProvider(
(requestMessage) =>
{
requestMessage.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
return Task.FromResult(0);
}
);
GraphServiceClient graphClient = new GraphServiceClient(delegateAuthenticationProvider);
var calendar = await graphClient.Me.Calendar.Request().GetAsync();
return calendar;
}
And this is how I get the access token:
public async Task<string> getAcessTokenAsync()
{
if(User.Identity.IsAuthenticated)
{
var userId = User.FindFirst("MicrosoftUserId")?.Value;
ConfidentialClientApplication cca =
new ConfidentialClientApplication( Configuration["MicrosoftAuth:ClientId"],
String.Format(System.Globalization.CultureInfo.InvariantCulture, "https://login.microsoftonline.com/{0}{1}", "common", "/v2.0"),
Configuration["MicrosoftAuth:RedirectUri"]+ "signin-oidc",
new Microsoft.Identity.Client.ClientCredential(Configuration["MicrosoftAuth:ClientSecret"]),
new SessionTokenCache(userId,_memoryCache).GetCacheInstance(),
null);
var token = await cca.AcquireTokenForClientAsync(new string[]{"https://graph.microsoft.com/.default"});
return token.AccessToken;
}
else
throw new Exception("User is not autenticated");
}
Finally, this is how the authentication options look in the startup file.
services.AddAuthentication().AddOpenIdConnect(openIdOptions =>
{
openIdOptions.ResponseType = OpenIdConnectResponseType.CodeIdToken;
openIdOptions.Authority = String.Format(CultureInfo.InvariantCulture, "https://login.microsoftonline.com/{0}{1}", "common", "/v2.0");
openIdOptions.ClientId = Configuration["MicrosoftAuth:ClientId"];
openIdOptions.ClientSecret = Configuration["MicrosoftAuth:ClientSecret"];
openIdOptions.SaveTokens = true;
openIdOptions.TokenValidationParameters = new TokenValidationParameters{
ValidateIssuer = false
};
var scopes = Configuration["MicrosoftAuth:Scopes"].Split(' ');
foreach (string scope in scopes){
openIdOptions.Scope.Add(scope);
}
openIdOptions.Events = new OpenIdConnectEvents{
OnAuthorizationCodeReceived = async (context) =>
{
var userId = context.Principal.Claims.First(item => item.Type == ObjectIdentifierType).Value;
IMemoryCache memoryCache = context.HttpContext.RequestServices.GetRequiredService<IMemoryCache>();
ConfidentialClientApplication cca =
new ConfidentialClientApplication( Configuration["MicrosoftAuth:ClientId"],
String.Format(CultureInfo.InvariantCulture, "https://login.microsoftonline.com/{0}{1}{2}", "common", "/v2.0", "/adminconsent"),
Configuration["MicrosoftAuth:RedirectUri"]+ "signin-oidc",
new Microsoft.Identity.Client.ClientCredential(Configuration["MicrosoftAuth:ClientSecret"]),
new SessionTokenCache(userId,memoryCache).GetCacheInstance(),
null);
var code = context.ProtocolMessage.Code;
var result = await cca.AcquireTokenByAuthorizationCodeAsync(code,new string[]{"User.Read.All", "Calendars.ReadWrite"});
context.HandleCodeRedemption(result.AccessToken, result.IdToken);
},
};
});
My app is registered in the Microsoft Application Registration Portal, and I do get a token when I request for it, so I'm not sure what could possibly be causing the problem.
Upvotes: 1
Views: 2238
Reputation: 14649
Same issue with the previews thread. There are two kinds of token issued by Azure AD, delegate for use or app. The token you were acquire is using the client credentials flow which is delegate for app. There is no me
context when you request using this kind of token(refer Get access on behalf of a user and Get access without a user for the difference).
To integrate Microsoft Graph with web app and delegate the user to call the Microsoft Graph, you need to use the code grant flow(OnAuthorizationCodeReceived
event) as you config in the startup.cs
file.
Upvotes: 1