0

We are exploring code sample provided by Microsoft for implementing "Azure AD B2C Authentication". We are using "4-2-B2C" (Refer the screen shot) code samples from "https://learn.microsoft.com/en-us/azure/active-directory-b2c/integrate-with-app-code-samples", 4th sample with name dotnetcore-webapp-msal-api.

Following is what we are trying to achieve:

  1. Get hold of access token in a controller.
  2. Display menu items based on role in claims .

Any input would be helpful.

Thanks in advance.

I tried the sample code provided by Microsoft by making required changes but I am not able to access the token. Refer to the following code:

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Identity.Web;
using System;
using System.Diagnostics;
using System.Threading.Tasks;
using WebApp_OpenIDConnect_DotNet.Models;

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

        public HomeController(ITokenAcquisition tokenAcquisition)
        {
            this.tokenAcquisition = tokenAcquisition;
        }

        public async Task<IActionResult> Index()
        {
            // Getting Token
            string accessToken = await this.tokenAcquisition.GetAccessTokenForAppAsync("https://<Domain>.<Tenant ID of the web api>/access_as_user");
            return View();
        }

        [AllowAnonymous]
        [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
        public IActionResult Error()
        {
            return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
        }
    }
}

What do you expect to happen? Get hold of "access" toke.

What did actually happen? Please refer to the Index method.

I am not able to get the access token. When I check the details in variable accessToken, I am getting the following exception:

InnerException = {"IDW10404: 'scope' parameter should be of the form 'AppIdUri/.default'. See https://aka.ms/ms-id-web/daemon-scenarios. (Parameter 'scope')"}

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
spalMcc
  • 21
  • 4
  • I tried the same already. Refer the following error: MsalClientException: WithTenantId can only be used when an AAD authority is specified at the application level. I already tried the same. – spalMcc Mar 13 '23 at 18:32

1 Answers1

0

I tried to reproduce the error :

Startup.cs:

public void ConfigureServices(IServiceCollection services)
{
    var initialScopes = Configuration.GetValue<string>("DownstreamApi:Scopes")?.Split(' ');


    services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)

       .AddMicrosoftIdentityWebApp(Configuration.GetSection("AzureAd"))
           .EnableTokenAcquisitionToCallDownstreamApi(initialScopes)
                .AddMicrosoftGraph(Configuration.GetSection("DownstreamApi"))
               .AddInMemoryTokenCaches();


    services.AddControllersWithViews(options =>
    {
        var policy = new AuthorizationPolicyBuilder()
            .RequireAuthenticatedUser()
            .Build();
        options.Filters.Add(new AuthorizeFilter(policy));
    });
   services.AddRazorPages()
        .AddMicrosoftIdentityUI();
}

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.


  public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
            IdentityModelEventSource.ShowPII = true;
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");
            // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
            app.UseHsts();
        }
        app.UseHttpsRedirection();
        app.UseStaticFiles();
        System.Net.ServicePointManager.SecurityProtocol = System.Net.SecurityProtocolType.Tls12;

        app.UseRouting();
        
        app.UseAuthentication();
        app.UseAuthorization();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllerRoute(
                name: "default",
                pattern: "{controller=Home}/{action=Index}/{id?}");
            endpoints.MapRazorPages();
        });
        
        }

enter image description here

error: 'invalid_client', error_description: 'AADSTS650053: The application 'app' asked for scope 'User.Read''' that doesn't exist on the resource xxxx.

Appsettings.json

{
  "AzureAd": {
    "Instance": "https://login.microsoftonline.com/",
    // "Authority": "https://login.microsoftonline.com/xxx",
    "Domain": "xxx.onmicrosoft.com",
    "ClientId": "xx",
    "TenantId": "xxx18f3b0",
    "ClientSecret": "xxx",
    "CallbackPath": "/signin-oidc"
  },
  "DownstreamApi": {
    "BaseUrl": "https://graph.microsoft.com/v1.0",
//    "Scopes": "api://xxxx/access_as_user"
    "Scopes": "api://xxx/.default"
  },

The error you got "IDW10404: 'scope' parameter should be of the form 'AppIdUri/.default' is due to scope being incorrect format.

enter image description here

It must be "Scopes": "api://xxx/.default"

Like api:///.default i.e.; <AppIdUri>/.default

AppId uri, you can check in the portal like:

enter image description here

In case you are calling microsoft graph api ,

Scope must be "Scopes": https://graph.microsoft.com/.default

Appsettings.json

  {
      "AzureAd": {
        "Instance": "https://login.microsoftonline.com/",
        "Domain": "xxxx.onmicrosoft.com",
        "ClientId": "xxx",
        "TenantId": "xxx",
        "ClientSecret": "xxxx",
        "CallbackPath": "/signin-oidc"
      },
      "DownstreamApi": {
        "BaseUrl": "https://graph.microsoft.com/v1.0",
        "Scopes": "https://graph.microsoft.com/.default",
      },
      "Logging": {
        "LogLevel": {
          "Default": "Information",
          "Microsoft": "Warning",
          "Microsoft.Hosting.Lifetime": "Information"
        }
      },
      "AllowedHosts": "*"
    }

It must be like

Code:

string appScope = "appIdUri/.default";
string accessToken = await this.tokenAcquisition.GetAccessTokenForAppAsync(appScope);
 

enter image description here

kavyaS
  • 8,026
  • 1
  • 7
  • 19
  • Thanks alot for the details. I know what is required to be configured. thanks alot fot the help. This is totally new to me, I mean the configuration. I have worked on Angular based app but we did not od any such thing. I will try this and check. – spalMcc Mar 15 '23 at 18:09
  • FYI - I am not calling Graph API, just running sample code ... – spalMcc Mar 15 '23 at 18:11
  • @spalMcc : In case where api:///access_as_user is set in portal , then you can use `api:///.default` as appscope in GetAccessTokenForAppAsync(appScope); – kavyaS Mar 31 '23 at 04:08