簡體   English   中英

如何配置.net內核angular azure AD認證?

[英]How to configure .net core angular azure AD authentication?

我目前正在研究 Azure AD 身份驗證集成到 Angular -.Net core 3.1 項目。 這是一個從 Visual Studio 2019 模板(ASP.NET Core Web App)生成的項目。
在 Azure 門戶中,我注冊了 2 個應用程序並通過MS 教程配置。

兩個注冊的應用程序:

  1. frontend_app(客戶端ID:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxx16e3)
  2. backend_api(客戶端ID:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxfcc1)

但是我只發布了一個App服務,其中包含SPA和API。 登錄后,我得到一個令牌,它是 append 到每個 api 調用與 MSAL 攔截器。

問題是所有的調用返回都是:401,由於“觀眾無效”。 在 auth 令牌中,受眾重視 frontend_app 的客戶端 ID。

我該如何解決才能接受觀眾? 僅對一項應用服務使用 2 個應用注冊是否正確?

我和你有同樣的問題,相信我已經想出了一個解決方案。 我最初遵循的所有指南都使用隱式流程。 正如卡爾在他的回答中指出的那樣(我認為這不能正確解決您的問題),有一個身份驗證流程,這是 go 的推薦方式。 不幸的是,所有示例和指南中的標准 MSAL 庫都是 1.x,不支持身份驗證流程。 相反,您需要使用MSAL.js 2.0 問題是 angular 庫仍處於alpha階段

所以,這就是我所做的一切。 我正在使用 Angular 10 前端和 ASP.NET Core 3.1 后端。

首先,您創建后端 api 應用注冊(您可能不需要更改)。 這是相關的文檔: 注冊 Web API 重要筆記:

  • 使用此方法,您無需將前端客戶端 ID 添加為“公開 API”部分下的授權應用程序。 我們將使用身份驗證流程以不同方式處理。
  • 不需要重定向 URI,因為您的后端不會讓用戶登錄
  • 您至少需要一個 scope 才能正常工作

然后按照MSAL.js 2.0文檔創建前端應用注冊。 重要說明如下:

  • 確保您的 SPA 平台 select 並輸入有效的重定向 URI
  • 不要選中“隱式授予”復選框
  • 在“API 權限”下,讓您的前端應用程序訪問您的后端 api:
    • 在“API 權限”下單擊“添加權限”,然后單擊“我的 API”選項卡
    • 找到您的后端應用程序和 select 和相應的 scope。
    • 點擊“添加權限”
    • (可選)為您的 API 授予同意

您的應用注冊應類似於以下內容:

后端應用程序注冊公開 api

前端應用注冊認證

前端應用注冊 api 權限

現在是代碼。 對於您的 angular 應用程序,首先安裝必要的模塊:

npm install @azure/msal-browser @azure/msal-angular@alpha

然后將其添加到您的應用程序模塊中:

import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { APP_INITIALIZER, NgModule } from '@angular/core';
import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
import { tap } from 'rxjs/operators';
import {
  IPublicClientApplication,
  PublicClientApplication,
  InteractionType,
  BrowserCacheLocation,
  LogLevel,
} from '@azure/msal-browser';
import {
  MsalGuard,
  MsalInterceptor,
  MsalBroadcastService,
  MsalInterceptorConfiguration,
  MsalModule,
  MsalService,
  MSAL_GUARD_CONFIG,
  MSAL_INSTANCE,
  MSAL_INTERCEPTOR_CONFIG,
  MsalGuardConfiguration,
} from '@azure/msal-angular';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';

const PROTECTED_RESOURCE_MAP: Map<string, Array<string>> = new Map([
  ['https://graph.microsoft.com/v1.0/me', ['user.read']],
  [
    'api/admin/users',
    ['api://<backend app id>/access_as_admin'],
  ],
]);

const IS_IE =
  window.navigator.userAgent.indexOf('MSIE ') > -1 ||
  window.navigator.userAgent.indexOf('Trident/') > -1;

export function loggerCallback(logLevel, message) {
  console.log(message);
}

export function MSALInstanceFactory(): IPublicClientApplication {
  return new PublicClientApplication({
    auth: {
      clientId: '<frontend app id>',
      authority:
        'https://login.microsoftonline.com/<azure ad tenant id>',
      redirectUri: 'http://localhost:4200',
      postLogoutRedirectUri: 'http://localhost:4200/#/logged-out',
    },
    cache: {
      cacheLocation: BrowserCacheLocation.LocalStorage,
      storeAuthStateInCookie: IS_IE, // set to true for IE 11
    },
    system: {
      loggerOptions: {
        loggerCallback,
        logLevel: LogLevel.Verbose,
        piiLoggingEnabled: false,
      },
    },
  });
}

export function MSALInterceptorConfigFactory(): MsalInterceptorConfiguration {
  return {
    interactionType: InteractionType.Redirect,
    protectedResourceMap: PROTECTED_RESOURCE_MAP,
  };
}

export function MSALGuardConfigFactory(): MsalGuardConfiguration {
  return {
    interactionType: InteractionType.Redirect,
  };
}

export function initializeApp(appConfig: AppConfigService) {
  const promise = appConfig
    .loadAppConfig()
    .pipe(tap((settings: IAppConfig) => {}))
    .toPromise();
  return () => promise;
}

@NgModule({
  declarations: [AppComponent],
  imports: [
    BrowserModule,
    BrowserAnimationsModule,
    AppRoutingModule,
    HttpClientModule,
    MsalModule,
  ],
  providers: [
    {
      provide: HTTP_INTERCEPTORS,
      useClass: MsalInterceptor,
      multi: true,
    },
    {
      provide: MSAL_INSTANCE,
      useFactory: MSALInstanceFactory,
    },
    {
      provide: MSAL_GUARD_CONFIG,
      useFactory: MSALGuardConfigFactory,
    },
    {
      provide: MSAL_INTERCEPTOR_CONFIG,
      useFactory: MSALInterceptorConfigFactory,
    },
    MsalService,
    MsalGuard,
    MsalBroadcastService,
  ],
  bootstrap: [AppComponent],
})
export class AppModule {}

然后,您可以簡單地將MsalGuard扔到您想要保護的任何路線上。

對於后端,首先安裝 Microsoft.Identity.Web package:

dotnet add package Microsoft.Identity.Web --version 1.3.0

這是我的 Startup.cs 中的相關代碼:

public void ConfigureServices(IServiceCollection services)
{
  // other stuff...
  services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddMicrosoftIdentityWebApi(options =>
    {
      Configuration.Bind("AzureAd", options);
    })
    .AddInMemoryTokenCaches();

  services.AddCors((options =>
  {
    options.AddPolicy("FrontEnd", builder =>
      builder.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader());
  }));
  // other stuff...
}
 
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
  // other stuff...
  app.UseCors("FrontEnd");
  app.UseAuthentication();
  app.UseAuthorization();
  // other stuff...
}

appsettings.json 包含:

"AzureAd": {
  "Instance": "https://login.microsoftonline.com/",
  "Domain": "<azure ad domain>",
  "TenantId": "<azure ad tenant id>",
  "ClientId": "<backend app id>"
}

正如我在評論中所說,401錯誤通常是因為您的受眾與您要調用的 api 不匹配,因此您需要確保您的目標受眾是您的 api,在您的問題中它應該是您的backend_api ,我使用auth 代碼流為您做一個簡單的演示:

在此處輸入圖像描述

獲取令牌: 在此處輸入圖像描述

解析令牌:

在此處輸入圖像描述

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM