0
votes

I am trying to call WebAPI from angularUI using AzureAD protection but I am this facing this error:

zone-evergreen.js:2952 GET https://localhost:44319/api/employee 401:

I have also refered below blog:

Azure AD Authentication In Angular And ASP.NET Core Web API App

msal.service.ts

import { Injectable } from '@angular/core';
import { BroadcastService, MsalService } from '@azure/msal-angular';
import * as Msal from 'msal';
import { environment } from '../../environments/environment';
import { Observable } from 'rxjs';

@Injectable()
export class MsalUserService {
  private accessToken: any;
  public clientApplication: Msal.UserAgentApplication = null;
  constructor() {
    this.clientApplication = new Msal.UserAgentApplication(
      environment.uiClienId,
      'https://login.microsoftonline.com/' + environment.tenantId,
      this.authCallback,
      {
        storeAuthStateInCookie: true,
        //cacheLocation: 'localStorage' ,  
      });
  }

  public GetAccessToken(): Observable<any> {
    if (sessionStorage.getItem('msal.idtoken') !== undefined && sessionStorage.getItem('msal.idtoken') != null) {
      this.accessToken = sessionStorage.getItem('msal.idtoken');
      console.log(this.accessToken);
    }
    return this.accessToken;
  }

  public authCallback(errorDesc, token, error, tokenType) {
    if (token) {

    } else {
      console.log(error + ':' + errorDesc);
    }
  }

  public getCurrentUserInfo() {
    const user = this.clientApplication.getUser();
    alert(user.name);
  }

  public logout() {
    this.clientApplication.logout();

I have set the environment file as follows:

export const environment = {
  production: false,
  baseUrl: 'https://localhost:44319/',
  scopeUri: ['api://3b4451a3-f813-4980-a477-fa8077138b8a/UserRead'],
  tenantId: 'e2xt89c0-058e-4dde-bb96-46de5ff97fe5',
  uiClienId: '9ebpqb4f-ee19-43c4-a221-2fec4930a1ec',
  redirectUrl: 'http://localhost:4200'
};  

app.module.ts

import { AppComponent } from './app.component';
import { NavMenuComponent } from './nav-menu/nav-menu.component';
import { HomeComponent } from './home/home.component';
import { CounterComponent } from './counter/counter.component';
import { FetchDataComponent } from './fetch-data/fetch-data.component';
import { EmployeeComponent } from './employee/employee.component';

export const protectedResourceMap: any =
  [
    [environment.baseUrl, environment.scopeUri
    ]
  ];

@NgModule({
  declarations: [
    AppComponent,
    NavMenuComponent,
    HomeComponent,
    CounterComponent,
    FetchDataComponent,
    EmployeeComponent
  ],
  imports: [
    MsalModule.forRoot({
      clientID: environment.uiClienId,
      authority: 'https://login.microsoftonline.com/' + environment.tenantId,
      protectedResourceMap: protectedResourceMap,
      redirectUri: environment.redirectUrl
    }), 
    BrowserModule.withServerTransition({ appId: 'ng-cli-universal' }),
    AppRoutingModule,  
    HttpClientModule,
    FormsModule,
  ],
  providers: [HttpClient,
    MsalUserService,
    {
      provide: HTTP_INTERCEPTORS, useClass: MsalInterceptor, multi: true
    }
  ],  
  bootstrap: [AppComponent]
})
export class AppModule { }

Employee.ts

import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Observable } from 'rxjs';
import { environment } from '../../environments/environment';
import { MsalUserService } from '../service/msaluser.service';
import { EmployeeModel } from './employeemodel';

@Injectable({
  providedIn: 'root'
})
export class EmployeeService {
  private url = environment.baseUrl + 'api/employee';

  httpOptions = {
    headers: new HttpHeaders({
      'Content-Type': 'application/json'
    })
  };

  constructor(private http: HttpClient, private msalService: MsalUserService
  ) { }

  getEmployees(): Observable<EmployeeModel[]> {

    this.httpOptions = {
      headers: new HttpHeaders({
        'Content-Type': 'application/json',
        'Authorization': 'Bearer ' + this.msalService.GetAccessToken()
      })

    };
    console.log(this.url);
    return this.http.get(this.url, this.httpOptions)
      .pipe((response: any) => {
        return response;
      });
  }

  getCurrentUserInfo() {
    this.msalService.getCurrentUserInfo();
  }

  logout() {
    this.msalService.logout();
  }
}  

appsetting.json

"AzureActiveDirectory": {
    "Instance": "https://login.microsoftonline.com/",
    "Domain": "mydomain.onmicrosoft.com",
    "TenantId": "e2xt89c0-058e-4dde-bb96-46de5ff97fe5",
    "ClientId": "api://3bdd4161a3-f813-4980-a477-fa8077138b8a"
  }

StartUp.cs

public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllersWithViews();
            // In production, the Angular files will be served from this directory
            services.AddSpaStaticFiles(configuration =>
            {
                configuration.RootPath = "ClientApp/dist";
            });

            services.AddAuthentication(AzureADDefaults.BearerAuthenticationScheme).AddAzureADBearer(options => Configuration.Bind("AzureActiveDirectory", options));

            string corsDomains = "http://localhost:4200";
            string[] domains = corsDomains.Split(",".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);

            
            services.AddCors(o => o.AddPolicy("AppCORSPolicy", builder =>
            {
                builder.AllowAnyOrigin()
                       .AllowAnyMethod()
                       .AllowAnyHeader()
                       .AllowCredentials()
                       .WithOrigins(domains);
            }));
        }

        // 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();
            }
            else
            {
                app.UseExceptionHandler("/Error");
                // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
                app.UseHsts();
            }
            app.UseCors("AppCORSPolicy");
            app.UseHttpsRedirection();
            app.UseStaticFiles();
            if (!env.IsDevelopment())
            {
                app.UseSpaStaticFiles();
            }

            app.UseRouting();
            app.UseAuthentication();
            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllerRoute(
                    name: "default",
                    pattern: "{controller}/{action=Index}/{id?}");
            });

            app.UseSpa(spa =>
            {
                // To learn more about options for serving an Angular SPA from ASP.NET Core,
                // see https://go.microsoft.com/fwlink/?linkid=864501

                spa.Options.SourcePath = "ClientApp";

                if (env.IsDevelopment())
                {
                    spa.UseAngularCliServer(npmScript: "start");
                }
            });
        }

EmployeeController.cs

  [Authorize]
    [Route("api/[controller]")]
    [ApiController]
    public class EmployeeController : ControllerBase
    {
        [HttpGet]
        public IEnumerable<Employee> Get()
        {
            List<Employee> employees = new List<Employee>
            {
                new Employee { Id = 1, Name = "AA", Company = "ABC", City = "xyz" },
                new Employee { Id = 2, Name = "BB", Company = "ABC", City = "xyz" },
                new Employee { Id = 3, Name = "CC", Company = "ABC", City = "xyz" }
            };
            return employees;
        }
    }

It is showing error in network that "zone-evergreen.js:2952 GET https://localhost:44319/api/employee 401"

Please help me to solve this issue. Thank you in advance.

1

1 Answers

0
votes

I have made one of the common mistakes. I have pass baseurl in environment.ts with http, but it should be https.

export const environment = {
  production: false,
  baseUrl: 'https://localhost:44319/',
  scopeUri: ['api://3b4451a3-f813-4980-a477-fa8077138b8a/UserRead'],
  tenantId: 'e2xt89c0-058e-4dde-bb96-46de5ff97fe5',
  uiClienId: '9ebpqb4f-ee19-43c4-a221-2fec4930a1ec',
  redirectUrl: 'http://localhost:4200'
};  

I hope this can help someone and save time.