如何在 NestJS 中实现 Passport.js Azure AD Bearer Strategy (OpenID)

How to implement Passport.js Azure AD Bearer Strategy ( OpenID ) in NestJS

根据 nestjs 和 passport 的文档,我有以下实现。

我从默认的 nest cli 设置开始,nest new auth-test 然后我在 src 文件夹下添加了一个 auth 文件夹,aad-auth.gaurd、aad.strategy 和 auth.module下面坐。

然后我将新守卫添​​加到 app.controller.ts

中的默认路由

我通过将其成功用作 C# Web API 确认了 Azure 应用程序注册设置,因此 Azure 端设置正确。

我不需要发布 JWT,因为这是 Azure AD 在前端的问题,不记名令牌被传递到 header 中的 API。没有有用的错误,只有 500 内部错误。我注意到很多 Github 要求提供有关使用 nest 以及任何 OAuth 流提供程序(facebook,google)实施 Azure AD 的文档,但该请求目前仍处于开放状态。

不确定实施错误的地方,如有任何指导或建议可修复以下代码,我们将不胜感激。

文档: NestJS:https://docs.nestjs.com/techniques/authentication 护照:http://www.passportjs.org/packages/passport-azure-ad/

//auth/aad.strategy.ts

import { BearerStrategy } from 'passport-azure-ad';
import { PassportStrategy } from '@nestjs/passport';
import { Injectable, ValidationPipe } from '@nestjs/common';

@Injectable() 
export class AADStrategy extends PassportStrategy(BearerStrategy) {
    constructor () {
        super({
            identityMetadata: "https://login.microsoftonline.com/<tenant>.onmicrosoft.com/v2.0/.well-known/openid-configuration",
            clientID: "<clientid>",
            issuer: null,
            audience: null,
            loggingLevel: "info",
            passReqToCallback: false
        })
    }

    async validate(payload: any){
        console.log(payload);
        return(payload);    
    }
}

//auth/aad-auth.gaurd

import { Injectable } from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';

@Injectable()
export class AADAuthGaurd extends AuthGuard('aad') {}

//auth/auth.module.ts

import { Module } from '@nestjs/common';
import { AADStrategy } from './aad.strategy'

@Module({
    imports: [
        AADStrategy,
    ],
    providers: [
        AADStrategy,
    ]
})
export class AuthModule {}

//app.controller.ts

import { Controller, Get, UseGuards } from '@nestjs/common';
import { AppService } from './app.service';
import { AADAuthGaurd } from './auth/aad-auth.gaurd';


@Controller()
export class AppController {
  constructor(private readonly appService: AppService) {}

  @UseGuards(AADAuthGaurd)
  @Get()
  getHello(): string {
    return this.appService.getHello();
  }
}

我解决了这个问题,这是压缩到一个文件中的工作代码。

//app.controller.ts
    import { Controller, Get, Injectable, UseGuards } from '@nestjs/common';
    import { AppService } from './app.service';
    import { AuthGuard, PassportStrategy } from "@nestjs/passport";
    import { BearerStrategy } from 'passport-azure-ad'
    
    @Injectable()
    export class AzureADStrategy extends PassportStrategy(BearerStrategy, 'oauth-bearer')
    {
      constructor()
      {
        super({
          identityMetadata: `https://login.microsoftonline.com/<tenant>.onmicrosoft.com/.well-known/openid-configuration`,
          clientID: 'client id from azure app',
        })
      }
    
      async validate(response: any)
      {
        const { unique_name }: {unique_name: string} = response;
        if (unique_name) return unique_name;
        else return null;
      }
    }
    
    @Controller()
    export class AppController {
      constructor() {}
    
      @Get('unprotected')
      unprotected() : string {
        return 'Unprotected';
      }
    
      @UseGuards(AuthGuard('oauth-bearer'))
      @Get('protected')
      protected() : string {
        return 'Protected';
      }
    }