Sep 21 2019
02:34 AM
- last edited on
Jan 14 2022
04:37 PM
by
TechCommunityAP
Sep 21 2019
02:34 AM
- last edited on
Jan 14 2022
04:37 PM
by
TechCommunityAP
I added a multitenant app registration with below permissions (image api-perm):
I build ASP.NET MVC web app with authorization code flow and MSAL.NET. I use this code as a base - https://github.com/microsoftgraph/msgraph-training-aspnetmvcapp/blob/master/Demos/03-add-msgraph/REA...
I want a user to consent to all static permissions I specified (see image above) on the first sign-in. For that purpose I use .default scope. So my scope for an authorization code request is https://graph.microsoft.com/.default. When a user signs in for the first time, a user will see consent screen with all permissions (image):
Here is the request from fiddler, /common/oauth2/v2.0/authorize? endpoint (image):
Then I use AcquireTokenByAuthorizationCode to get an access token to read a user profile from MS Graph (code):
var idClient = ConfidentialClientApplicationBuilder.Create(appId)
.WithRedirectUri(redirectUri)
.WithClientSecret(appSecret)
.Build();
var signedInUser = new ClaimsPrincipal(notification.AuthenticationTicket.Identity);
var tokenStore = new SessionTokenStore(idClient.UserTokenCache, HttpContext.Current, signedInUser);
try
{
string[] scopes = { "User.Read" };
var result = await idClient.AcquireTokenByAuthorizationCode(
scopes, notification.Code).ExecuteAsync();
var accounts = await idClient.GetAccountsAsync();
// second try to get User.Read scope
var result2 = await idClient.AcquireTokenSilent(scopes, accounts.FirstOrDefault())
.ExecuteAsync();
var userDetails = await GraphHelper.GetUserDetailsAsync(result2.AccessToken);
var cachedUser = new CachedUser()
{
DisplayName = userDetails.DisplayName,
Email = string.IsNullOrEmpty(userDetails.Mail) ?
userDetails.UserPrincipalName : userDetails.Mail,
Avatar = string.Empty
};
tokenStore.SaveUserDetails(cachedUser);
public static async Task<User> GetUserDetailsAsync(string accessToken)
{
var graphClient = new GraphServiceClient(
new DelegateAuthenticationProvider(
async (requestMessage) =>
{
requestMessage.Headers.Authorization =
new AuthenticationHeaderValue("Bearer", accessToken);
}));
return await graphClient.Me.Request().GetAsync();
}
However the token which is returned from /common/oauth2/v2.0/token endpoint doesn't have User.Read scope, despite that I explicitly request it in AcquireTokenByAuthorizationCode method(image):
I even tried to get the token again with AcquireTokenSilent (refresh token flow), but once again User.Read scope is missing(image):
As a result, I have an error - Authorization_RequestDenied. "Insufficient privileges to complete the operation."
If I simply refresh the page and try to sign in with the same user again - no consent screen (because the user already consented), and no errors any more.
Do you have any ideas what's happening?
Sep 21 2019 08:13 PM
@Sergei Sergeev Your forensic approach to understanding and identifying are impeccable ! Hey Have you ever heard of Ansible linux tower system ! I coded 2 play books for there Moscone Frisco Oracle World Kick off ! I work for Tech Data Americas ! I work for Microsoft/IBM Oracle Sun/Linux Systems ! I had to code with PYTHON ! It is not compatible wit Ansible though . That is the beauty of it ! That is what makes it so stble ! Check It Out ! Thanks Richardrut