Home

Microsoft identity platform returns invalid scopes?

%3CLINGO-SUB%20id%3D%22lingo-sub-868565%22%20slang%3D%22en-US%22%3EMicrosoft%20identity%20platform%20returns%20invalid%20scopes%3F%3C%2FLINGO-SUB%3E%3CLINGO-BODY%20id%3D%22lingo-body-868565%22%20slang%3D%22en-US%22%3E%3CP%3EI%20added%20a%20multitenant%20app%20registration%20with%20below%20permissions%20(image%20api-perm)%3A%3C%2FP%3E%0A%3CP%3E%3CSPAN%20class%3D%22lia-inline-image-display-wrapper%20lia-image-align-inline%22%20style%3D%22width%3A%20400px%3B%22%3E%3CIMG%20src%3D%22https%3A%2F%2Fgxcuf89792.i.lithium.com%2Ft5%2Fimage%2Fserverpage%2Fimage-id%2F132878iD7C032C946E1329D%2Fimage-size%2Fmedium%3Fv%3D1.0%26amp%3Bpx%3D400%22%20alt%3D%22api-perm.jpg%22%20title%3D%22api-perm.jpg%22%20%2F%3E%3C%2FSPAN%3E%3CBR%20%2F%3EI%20build%20ASP.NET%20MVC%20web%20app%20with%20authorization%20code%20flow%20and%20MSAL.NET.%20I%20use%20this%20code%20as%20a%20base%20-%20%3CA%20href%3D%22https%3A%2F%2Fgithub.com%2Fmicrosoftgraph%2Fmsgraph-training-aspnetmvcapp%2Fblob%2Fmaster%2FDemos%2F03-add-msgraph%2FREADME.md%22%20target%3D%22_blank%22%20rel%3D%22noopener%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%22%3Ehttps%3A%2F%2Fgithub.com%2Fmicrosoftgraph%2Fmsgraph-training-aspnetmvcapp%2Fblob%2Fmaster%2FDemos%2F03-add-msgraph%2FREADME.md%3C%2FA%3E%20%3CBR%20%2F%3EI%20want%20a%20user%20to%20consent%20to%20all%20static%20permissions%20I%20specified%20(see%20image%20above)%20on%20the%20first%20sign-in.%20For%20that%20purpose%20I%20use%20%3CA%20href%3D%22https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Factive-directory%2Fdevelop%2Fv2-permissions-and-consent%23the-default-scope%22%20target%3D%22_blank%22%20rel%3D%22noopener%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%22%3E.default%20scope.%3C%2FA%3E%26nbsp%3B%20So%20my%20scope%20for%20an%20authorization%20code%20request%20is%20%3CEM%3E%3CA%20href%3D%22https%3A%2F%2Fgraph.microsoft.com%2F.default%22%20target%3D%22_blank%22%20rel%3D%22noopener%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%22%3Ehttps%3A%2F%2Fgraph.microsoft.com%2F.default%3C%2FA%3E.%3C%2FEM%3E%20When%20a%20user%20signs%20in%20for%20the%20first%20time%2C%20a%20user%20will%20see%20consent%20screen%20with%20all%20permissions%20(image)%3A%3C%2FP%3E%0A%3CP%3E%3CSPAN%20class%3D%22lia-inline-image-display-wrapper%20lia-image-align-inline%22%20style%3D%22width%3A%20291px%3B%22%3E%3CIMG%20src%3D%22https%3A%2F%2Fgxcuf89792.i.lithium.com%2Ft5%2Fimage%2Fserverpage%2Fimage-id%2F132879iA53B35463B766139%2Fimage-size%2Fmedium%3Fv%3D1.0%26amp%3Bpx%3D400%22%20alt%3D%22all-perm.jpg%22%20title%3D%22all-perm.jpg%22%20%2F%3E%3C%2FSPAN%3E%3C%2FP%3E%0A%3CP%3EHere%20is%20the%20request%20from%20fiddler%2C%20%3CEM%3E%2Fcommon%2Foauth2%2Fv2.0%2Fauthorize%3F%3C%2FEM%3E%20endpoint%20(image)%3A%3C%2FP%3E%0A%3CP%3E%3CSPAN%20class%3D%22lia-inline-image-display-wrapper%20lia-image-align-inline%22%20style%3D%22width%3A%20400px%3B%22%3E%3CIMG%20src%3D%22https%3A%2F%2Fgxcuf89792.i.lithium.com%2Ft5%2Fimage%2Fserverpage%2Fimage-id%2F132880i3B00105CB89425CB%2Fimage-size%2Fmedium%3Fv%3D1.0%26amp%3Bpx%3D400%22%20alt%3D%22consent-auth-code.jpg%22%20title%3D%22consent-auth-code.jpg%22%20%2F%3E%3C%2FSPAN%3E%3C%2FP%3E%0A%3CP%3EThen%20I%20use%20AcquireTokenByAuthorizationCode%20to%20get%20an%20access%20token%20to%20read%20a%20user%20profile%20from%20MS%20Graph%20(code)%3A%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CPRE%20class%3D%22lia-code-sample%20language-csharp%22%3E%3CCODE%3Evar%20idClient%20%3D%20ConfidentialClientApplicationBuilder.Create(appId)%0A.WithRedirectUri(redirectUri)%0A.WithClientSecret(appSecret)%0A.Build()%3B%0A%0Avar%20signedInUser%20%3D%20new%20ClaimsPrincipal(notification.AuthenticationTicket.Identity)%3B%0Avar%20tokenStore%20%3D%20new%20SessionTokenStore(idClient.UserTokenCache%2C%20HttpContext.Current%2C%20signedInUser)%3B%0A%0Atry%0A%7B%0Astring%5B%5D%20scopes%20%3D%20%7B%20%22User.Read%22%20%7D%3B%0A%0Avar%20result%20%3D%20await%20idClient.AcquireTokenByAuthorizationCode(%0Ascopes%2C%20notification.Code).ExecuteAsync()%3B%0A%0Avar%20accounts%20%3D%20await%20idClient.GetAccountsAsync()%3B%0A%0A%2F%2F%20second%20try%20to%20get%20User.Read%20scope%0Avar%20result2%20%3D%20await%20idClient.AcquireTokenSilent(scopes%2C%20accounts.FirstOrDefault())%0A.ExecuteAsync()%3B%0A%0Avar%20userDetails%20%3D%20await%20GraphHelper.GetUserDetailsAsync(result2.AccessToken)%3B%0A%0Avar%20cachedUser%20%3D%20new%20CachedUser()%0A%7B%0ADisplayName%20%3D%20userDetails.DisplayName%2C%0AEmail%20%3D%20string.IsNullOrEmpty(userDetails.Mail)%20%3F%0AuserDetails.UserPrincipalName%20%3A%20userDetails.Mail%2C%0AAvatar%20%3D%20string.Empty%0A%7D%3B%0A%0AtokenStore.SaveUserDetails(cachedUser)%3B%0A%0Apublic%20static%20async%20Task%3CUSER%3E%20GetUserDetailsAsync(string%20accessToken)%0A%7B%0Avar%20graphClient%20%3D%20new%20GraphServiceClient(%0Anew%20DelegateAuthenticationProvider(%0Aasync%20(requestMessage)%20%3D%26gt%3B%0A%7B%0ArequestMessage.Headers.Authorization%20%3D%0Anew%20AuthenticationHeaderValue(%22Bearer%22%2C%20accessToken)%3B%0A%7D))%3B%0A%0Areturn%20await%20graphClient.Me.Request().GetAsync()%3B%0A%7D%3C%2FUSER%3E%3C%2FCODE%3E%3C%2FPRE%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%3CBR%20%2F%3EHowever%20the%20token%20which%20is%20returned%20from%20%3CEM%3E%2Fcommon%2Foauth2%2Fv2.0%2Ftoken%3C%2FEM%3E%20endpoint%20doesn't%20have%20%3CEM%3EUser%3C%2FEM%3E.Read%20scope%2C%20despite%20that%20I%20explicitly%20request%20it%20in%20AcquireTokenByAuthorizationCode%20method(image)%3A%3C%2FP%3E%0A%3CP%3E%3CSPAN%20class%3D%22lia-inline-image-display-wrapper%20lia-image-align-inline%22%20style%3D%22width%3A%20400px%3B%22%3E%3CIMG%20src%3D%22https%3A%2F%2Fgxcuf89792.i.lithium.com%2Ft5%2Fimage%2Fserverpage%2Fimage-id%2F132881i70419D5579098D0C%2Fimage-size%2Fmedium%3Fv%3D1.0%26amp%3Bpx%3D400%22%20alt%3D%22no-user-auth-code.jpg%22%20title%3D%22no-user-auth-code.jpg%22%20%2F%3E%3C%2FSPAN%3E%3C%2FP%3E%0A%3CP%3EI%20even%20tried%20to%20get%20the%20token%20again%20with%20AcquireTokenSilent%20(refresh%20token%20flow)%2C%20but%20once%20again%20User.Read%20scope%20is%20missing(image)%3A%3C%2FP%3E%0A%3CP%3E%3CSPAN%20class%3D%22lia-inline-image-display-wrapper%20lia-image-align-inline%22%20style%3D%22width%3A%20400px%3B%22%3E%3CIMG%20src%3D%22https%3A%2F%2Fgxcuf89792.i.lithium.com%2Ft5%2Fimage%2Fserverpage%2Fimage-id%2F132882i0EE974328786B4A9%2Fimage-size%2Fmedium%3Fv%3D1.0%26amp%3Bpx%3D400%22%20alt%3D%22no-user-refresh.jpg%22%20title%3D%22no-user-refresh.jpg%22%20%2F%3E%3C%2FSPAN%3E%3C%2FP%3E%0A%3CP%3EAs%20a%20result%2C%20I%20have%20an%20error%20-%20Authorization_RequestDenied.%20%22Insufficient%20privileges%20to%20complete%20the%20operation.%22%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EIf%20I%20simply%20refresh%20the%20page%20and%20try%20to%20sign%20in%20with%20the%20same%20user%20again%20-%20no%20consent%20screen%20(because%20the%20user%20already%20consented)%2C%20and%20no%20errors%20any%20more.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EDo%20you%20have%20any%20ideas%20what's%20happening%3F%3C%2FP%3E%3C%2FLINGO-BODY%3E%3CLINGO-LABS%20id%3D%22lingo-labs-868565%22%20slang%3D%22en-US%22%3E%3CLINGO-LABEL%3EAuthentication%3C%2FLINGO-LABEL%3E%3CLINGO-LABEL%3EAzure%20AD%3C%2FLINGO-LABEL%3E%3CLINGO-LABEL%3EIdentity%20Management%3C%2FLINGO-LABEL%3E%3C%2FLINGO-LABS%3E%3CLINGO-SUB%20id%3D%22lingo-sub-869004%22%20slang%3D%22en-US%22%3ERe%3A%20Microsoft%20identity%20platform%20returns%20invalid%20scopes%3F%3C%2FLINGO-SUB%3E%3CLINGO-BODY%20id%3D%22lingo-body-869004%22%20slang%3D%22en-US%22%3E%3CP%3E%3CA%20href%3D%22https%3A%2F%2Ftechcommunity.microsoft.com%2Ft5%2Fuser%2Fviewprofilepage%2Fuser-id%2F7803%22%20target%3D%22_blank%22%3E%40Sergei%20Sergeev%3C%2FA%3E%26nbsp%3B%20Your%20forensic%20approach%20to%20understanding%20and%20identifying%20are%20impeccable%20!%20Hey%26nbsp%3B%20Have%20you%20ever%20heard%20of%20Ansible%20linux%20tower%20system%20!%20I%20coded%202%20play%20books%20for%20there%20Moscone%20Frisco%20Oracle%20World%20Kick%20off%20!%20I%20work%20for%20Tech%20Data%20Americas%20!%20I%20work%20for%20Microsoft%2FIBM%20Oracle%20Sun%2FLinux%20Systems%20!%20I%20had%20to%20code%20with%20PYTHON%20!%20It%20is%20not%20compatible%20wit%20Ansible%20though%20.%20That%20is%20the%20beauty%20of%26nbsp%3B%20it%20!%20That%20is%20what%20makes%20it%20so%20stble%20!%20Check%20It%20Out%20!%20Thanks%20%26nbsp%3B%20Richardrut%26nbsp%3B%3C%2FP%3E%3C%2FLINGO-BODY%3E
Sergei Sergeev
MVP

I added a multitenant app registration with below permissions (image api-perm):

api-perm.jpg
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):

all-perm.jpg

Here is the request from fiddler, /common/oauth2/v2.0/authorize? endpoint (image):

consent-auth-code.jpg

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):

no-user-auth-code.jpg

I even tried to get the token again with AcquireTokenSilent (refresh token flow), but once again User.Read scope is missing(image):

no-user-refresh.jpg

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?

1 Reply

@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 

Related Conversations
Extentions Synchronization
Deleted in Discussions on
3 Replies
Tabs and Dark Mode
cjc2112 in Discussions on
35 Replies
Stable version of Edge insider browser
HotCakeX in Discussions on
35 Replies
flashing a white screen while open new tab
Deleted in Discussions on
14 Replies
How to Prevent Teams from Auto-Launch
chenrylee in Microsoft Teams on
29 Replies