Search code examples
asp.net-coreauthentication.net-6.0azure-ad-msalmsal

AcquireTokenForUser in ASP.NET Core Web app


I have a AspNetCore app in net6.0. The user is asked to login against Azure Ad (Entra).

After this is done, the web app needs to make a call to an API. The endpoint it hits has a scope requirement. This is a scope the web app registration has permission for in Azure.

How do I get a hold of a token containing that scope, so I can use it to authorize in the API? I've looked at _tokenAcquisition.AcquireTokenForUser, but even if I have all AzureAd configuration in pla, including a client secret, it says no account or login hint was passed to AcquireTokenSilent.

Reading the documentation confuses me, and it's hard to find a concrete example of what I'm after. I've tried different solutions in code, but none seem to work.

Any help appreciated, and let me know if more info is needed, thanks!


Solution

  • According to the error message, we can only say that you didn't sign in successfully so that the _tokenAcquisition failed to work. Since you didn't share how you compose your code, pls allow me to share my steps.

    Firstly, I created a new .net 8 mvc application, when creating the app, I choose "Microsoft Identity Platform" as the authentication type. Then I need to modify the appsettings.json, Program.cs and HomeController.

    "AzureAd": {
      "Instance": "https://login.microsoftonline.com/",
      "ClientId": "aad_client_id",
      "ClientSecret": "client_secret",
      "Domain": "tenant_id",
      "TenantId": "tenant_id",
      "CallbackPath": "/signin-oidc"
    },
    

    In Program.cs, add toke acquisition service, and http service to send http request.

    builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
        .AddMicrosoftIdentityWebApp(builder.Configuration.GetSection("AzureAd"))
        .EnableTokenAcquisitionToCallDownstreamApi()
        .AddInMemoryTokenCaches();
    
    builder.Services.AddHttpClient();
    

    Then inject related service to generate access token and send http request.

    [Authorize]
    public class HomeController : Controller
    {
        private readonly ILogger<HomeController> _logger;
        private readonly ITokenAcquisition _tokenAcquisition;
        private readonly IHttpClientFactory _httpClientFactory;
    
        public HomeController(ITokenAcquisition tokenAcquisition, ILogger<HomeController> logger, IHttpClientFactory httpClientFactory)
        {
            _tokenAcquisition = tokenAcquisition;
            _logger = logger;
            _httpClientFactory = httpClientFactory;
        }
    
        public async Task<IActionResult> IndexAsync()
        {
            var accessToken = await _tokenAcquisition.GetAccessTokenForUserAsync(new string[] { "api://client_id_exposing_API/Tiny.Read" });
    
            var httpRequestMessage = new HttpRequestMessage(HttpMethod.Get, "https://localhost:7076/home/getData")
            {
                Headers =
                {
                    { HeaderNames.Authorization, "Bearer "+ accessToken}
                }
            };
    
            var httpClient = _httpClientFactory.CreateClient();
            var response = await httpClient.SendAsync(httpRequestMessage);
            if (response.StatusCode == HttpStatusCode.OK)
            {
                var result = await response.Content.ReadAsStringAsync();
            }
            return View();
        }
    
        [AllowAnonymous]
        public string getData() {
            return "success";
        }
    }
    

    Just like you see, after I sign in the app and hit the action method, I can generate access token successfully which containing correct scope I set in my method.

    enter image description here

    Nuget packages I used are generated by VS 2022 template:

    <ItemGroup>
      <PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.0" NoWarn="NU1605" />
      <PackageReference Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="8.0.0" NoWarn="NU1605" />
      <PackageReference Include="Microsoft.Identity.Web" Version="2.15.2" />
      <PackageReference Include="Microsoft.Identity.Web.UI" Version="2.15.2" />
      <PackageReference Include="Microsoft.Identity.Web.DownstreamApi" Version="2.15.2" />
    </ItemGroup>