简体   繁体   中英

Azure Active Directory Msal Angular Configuration

I'm configuring azure ative directory login with angular app but getting a problem while implementing msal angular interceptor for azure active directory login in the app.

I get my token but when I authorize this token on swagger this not authenticating and getting an error.

www-authenticate: Bearer error="invalid_token", error_description="The audience 'cb343c76-cd5b-4af6-8229-014b2522adab' is invalid"

Here are some of my results of code and swagger. Please get back to me about what's wrong with my API and app.

Startup.cs

    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }
    public IConfiguration Configuration { get; }
     // This method gets called by the runtime. Use this method to add services to the services.
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
            .AddMicrosoftIdentityWebApi(Configuration,"AzureAd");
        services.AddControllers();
        services.AddCors((options =>
        {
            options.AddPolicy("FrontEnd", builder =>
              builder.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader());
        }));
        services.AddSwaggerGen(c =>
        {
            c.SwaggerDoc("v1", new OpenApiInfo { Title = "xperters.web.admin", Version = "v1" });

            c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
            {
                Name = "Authorization",
                Type = SecuritySchemeType.ApiKey,
                Scheme = "Bearer",
                BearerFormat = "JWT",
                In = ParameterLocation.Header,
                Description = "JWT Authorization header using the Bearer scheme."
            });

            c.AddSecurityRequirement(new OpenApiSecurityRequirement
            {
                {
                      new OpenApiSecurityScheme
                        {
                            Reference = new OpenApiReference
                            {
                                Type = ReferenceType.SecurityScheme,
                                Id = "Bearer"
                            }
                        },
                        new string[] {}

                }
            });
        });


        var result = ConfigureBuilder(services);  
        services.AddSingleton(result.Config);
        services.ConfigureDependencies(result.Config);
        services.ConfigureDatabase(result.Config);
        services.AddApplicationInsightsTelemetry();
        services.AddApplicationInsightsTelemetryProcessor<SuppressHealthStaticAndBotsResourcesFilter>();

        services.AddSpaStaticFiles(configuration =>
        {
            configuration.RootPath = "AdminUI/dist";
        });
    }
    // 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();
        }
        //if (!env.IsDevelopment())
        //{
        //    app.UseSpaStaticFiles();
        //}

        app.UseSwagger();
        app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "xperters.web.admin v1"));
        app.UseHttpsRedirection();
        //app.UseSpa(spa =>
        //{
        //    spa.Options.SourcePath = "AdminUI";
        //    spa.Options.StartupTimeout = new TimeSpan(0, 5, 0);
        //    spa.UseAngularCliServer(npmScript: "start");
        //});
        app.UseRouting();
        app.UseCors("FrontEnd");
        app.UseAuthentication();
        app.UseAuthorization();
        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllers();
        });
    }
    
    private static (AppConfig Config, ILoggerFactory LoggerFactory) ConfigureBuilder(IServiceCollection services)
    {
        var handler = new EnvironmentHandler();
        services.AddTransient<IHandleFiles, FilesHandler>();
        services.AddTransient<IHandleEnvironment, EnvironmentHandler>();
        
        var env = handler.GetHostingEnvironment<Program>();

        services.AddSingleton(env);
        services.AddLogging(builder =>
            builder.AddSerilog(dispose: true));
        
        var currentDirectory = Directory.GetCurrentDirectory();
        
        // IHostingEnvironment is obsolete therefore this is required.
        // https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.hosting.ihostingenvironment?view=aspnetcore-3.1
        var webEnvHosting = new Mock<IWebHostEnvironment>();
        webEnvHosting.Setup(x => x.ContentRootPath).Returns(currentDirectory);
        services.AddSingleton(webEnvHosting.Object);

        var provider = services.BuildServiceProvider();
        var loggerFactory = provider.GetService<ILoggerFactory>();
        var hostingEnvironment = provider.GetService<IWebHostEnvironment>();

        if (hostingEnvironment == null)
        {
            throw new ArgumentNullException("Application can't start.  hosting environment is null");
        }

        var filesHandler = provider.GetService<IHandleFiles>();

        var appConfigBuilder = new AppConfigBuilder(services, filesHandler, loggerFactory);
        return (appConfigBuilder.Build(), loggerFactory);
    }        

Controller

[Authorize]
[Route("api/approveMilestones")]
[ApiController]
public class ApproveMilestoneController : ControllerBase
{
    private readonly IMilestoneManager _service;
    public ApproveMilestoneController(IMilestoneManager service)
    {
        _service = service;
    }

    [HttpGet]
    [Route("getMilestones")]
    public IActionResult GetPaymentMilestones()
    {
        return Ok(_service.GetMilestonesToApproveForPayment(1, 50));
    }
}

I'm attaching app.module code but getting error here while formatting so please let me know what's wrong

Token:

eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6Imwzc1EtNTBjQ0g0eEJWWkxIVEd3blNSNzY4MCJ9..d8rTl15ew3Z9AHLxWEnuXcEZjn1hWcHqkoqv8DlnhXF7C7NNACrmzEGiuXYBXccCgwA5C2SO4O8HMeQEti7B-6BfTUQFDpj3eMHHpTpGaFtIN7qy9dVTfelEY-oMfufHr3sQa3eRpxSvjVfN8f1QVdzzW-vp2f4c6ECpXnX-5ZOxeUDru4s4RlRm6GtyfENzPUEKN-v_ZL2VGsdEbGGdHsP-lkN5veygwyb4DcnpAxVzlAFRgxWIEgSYHUXnSpVbl_rrRkcebD7ZoTJm1AgTnNIXqGuQzWBE9_EBLPncc9vzLLCM6FFctlmBnW6qn8-f8BtoNm8fJ-EIYSxajjJ-nw

But still getting 401 error and audience is invalid.

I tested same clientId and tenantId with sample code and it works fine. but not working in my actual code

Some work arounds you may try:

  1. The ISS value of token has v2 endpoint("iss": "https://login.microsoftonline.com/xxx/v2.0") , please make sure "accessTokenAcceptedVersion": 2, in app manifest file in azure portal. It maybe 0 or 1 by default.

在此处输入图片说明

Make sure you check marked the Access token in portal while registering the app. you can track the token you get in jwt.io . Azure AD audience must match the “aud” claim when. The Audience must equal the AppIduri or client id set for the application.

  1. Make sure to expose an api in azure ad.

在此处输入图片说明

在此处输入图片说明

Give api permissions and add that scope with that permission and make sure to grant consent if required.

在此处输入图片说明

  1. Check the Application Id URI value when you expose the api and try placing the same value for client Id in your Application code. For example if in portal app id uri=api://, then in app settings, make sure client id: api://

And make sure the scopes are same in portal and code.

References:

  1. SO ref1
  2. SO ref2

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM