1

I am developing Windows form application using Graph API. I created a function that returns a GraphServiceClient and a function that returns signed-in user. When I launch the application, an error appears- MsalUiRequiredException: No account or login hint was passed to the AcquireTokenSilent call. Here is the code:

 public class GraphHelper
{
    private static string ClientId = "clientID";
    private static string Tenant = "tenantID";
    public static IPublicClientApplication PublicClientApp;
    private static string[] scopes = { "user.read" };
    private static GraphServiceClient graphClient;

    public static async Task<string> GetAccessToken()
    {
        PublicClientApp = PublicClientApplicationBuilder.Create(ClientId)
            .WithRedirectUri("https://login.microsoftonline.com/common/oauth2/nativeclient")
            .WithAuthority(AzureCloudInstance.AzurePublic, Tenant)
            .Build();

        IEnumerable<IAccount> accounts = await PublicClientApp.GetAccountsAsync().ConfigureAwait(false);
        IAccount firstAccount = accounts.FirstOrDefault();
        var authResult = await PublicClientApp.AcquireTokenSilent(scopes, firstAccount)
                                              .ExecuteAsync();

        authResult = await PublicClientApp.AcquireTokenInteractive(scopes)
                                  .ExecuteAsync();

        return authResult.AccessToken;
    }

    public static async Task<GraphServiceClient> GetGraphServiceClient()
    {
        var delegateAuthProvider = new DelegateAuthenticationProvider((requestMessage) =>
        {
            requestMessage.Headers.Authorization = new AuthenticationHeaderValue("bearer", GetAccessToken().Result);

            return Task.FromResult(0);
        });
        var graphClient = new GraphServiceClient(delegateAuthProvider);

        return graphClient;
    }

    public  async Task<User> GetMeAsync()
    {
        graphClient = GetGraphServiceClient().Result;

        var user = await graphClient.Me
            .Request()
            .GetAsync();

        return user;
    }
}
Goga
  • 53
  • 2
  • 8

1 Answers1

1

GetAccountsAsync returns all the available accounts in the user token cache for the application. When you call GetAccountsAsync for the first time or if you the token cache is empty it can return empty accounts collection. In that case AcquireTokenSilent will throw the exception. Add try catch block around AcquireTokenSilent and if an expcetion is raised then call AcquireTokenInteractive.

AuthenticationResult authResult;
try
{
    authResult = await PublicClientApp.AcquireTokenSilent(scopes, firstAccount)
                                          .ExecuteAsync();
}
catch (MsalUiRequiredException ex)
{
    authResult = await PublicClientApp.AcquireTokenInteractive(scopes)
                              .ExecuteAsync();
}
user2250152
  • 14,658
  • 4
  • 33
  • 57