3
votes

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

1
I believe the issue is in HttpClient request header! but not sure 100%Toxic
Usually this is because your token is wrong or mismatched, so check the access token you pass in to make sure it is correct.Carl Zhao
Could you please provide the screenshot of your request headers and which sdk you use to configure auth?Jim Xu
Hi Jim, I have put a screenshot of request header in above question, please refer to itToxic
Hi. When we call the api projected by Azure AD b2C, we should set Authorization header as Bearer {accessToken}Jim Xu

1 Answers

2
votes

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