0

I'm getting the following error when trying to use a cached token. I'm using the list that was provided as an example here: https://learn.microsoft.com/bs-latn-ba/azure/active-directory/develop/msal-net-acquire-token-silently

cannot convert from 'System.Collections.Generic.IEnumerable' to 'Microsoft.Identity.Client.IAccount'`

        static async Task<GraphServiceClient> Auth()
        {

            var clientApp = PublicClientApplicationBuilder.Create(ConfigurationManager.AppSettings["clientId"]).Build();
            string[] scopes = new string[] { "user.read" };
            string token = null;
            var app = PublicClientApplicationBuilder.Create(ConfigurationManager.AppSettings["clientId"]).Build();
            AuthenticationResult result = null;
            var accounts = await app.GetAccountsAsync();

                result = await app.AcquireTokenSilent(scopes, accounts)
                       .ExecuteAsync();
                token = result.AccessToken;

            GraphServiceClient graphClient = new GraphServiceClient(
                        "https://graph.microsoft.com/v1.0",
                        new DelegateAuthenticationProvider(
                            async (requestMessage) =>
                            {
                                requestMessage.Headers.Authorization = new AuthenticationHeaderValue("bearer", token);
                            }));
            return graphClient;
        }
Jawad
  • 11,028
  • 3
  • 24
  • 37
Ryvik
  • 363
  • 1
  • 3
  • 14

1 Answers1

1

The call that is causing the error is this one

result = await app.AcquireTokenSilent(scopes, accounts)
                  .ExecuteAsync();

AcquireTokenSilent requires two variables, IEnumerable<String> (scops) and string (loginHint). What you are passing for loginHist is an array of accounts when it's supposed to be a single string (single account).

var accounts = await app.GetAccountsAsync();

GetAccountsAsync()'s return type is IEnumerable which is why its throwing the error at that call.

In an example here, the account looked up is from the list.

// Get the account
IAccount account = await application.GetAccountAsync(accountIdentifier).ConfigureAwait(false);

// Special case for guest users as the Guest oid / tenant id are not surfaced.
if (account == null)
{
    if (loginHint == null)
        throw new ArgumentNullException(nameof(loginHint));

    var accounts = await application.GetAccountsAsync().ConfigureAwait(false);
    account = accounts.FirstOrDefault(a => a.Username == loginHint);
}

Add this line to your code:

var accounts = await app.GetAccountsAsync();
IAccount account = accounts.FirstOrDefault(a => a.Username == loginHint); // <--- Get Account from accounts
result = await app.AcquireTokenSilent(scopes, account) // Use account instead of accounts.
                  .ExecuteAsync();
token = result.AccessToken;
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Jawad
  • 11,028
  • 3
  • 24
  • 37
  • make sure you add `using System.Linq;` – Jawad Jan 12 '20 at 05:54
  • Yep, just noticed that. I'm now getting `The name 'loginHint' does not exist in the current context` – Ryvik Jan 12 '20 at 06:01
  • LoginHint is supposed to be a string variable.. a username you are working with. Do check the link i sent that has a full code on how to do what you are trying to do – Jawad Jan 12 '20 at 06:02