AzureAD / microsoft-authentication-library-for-js

Microsoft Authentication Library (MSAL) for JS
http://aka.ms/aadv2
MIT License
3.64k stars 2.65k forks source link

Interceptor Question / Maybe a bug #3150

Closed johnfabian closed 3 years ago

johnfabian commented 3 years ago

Library

Description

I have azure b2c and MSAL authentication is working fine and I seem to have everything configured correctly but when I try to call my web api (localhost:5000) in the console I see the following:

@angular/msal-angular@2.0.0-beta.0: Error - Interceptor - acquireTokenSilent resolved with null access token. Known issue with B2C tenats, invoking interaction to resolve

Emitting event: masl:aquireTokenStart

Then it seems to do a redirect page, refreshes and API is never called. I have a redirect to localhost in b2c for the API and have the following set:

export const apiConfig: {scopes: string[]; uri: string} = { scopes: ['https://xxx.onmicrosoft.com/api1/users.access.all'], uri: 'http://localhost:5000' };

It doesn't even seem to be hitting my web api at all just redirects which guess may something with the B2C an web api. Am I missing something? I have the api in the protected resource map

Source

johnfabian commented 3 years ago

I figured out one configuration issue, I needed to add the permission to the api in the angular application setting. I followed the documentation and noticed it was adding app permissions to the api instead of the angular app and I see an access token but still getting access denied . Could this be an issue with trying to use localhost?

When I checked the token in jwt.io I get invalid signature. Really wish there was some documentation on how to configure this with a custom web api. Everything I followed doesn't work but I feel like I'm really close.

pkanher617 commented 3 years ago

@johnfabian Could you post some code snippets of how you are invoking acquireTokenSilent and calling the web API? Verbose-level logs would help us debug this further as well.

johnfabian commented 3 years ago

@pkanher617 Thank you very much for your quick response.

I'm not invoking it manually, I'm using the MSAL interceptor (@azure/msal-angular) that invokes it but I was finally able to get an access token. I had removed and added the web api back into Azure, added scope, permissions, etc then all of a sudden it started working. But now having CORS issues

I'm actually using the example app angular11-b2c-sample but I removed the graph api it calls, replaced with web api and changed all the setting so course.

services.AddCors(o => o.AddPolicy("default", builder =>
            {               
                builder.AllowAnyOrigin()
                          .AllowAnyMethod()
                          .AllowAnyHeader()
                          .AllowCredentials()
                          .WithOrigins("http://localhost:4200");
            }));

services.AddMicrosoftIdentityWebApiAuthentication(Configuration, "AzureAdB2C"); -> this line causes the CORS issue 

--appsettings
"AzureAdB2C": {
      "Instance": "https:/xxx.b2clogin.com", 
      "ClientId": "xxx", 
      "Domain": "xxx.onmicrosoft.com", 
      "SignUpSignInPolicyId": "b2c_1_SignupSign" 
    }

even with the Authorize attribute commented out I'm still getting cors issues.  

//I have this in the configuration:

export const apiConfig: {scopes: string[]; uri: string} = {
    scopes: ['https://xxx.onmicrosoft.com/api1/users.access.all'],
    uri: 'https://xxx.onmicrosoft.com/api1'
};

//I've tried this as well and have a redirect on the web api http://localhost:5000

export const apiConfig: {scopes: string[]; uri: string} = {
    scopes: ['https://xxx.onmicrosoft.com/api1/users.access.all'],
    uri: 'https://localhost:5000'
};

I think the problem is all the examples at least for .net core 5 web api and angular 11 and the current B2C are outdated. I can't find one example of how to set this up and use localhost for development. It works fine without any authentication in startup, it does authenticate with Azure for logging in with angular but when I try call then web api CORS issues now even without the authorize attribute. I have the CORS settings in web api as well so really lost now.

This might be on Microsoft side though at this point but still would be nice to have an example. The one that is currently there (angular11-b2c-sample) is only working with MS graph and not web api. It would be so helpful to everyone if they added a .net core web api to that example so it works with both.

I'm going to keep trying though. I can't believe there isn't one post on this. Is anyone using this? Lol

Thank You

johnfabian commented 3 years ago

@pkanher617

it looks like a .net issue and just displays CORS error because it's an error on the .net side. This is what I'm currently getting. It wants a client id which is what is provided but seems nothing binds in the AddMicrosoftIdentityWebApiAuthentication so I'm totally lost now:

info: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[0] User profile is available. Using 'C:\Users\jfabi\AppData\Local\ASP.NET\DataProtection-Keys' as key repository and Windows DPAPI to encrypt keys at rest. info: Microsoft.Hosting.Lifetime[0] Now listening on: http://localhost:5000 info: Microsoft.Hosting.Lifetime[0] Application started. Press Ctrl+C to shut down. info: Microsoft.Hosting.Lifetime[0] Hosting environment: Development info: Microsoft.Hosting.Lifetime[0] Content root path: C:\TFSProjects\WepApi1 info: Microsoft.AspNetCore.Hosting.Diagnostics[1] Request starting HTTP/1.1 GET http://localhost:5000/weatherforecast warn: Microsoft.AspNetCore.HttpsPolicy.HttpsRedirectionMiddleware[3] Failed to determine the https port for redirect. fail: Microsoft.AspNetCore.Server.Kestrel[13] Connection id "0HM70IOK4SL05", Request id "0HM70IOK4SL05:00000001": An unhandled exception was thrown by the application. Microsoft.Extensions.Options.OptionsValidationException: IDW10106: The 'ClientId' option must be provided. at Microsoft.Extensions.Options.OptionsFactory`1.Create(String name) at Microsoft.Extensions.Options.OptionsMonitor`1.<>c__DisplayClass11_0.<Get>b__0() at System.Lazy`1.ViaFactory(LazyThreadSafetyMode mode) at System.Lazy`1.ExecutionAndPublication(LazyHelper executionAndPublication, Boolean useDefaultConstructor) at System.Lazy`1.CreateValue() at System.Lazy`1.get_Value() at Microsoft.Extensions.Options.OptionsCache`1.GetOrAdd(String name, Func`1 createOptions) at Microsoft.Extensions.Options.OptionsMonitor`1.Get(String name) at Microsoft.Identity.Web.MicrosoftIdentityWebApiAuthenticationBuilderExtensions.<>c__DisplayClass3_0.<AddMicrosoftIdentityWebApiImplementation>b__0(JwtBearerOptions options, IServiceProvider serviceProvider, IOptionsMonitor`1 microsoftIdentityOptionsMonitor) at Microsoft.Extensions.Options.ConfigureNamedOptions`3.Configure(String name, TOptions options) at Microsoft.Extensions.Options.OptionsFactory`1.Create(String name) at Microsoft.Extensions.Options.OptionsMonitor`1.<>c__DisplayClass11_0.<Get>b__0() at System.Lazy`1.ViaFactory(LazyThreadSafetyMode mode) at System.Lazy`1.ExecutionAndPublication(LazyHelper executionAndPublication, Boolean useDefaultConstructor) at System.Lazy`1.CreateValue() at System.Lazy`1.get_Value() at Microsoft.Extensions.Options.OptionsCache`1.GetOrAdd(String name, Func`1 createOptions) at Microsoft.Extensions.Options.OptionsMonitor`1.Get(String name) at Microsoft.AspNetCore.Authentication.AuthenticationHandler`1.InitializeAsync(AuthenticationScheme scheme, HttpContext context) at Microsoft.AspNetCore.Authentication.AuthenticationHandlerProvider.GetHandlerAsync(HttpContext context, String authenticationScheme) at Microsoft.AspNetCore.Authentication.AuthenticationService.AuthenticateAsync(HttpContext context, String scheme) at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context) at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProcessRequests[TContext](IHttpApplication`1 application) info: Microsoft.AspNetCore.Hosting.Diagnostics[2] Request finished in 112.5195ms 500

Here is the configuration which is what I'm seeing in the examples:

public void ConfigureServices(IServiceCollection services)
        {

            //wtf is the azure b2c configuration

            services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
                .AddMicrosoftIdentityWebApi(Configuration, "AzureAdB2C");

            services.AddCors(o => o.AddPolicy("CorsPolicy", builder =>
            {
                builder.WithOrigins("http://localhost:4200")
                       .AllowAnyMethod()
                       .AllowAnyHeader()
                       .AllowCredentials()
                       .SetIsOriginAllowed((host) => true);
            }));

            services.AddControllers();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {

            app.UseHttpsRedirection();

            app.UseRouting();

            app.UseAuthentication();

            app.UseAuthorization();

            app.UseCors("CorsPolicy");

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
        }
johnfabian commented 3 years ago

My entire issue was Kestrel. As soon as I switched to using IISExpress everything worked. Unreal.