azure-active-directoryasp.net-core-webapiangular9asp.net-core-3.1angular2-jwt

Call .NET CORE Web API Secure End-point from Angular by passing Azure B2C JWT Bearer token


I need to call secure Web API from Angular 9 application by presenting the Azure B2C JWT Bearer token. I am using Angular 9 with .NET CORE 3.1 Web API. I have managed to generate Azure B2C token but stuck to call secure Web API end-point as I am getting 401 unauthorized error. I am passing token in the header from angular.

Angular component calling Web API end-point

testAPI1(){
    console.log("calling test API ...");

    const myheaders = new HttpHeaders({
        'Content-Type': 'application/json; charset=utf-8',
        'Authorization': this.authService.accessToken
    });

    this.http.get('https://localhost:5001/txn/v1/Dashboard/GetMessage', {headers: myheaders})
        .subscribe((data)=>{
            console.warn(data);
        })
}

Auth Service

@Injectable()
export class AuthService implements OnInit{

constructor(
    private oauthService: OAuthService,
    private router: Router

){// other code}


public get accessToken() { 
    return this.oauthService.getAccessToken(); 
}

Web API controller & endpoint

[Authorize]
[Route("txn/v1/[controller]/[action]")]
[EnableCors("CorsPolicy")]
[ApiController]
public class DashboardController : ControllerBase
{
    [HttpGet]
    public ActionResult<HelloMessage> GetMessage()
    {
        var result = new HelloMessage()
        {
            GivenName = "james",
            ReturnMessage = "Dashboard@ Hello, Welcome to Digital tech"
        };
        return result;
    }

Startup.cs

public void ConfigureServices(IServiceCollection services)
    {
       //JWT Authentication 
        services.AddAuthentication(options =>
        {
            options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
            options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
        }).AddJwtBearer(jwtConfig => 
            {
                jwtConfig.Audience = Configuration["AzureAdB2C:ResourceId"];
                jwtConfig.Authority = $"{Configuration["AzureAdB2C:Instance"]}{Configuration["AzureAdB2C:TanantId"]}";
                jwtConfig.RequireHttpsMetadata = false;
                jwtConfig.SaveToken = true;
                jwtConfig.TokenValidationParameters = new TokenValidationParameters
                {
                    ValidateIssuerSigningKey = true,
                    ValidateIssuer =true,
                    ValidateAudience = true,
                    ValidateLifetime = true

                };
        });

 //CORS policy
 services.AddCors(options =>
                          options.AddPolicy("CorsPolicy", builder => builder.AllowAnyOrigin()));

error

enter image description here

request header in response

enter image description here

visual studio event exception

enter image description here

PII is Hidden error

enter image description here


Solution

  • According to the code you provided, you use the wrong Authority. If we use Azure AD B2C, the Authority should be likehttps://{your-tenant-name}.b2clogin.com/tfp/{your-tenant-domain}/{your-policy-name}/v2.0.

    For example

    Web API Application

    a. appsettings.json.

    {
      "AzureAdB2C": {
        "Instance": "https://<your tenant name>.b2clogin.com",
        "ClientId": " your client id",
        "Domain": "your tenant domain",
    "TenantId": "your tenant id",
        "SignUpSignInPolicyId": "your policy name"
      },
      ...
    }
    

    b. Startup.cs.

     public void ConfigureServices(IServiceCollection services)
            {
                services.AddAuthentication(options =>
                {
                    options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                    options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
                }).AddJwtBearer(jwtConfig =>
                {
                    jwtConfig.Audience = Configuration["AzureAdB2C:ClientId"];
                    jwtConfig.Authority = $"{Configuration["AzureAdB2C:Instance"]}/tfp/{Configuration["AzureAdB2C:Domain"]}/{Configuration["AzureAdB2C:SignUpSignInPolicyId"]}/v2.0";
                    jwtConfig.RequireHttpsMetadata = false;
                    jwtConfig.SaveToken = true;
                    jwtConfig.TokenValidationParameters = new TokenValidationParameters
                    {
                        ValidateIssuerSigningKey = true,
                        ValidateIssuer = true,
                        ValidateAudience = true,
                        ValidateLifetime = true,
                        ValidAudience= jwtConfig.Audience,
                        ValidIssuer = $"{Configuration["AzureAdB2C:Instance"]}/{Configuration["AzureAdB2C:TenantId"]}/v2.0/"
                    };
    
                });
    
                services.AddCors(options =>
                {
                    options.AddDefaultPolicy(
                        builder => builder.AllowAnyOrigin()
                            .AllowAnyHeader()
                            .AllowAnyMethod());
                });
                services.AddControllers();
            }
    

    Angular component calling Web API end-point

    public getMessage() {
        const myheaders = new HttpHeaders({
          'Content-Type': 'application/json; charset=utf-8',
          'Authorization': 'Bearer '+this.oauthService.getAccessToken(),
          'Access-Control-Allow-Origin':'*'
      });
       console.log(myheaders)
        this.http.get("https://localhost:44389/weatherforecast", {headers: myheaders})
          .subscribe(r => {
            this.message = JSON.stringify(r) 
            console.log("message: ", this.message);
          });
      }
    
    

    enter image description here