Angular ASP.NET Core Web API Windows Authentication
▌Introduction
This is a tutorial of how to set windows authentication on ASP.NET Core Web API and send a request with Angular to get the current windows user. There will 4 parts in the article.
1. Enable windows authentication on ASP.NET Core Web API(on IIS
integration or HTTP.sys)
2. Angular: fail try
3. Angular: solve problem with Http Interceptors
▌Environment
▋Angular 5.0.0
▋ASP.NET Core 2.0
▋Windows 7
▌Implement: Enable windows authentication
▋Enable windows
authentication on ASP.NET Core Web API
Enable windows authentication by putting the
following settings to appsettings.json.
▋appsettings.json
"iisSettings": {
"windowsAuthentication": true,
"anonymousAuthentication": true
}
Set "anonymousAuthentication" to false if you want to deny the request from anonymous user.
Or you can easily enable
windows authentication in Visual Studio like following.
The settings are stored in ./Prperties/launchSettings.json
▋appsettings.json
"iisSettings": {
"windowsAuthentication": true,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:9486/",
"sslPort": 0
}
}
▋For HTTP.sys
▋Program.cs
public static void Main(string[] args)
{
BuildWebHost(args).Run();
}
public static IWebHost BuildWebHost(string[] args)
=>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.UseHttpSys(options =>
{
options.Authentication.Schemes =
AuthenticationSchemes.NTLM | AuthenticationSchemes.Negotiate;
options.Authentication.AllowAnonymous = true;
})
.Build();
}
▋Startup.cs
public void ConfigureServices(IServiceCollection
services)
{
services.AddMvc();
services.AddAuthentication(HttpSysDefaults.AuthenticationScheme);
}
▋For IIS integration
▋Program.cs
public static void Main(string[] args)
{
BuildWebHost(args).Run();
}
public static IWebHost BuildWebHost(string[] args)
=>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.UseIISIntegration()
.Build();
}
▋Startup.cs
public void ConfigureServices(IServiceCollection
services)
{
services.AddMvc();
services.AddAuthentication(
Microsoft.AspNetCore.Server.IISIntegration.IISDefaults.AuthenticationScheme);
Microsoft.AspNetCore.Server.IISIntegration.IISDefaults.AuthenticationScheme);
}
Now let’s write a HttpGet
method for later testing.
[HttpGet("IsAdmin")]
[Authorize]
public async Task<bool> IsAdmin()
{
var userId
= HttpContext.User.Identity.Name;
base._logger.Info($"Windows
User for request : {userId}");
return true;
}
▌Implement: Angular
▋Service &
Component
Notice that we have to send
the request with http header:
withCredentials: true
to make the request a user
credential, like a cookie, to the server side.
▋MyService.ts
import { HttpClient, HttpHeaders } from "@angular/common/http";
export class YearEndService {
private httpHeaders: HttpHeaders;
constructor(
private http: HttpClient,
private uriService: RestUriService) {
this.httpHeaders = new HttpHeaders({
'Content-Type': 'application/json',
'withCredentials': 'true'
});
}
public isAdmin() {
return this.http.get("http://localhost:3214/api/blablabla", {headers:this.httpHeaders});
}
}
▋MyComponent.ts
export class MyComponent implements OnInit {
constructor() {
}
ngOnInit() {
this.ypService.isAdmin().subscribe(rtn => {})
}
}
The above codes will result
in HTTP 401 Unauthorized on Chrome or Firefox, but works fine on IE.
▋Why not working on Chrome/Firefox
Incorrect request (Chrome):
But the success request
must be like …
▋Solve the problem by HTTP
Interceptors
We will attach the withCredentials
header to every request by HTTP
Interceptors to guarantee sending user credential on the request.
First create a WinAuthInterceptor
to implement HttpInterceptor
▋WinAuthInterceptor.ts
import { Injectable } from '@angular/core';
import { HttpRequest, HttpHandler,
HttpInterceptor, HttpEvent} from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
@Injectable()
export class
WinAuthInterceptor implements HttpInterceptor {
constructor() {
}
intercept(request: HttpRequest<any>, next: HttpHandler):
Observable<HttpEvent<any>> {
// request =
request.clone({ headers: request.headers.set('withCredentials', 'true') });
request = request.clone({
withCredentials: true
});
return
next.handle(request);
}
}
▋app.module.ts
Enable our Http Interceptor
on every request like following.
import { HttpClientModule } from '@angular/common/http';
import { HTTP_INTERCEPTORS } from '@angular/common/http';
import { WinAuthInterceptor } from './class/winAuthInterceptor';
@NgModule({
declarations: [
//…
],
imports: [
HttpClientModule,
AppRouteModule
],
providers: [
{
provide: HTTP_INTERCEPTORS,
useClass: WinAuthInterceptor,
multi: true
}
],
//…
})
export class AppModule { }
▋MyService.ts
public isAdmin() {
return this.http.get("http://localhost:3214/api/blablabla");
}
The Http Interceptor will
solve the problem of losing user credentials in Chrome/Firefox.
▌Reference
沒有留言:
張貼留言