0

GetUserAccessTokenAsync by using this method I am trying to get the Token, The same code working fine in POC App, where as in the real application I am getting TokenNotFound.

User is authenticated and able to get the userId too, at the end I am getting account as null, it leads to the main error.

 public async Task<string> GetUserAccessTokenAsync(string userId)
        {
            var account = await _app.GetAccountAsync(userId);
            if (account == null) throw new ServiceException(new Error
            {
                Code = "TokenNotFound",
                Message = "User not found in token cache. Maybe the server was restarted."
            });

            try
            {
                var result = await _app.AcquireTokenSilent(_scopes, account).ExecuteAsync();
                return result.AccessToken;
            }

            // Unable to retrieve the access token silently.
            catch (Exception)
            {
                throw new ServiceException(new Error
                {
                    Code = GraphErrorCode.AuthenticationFailure.ToString(),
                    Message = "Caller needs to authenticate. Unable to retrieve the access token silently."
                });
            }
        }

Note: The same code working fine in POC application, I tried with same app resource and created new app resource too.

Please help me what exactly I am missing...

Tiny Wang
  • 10,423
  • 1
  • 11
  • 29
Venu Gopal Reddy
  • 301
  • 1
  • 3
  • 13

2 Answers2

0

I have a sample with asp.net core mvc, which integrate MSAL to obtain access token for calling Ms graph api. I don't know what is POC App actually, but per my searching, AcquireTokenSilent may from MSAL.js

Here's the detail.

Adding configurations in appsetting file about azure ad:

"AzureAd": {
    "Instance": "https://login.microsoftonline.com/",
    "Domain": "your_tenant_name.onmicrosoft.com",
    "TenantId": "tenant_id",
    "ClientId": "azure_ad_client_id", 
    "ClientSecret": "client_secret", 
    "CallbackPath": "/signin-oidc",//don't forget to set redirect url in azure portal
    "SignedOutCallbackPath ": "/signout-callback-oidc"
}

installing packages:

<PackageReference Include="Microsoft.Identity.Web" Version="1.23.1" />
<PackageReference Include="Microsoft.Identity.Web.UI" Version="1.23.1" />

StartUp.cs, don't forget to add app.UseAuthentication();app.UseAuthorization(); in Configure method:

public void ConfigureServices(IServiceCollection services)
{
    services.AddMicrosoftIdentityWebAppAuthentication(Configuration)
        .EnableTokenAcquisitionToCallDownstreamApi(new string[] { "user.read" })
        .AddInMemoryTokenCaches();

    // Require authentication
    services.AddControllersWithViews(options =>
    {
        var policy = new AuthorizationPolicyBuilder()
            .RequireAuthenticatedUser()
            .Build();
        options.Filters.Add(new AuthorizeFilter(policy));
    })
    // Add the Microsoft Identity UI pages for signin/out
    .AddMicrosoftIdentityUI();
}

And my test Controller:

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Microsoft.Identity.Web;
using System.Diagnostics;
using System.Threading.Tasks;
using WebAppMvc.Models;

namespace WebAppMvc.Controllers
{
    [Authorize]
    public class HomeController : Controller
    {
        private readonly ITokenAcquisition _tokenAcquisition;

        public HomeController(ITokenAcquisition tokenAcquisition)
        {
            _tokenAcquisition = tokenAcquisition;
        }

        public async Task<IActionResult> IndexAsync()
        {
            string[] scopes = new string[] { "user.read" };
            string accessToken = await _tokenAcquisition.GetAccessTokenForUserAsync(scopes);
            return View();
        }
    }
}

If the redirection url is wrong after signing in, just changing the url in browser manually to localhost:xxx/home

enter image description here

Tiny Wang
  • 10,423
  • 1
  • 11
  • 29
  • Thanks for your response, actually I followed your steps and able to generate **token**, but I want add ``` string[] scopes = new string[] { "user.read" }; string accessToken = await _tokenAcquisition.GetAccessTokenForUserAsync(scopes); ``` lines code into else condition on my above method, which helps me to get graph photo stream. But I am getting following error. System.AggregateException: 'Some services are not able to be constructed'. Please suggest. and when mention poc is proof of concept or sample application. My moto to get profile pic – Venu Gopal Reddy Mar 23 '22 at 10:18
  • Could you pls show us your `ConfigureServices` method in your `Startup.cs` file? Your error message means the injection of _tokenAcquisition met issue and you may not inject it.. If your `ConfigureServices` is the same as mine, then you may check if you inject it in your construct method of your Controller. – Tiny Wang Mar 23 '22 at 11:26
  • services.Configure(options =>{options.CheckConsentNeeded = context => true;options.MinimumSameSitePolicy = SameSiteMode.None;}); services.AddSingleton(); services.AddSingleton(); – Venu Gopal Reddy Mar 23 '22 at 12:42
  • services.AddAuthentication(AzureADDefaults.AuthenticationScheme).AddAzureAD(options => Configuration.Bind("AzureAd", options)); services.AddMicrosoftIdentityWebAppAuthentication(Configuration).EnableTokenAcquisitionToCallDownstreamApi(new string[] { "user.read" }) .AddInMemoryTokenCaches(); services.AddControllersWithViews(options => { var policy = new AuthorizationPolicyBuilder().RequireAuthenticatedUser().Build(); options.Filters.Add(new AuthorizeFilter(policy)); }); – Venu Gopal Reddy Mar 23 '22 at 12:42
  • I added here above my code from startup.cs; Tiny please help – Venu Gopal Reddy Mar 23 '22 at 12:45
  • Did you inject `_tokenAcquisition` into the construct method of the class that you want to use _tokenAcquisition? `private readonly ITokenAcquisition _tokenAcquisition; public HomeController(ITokenAcquisition tokenAcquisition){_tokenAcquisition = tokenAcquisition;}` – Tiny Wang Mar 23 '22 at 13:14
  • Yes. I did it. But not in HomeController, that I am using GraphAuthProvider.cs Class. Because I want this should be executed when my actual code jump to else block – Venu Gopal Reddy Mar 23 '22 at 13:30
  • Actual Error: Singleton ImplementationType: XXX.Services.GraphAuthProvider': Cannot consume scoped service 'Microsoft.Identity.Web.ITokenAcquisition' from singleton 'XXX.Services.IGraphAuthProvider'. – Venu Gopal Reddy Mar 23 '22 at 13:37
  • could you pls try to use `services.AddScoped();` instead of `services.AddSingleton();` `Cannot consume scoped` means you used `Singleton` here but it required to be `scoped` – Tiny Wang Mar 23 '22 at 13:44
  • Seems it worked a bit. But now getting this : ( Exception: Unable to unprotect the message.State. Unknown location Exception: An error was encountered while handling the remote login. Microsoft.AspNetCore.Authentication.RemoteAuthenticationHandler.HandleRequestAsync() – Venu Gopal Reddy Mar 23 '22 at 13:56
  • Could you pls check [this answer](https://stackoverflow.com/a/42425810)? I'm afraid you need to double confirm the `appsetting.json` file to check the value of `CallbackPath` and if it matched the redirect url you set in azure portal. In azure portal-> azure ad->your app-> authentication, you may set the redirect url like `https://localhost:xxxx/` – Tiny Wang Mar 24 '22 at 05:29
  • I did setup redirect url and its mached Tiny. and I am using "CallbackPath": "/signin-oidc", this as call back path. above answer also not helped me. really appreciate your patience, to help on this issue. – Venu Gopal Reddy Mar 24 '22 at 07:38
  • Then can [this question](https://github.com/AzureAD/microsoft-identity-web/issues/1555) help you? – Tiny Wang Mar 24 '22 at 08:35
  • Main root cause for this issue is var account = await _app.GetAccountAsync(userId); in this line account is getting null. if I get valid data into account it will work. still its not resolved. – Venu Gopal Reddy Mar 25 '22 at 12:18
0

At Finally I have followed below link it helped to get rid of my all queries for graph API;

https://github.com/microsoftgraph/msgraph-training-aspnet-core

Venu Gopal Reddy
  • 301
  • 1
  • 3
  • 13