如何将Saml身份验证添加到asp.net Web API应用程序

时间:2019-04-15 10:28:23

标签: angular asp.net-web-api azure-active-directory

我有一个Web应用程序,其asp.net Web Api后端是一个有角度的前端。 该应用程序使用基于表单的身份验证,可以根据其数据库检查用户的身份。

我受命向以Azure AD作为身份提供者的应用程序添加Saml身份验证。

我已经尝试使用SustainSys: Add SAML Authentication to .net WebAPI

这种方法的问题在于,Angular SPA不是由Saml Authentication的最终重定向触发的,因此不执行登录操作。

我正在评估的另一个选项是Adal: https://www.npmjs.com/package/microsoft-adal-angular6

在这种情况下,我不知道我应该在Web API中实现什么来执行身份验证。

添加这种身份验证的正确方法是什么?

1 个答案:

答案 0 :(得分:0)

您可以在这里进行一些操作,以确保角度SPA和asp.net核心Web API的安全。

技术解决方案

1)实施Web application to web API authentication scenario

2)使用https://portal.azure.com配置身份验证过程。

3)Use adal-angular4(版本3.0.1+)用于在角度应用程序中实现身份验证的角度包。

4)使用Microsoft.AspNetCore.Authentication.AzureAD.UI NuGet包在Asp.Net核心Web API服务中实施身份验证。

先决条件

注册Angular应用程序

通过https://portal.azure.com在Azure Active Directory中注册应用程序 转到“ Azure Active Directory”->“应用程序注册”,然后选择添加“新应用程序注册”。

enter image description here

注册Web API

https://portal.azure.com在Azure Active Directory中注册Web API服务。 注册过程类似于注册Angular应用程序。 (请参见上文)

配置对Web API资源的访问

客户端应用程序通过声明许可请求来访问资源服务器。 转到Azure Active Directory->应用程序注册,然后选择Angular应用程序的设置。

选择Angular应用程序访问的Web API:

enter image description here

启用具有委派权限的访问权限

enter image description here

所需的资源(Web API)访问权限已添加到已注册的Angular应用程序清单中:

enter image description here

授予对Web API资源的访问权限

enter image description here

安装adal包

nstall adal软件包adal-angular4(版本3.0.1+)。软件包adal-angular4已更新为与angular6兼容。找到正确的程序包会造成混淆,因为程序包名称引用的是角度4,而且还因为存在另一个与角度6不兼容的程序adal-angular5。

技术解决方案

身份验证过程

第一步:

当用户第一次通过浏览器访问该应用程序时,Angular应用程序会检测到该应用程序未通过身份验证,并重定向到Microsoft登录名以引入凭据。

enter image description here

第2步:

登录步骤之后,身份验证服务将过程重定向到已配置的角度应用程序回调,在此回调过程中完成身份验证过程。

第3步:

Angular应用程序调用所需的Web API。在调用Web API之前,身份验证令牌已添加到HTTP标头中。

第4步:

Web API会验证身份验证令牌,并在成功的情况下返回请求的资源。

实施

步骤1:

a)配置ADAL服务

import { Component } from '@angular/core';
import { AdalService } from 'adal-angular4';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'app';

  private adalConfig = {
    tenant: '[TENANT_GUID]',
    clientId: '[CLIENTID_GUID]',
    redirectUri: "[LOGIN_REDIRECT_URL]",
    postLogoutRedirectUri: "[POST_LOGOUT_REDIRECT_URL]",
    endpoints: {
      "[HOME_URL_WEB_API]": "[HOME_WEB_API_GUID]"
    }
  }

  constructor(private adal: AdalService) {
    this.adal.init(this.adalConfig);
  }

  signOut(): void {
    this.adal.logOut();
  }
}

[TENANT_GUID]是Azure AD目录ID。

enter image description here

b)实施一种保护措施,以防未经身份验证的请求重定向到登录

import { Injectable } from '@angular/core';
import { CanActivate } from '@angular/router';
import { AdalService } from 'adal-angular4';

@Injectable({
  providedIn: 'root'
})
export class AuthGuard implements CanActivate {

  constructor(private adal: AdalService) { }

  canActivate(): boolean {

    if (this.adal.userInfo.authenticated) {
      return true;
    }

    this.adal.login();

    return false;
  }

}

c)保护路由器类中的应用程序路径:

const routes: Routes = [
  { path: '', component: MyComponent, canActivate: [AuthGuard] },
  { path: 'auth-callback', component: AuthCallbackComponent },
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule {}

步骤2:-完成登录过程。

实现一个回调组件,该组件将在登录过程中被调用。 在为adal配置redirectUri信息时,回调URL的注册在步骤1中完成。

import { Component, OnInit, NgZone } from '@angular/core';
import { Router } from '@angular/router';
import { AdalService } from 'adal-angular4';

@Component({
  selector: 'app-auth-callback',
  templateUrl: './auth-callback.component.html',
  styleUrls: ['./auth-callback.component.css']
})
export class AuthCallbackComponent implements OnInit {

  constructor(private router: Router, private adal: AdalService, private _zone: NgZone) { }

  ngOnInit() {
    this.adal.handleWindowCallback();

    setTimeout(() = {
      this._zone.run(
        () = this.router.navigate(['/'])
      );
    }, 200);
  }

}

handleWindowCallback()将身份验证令牌添加到会话中。

第3步:

为发送到Web API的HTTP请求设置身份验证令牌 Adal使其简单易行。唯一要做的步骤是在app.module.ts文件中注册开箱即用的AdalInterceptor:

从'@ angular / platform-b​​rowser'导入{BrowserModule}; 从'@ angular / core'导入{NgModule}; 从'@ angular / common / http'导入{HttpClientModule}; 从'@ angular / forms'导入{FormsModule};

import { AppComponent } from './app.component';
import { AppRoutingModule } from './/app-routing.module';
import { HTTP_INTERCEPTORS } from '@angular/common/http';
import { AuthCallbackComponent } from './auth-callback/auth-callback.component';
import { AdalService, AdalInterceptor } from 'adal-angular4';

@NgModule({
  declarations: [
    AppComponent,
    AuthCallbackComponent
  ],
  imports: [
    BrowserModule,
    HttpClientModule,
    AppRoutingModule,
    FormsModule
  ],
  providers: [AdalService, { provide: HTTP_INTERCEPTORS, useClass: AdalInterceptor, multi: true }],
  bootstrap: [AppComponent]
})
export class AppModule { }

第4步:

验证Web API服务中的身份验证令牌 在Web API Startup.cs文件中将身份验证服务配置为AzureADBear:

public void ConfigureServices(IServiceCollection services)
{

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

    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
    services.AddCors(options = 
    {
        options.AddPolicy("AllowAllOrigins",
         builder =
         {
             builder.AllowAnyMethod().AllowAnyHeader().AllowAnyOrigin();
         });
    });
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseHsts();
    }

    app.UseHttpsRedirection();

    app.UseCors("AllowAllOrigins");
    app.UseAuthentication();

    app.UseStaticFiles();
    app.UseMvc(routes =
    {
        routes.MapRoute(name: "default", template: "api/{controller}/{id}");
    });
}

请确保已安装先决条件部分中提到的Microsoft.AspNetCore.Authentication.AzureAD.UI NuGet程序包。 在appsettings.json中添加AzureAD部分,以提供验证过程的身份验证详细信息:

"AzureAd": {
  "Instance": "https://login.microsoftonline.com",
  "Domain": "[AD_DOMAIN]",
  "TenantId": "[TENANTID_GUID]",
  "ClientId": "[CLIENTID_GUID]"
}

用以下信息替换上述占位符:

[AD_DOMAIN]是Azure AD域。

[TENANT_GUID]是Azure AD目录ID。 (请参见上文)

[CLIENTID_GUID]是Web API的应用程序ID。

最后用以下过滤器属性装饰您的控制器:

[Authorize]
[ApiController]
public class MyController : ControllerBase

希望有帮助。