3

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

K.Z
  • 5,201
  • 25
  • 104
  • 240
  • 1
    I believe the issue is in HttpClient request header! but not sure 100% – K.Z Jul 08 '20 at 14:30
  • 1
    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 Jul 09 '20 at 02:09
  • 1
    Could you please provide the screenshot of your request headers and which sdk you use to configure auth? – Jim Xu Jul 09 '20 at 03:51
  • 1
    Hi Jim, I have put a screenshot of request header in above question, please refer to it – K.Z Jul 09 '20 at 07:40
  • 3
    Hi. When we call the api projected by Azure AD b2C, we should set `Authorization` header as `Bearer {accessToken}` – Jim Xu Jul 09 '20 at 09:14
  • 1
    I have added Bearer token and not getting 401 error but there is still something missing... I got an exception on .NET CORE Web API side... I paste the error in question ... many thanks for support me on this – K.Z Jul 09 '20 at 09:19
  • 1
    Maybe this one? https://stackoverflow.com/a/50744127/1595293 – Luke Duda Jul 09 '20 at 12:54

1 Answers1

3

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

Jim Xu
  • 21,610
  • 2
  • 19
  • 39
  • Hi Jim ... many thanks I was so stuck with this... I have managed to get token ... another small relevant issue but working on it – K.Z Jul 11 '20 at 08:31