0
votes

I am trying to get full name of a user using MS Graph API. The code is not working with delegated permission User.ReadBasic.All while working with App permission of User.Read.All

code is:

public static async Task<string> GetAccessToken()
    {
        string authorityUri = $"https://login.microsoftonline.com/{tenantid}";
        AuthenticationContext authContext = new AuthenticationContext(authorityUri);

        string resourceUrl = "https://graph.microsoft.com";

        ClientCredential creds = new ClientCredential(ConfigHelper.ClientId, ConfigHelper.AppKey);
        AuthenticationResult authResult = await authContext.AcquireTokenAsync(resourceUrl, creds);

        return authResult.AccessToken;
    }

public static async Task<GraphServiceClient> GetGraphClient()
    {
        GraphServiceClient graphServiceClient = new GraphServiceClient(new DelegateAuthenticationProvider(
                                                    async (requestMessage) =>
                                                    {
                                                        string accessToken = await GetAccessToken();
                                                        if (!string.IsNullOrEmpty(accessToken))
                                                        {
                                                            requestMessage.Headers.Authorization = new AuthenticationHeaderValue("bearer", accessToken);
                                                        }
                                                    }));

        return graphServiceClient;
    }

Error is

Microsoft.Graph.ServiceException: Code: Authorization_RequestDenied Message: Insufficient privileges to complete the operation. Blockquote

I am not sure why this is happening.

Edited:

private static async Task<string> GetAccessToken()
    {
        string signedInUserID = ClaimsPrincipal.Current.FindFirst(ClaimTypes.NameIdentifier).Value;
        string tenantID = ClaimsPrincipal.Current.FindFirst("http://schemas.microsoft.com/identity/claims/tenantid").Value;
        string userObjectID = ClaimsPrincipal.Current.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier").Value;
        string resourceUrl = "https://graph.microsoft.com";

        //// get a token for the Graph without triggering any user interaction (from the cache, via multi-resource refresh token, etc)
        ClientCredential clientcred = new ClientCredential(ConfigHelper.ClientId, ConfigHelper.AppKey);
        //// initialize AuthenticationContext with the token cache of the currently signed in user, as kept in the app's database
        AuthenticationContext authenticationContext = new AuthenticationContext($"https://login.microsoftonline.com/{tenantid}") ;
        AuthenticationResult authenticationResult = await authenticationContext.AcquireTokenSilentAsync(resourceUrl, clientcred, new UserIdentifier(userObjectID, UserIdentifierType.UniqueId));
        return authenticationResult.AccessToken;
    }
1

1 Answers

2
votes

Well, you are using Client Credentials Grant Flow, expecting delegated permissions to be applied to a scenario where there is no user.

The token you get is for the app acting purely as itself, which means only Application Permissions will be applied. Delegated permissions are only applied when there is a user context.

Your options:

  1. Use Application permissions
  2. Use a flow like Authorization Code Grant Flow to get a delegated access token
    • You get a refresh token too when you get a token in this way, which you can use to get a new access token for this user whenever you want (+ a new refresh token)
    • Though certain situations like the user resetting their password will cause the refresh token to be revoked