You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

NestJS集成Azure AD认证遇401问题:Token已获取但鉴权失败

NestJS集成Azure AD认证401问题排查

已成功获取Token,但访问受AzureADGuard保护的接口时返回401访问拒绝,且AzureAdStrategy中的validate方法未被调用。以下是相关代码:

azure-ad.guard.ts

import { Injectable, Logger } from "@nestjs/common";
import { PassportStrategy, AuthGuard } from "@nestjs/passport";
import {BearerStrategy} from "passport-azure-ad";

const clientID = 'my application guid';
const tenantID = 'my tenant guid'; // xxx Tenant

/**
 * Extracts ID token from header and validates it.
 */
@Injectable()
export class AzureAdStrategy extends PassportStrategy(
    BearerStrategy,
    'azure-ad',
){
constructor() {
    super({
        identityMetadata: `https://login.microsoftonline.com/${tenantID}/v2.0/.well-known/openid-configuration`,
        clientID,
        });
    }

    async validate(data) {
        Logger.verbose(data);
        return data;
    }
}

export const AzureADGuard = AuthGuard('azure-ad');

contacts.controller.ts

import { Body, Controller, Get, Param, Patch, Post, Logger, HttpStatus, UseGuards} from '@nestjs/common';
import { ContactsService } from './contacts.service';
import { CreateContactDto } from './dto/create-contact.dto';
import { Contact } from './schema/contact.schema';
import { AzureADGuard } from 'src/azure-ad.guard';

@Controller('contacts')
export class ContactsController {
constructor(private readonly contactsService: ContactsService) {}


@Get(':funechID')
@UseGuards(AzureADGuard)
async getContact(@Param('funechID') funechID: number): Promise<Contact> {
    try {
        return this.contactsService.getContactById(funechID);
    } catch (error) {
       Logger.error(error,"","Class:"+ContactsController.name)
       }
    }
// other methods like @Get ... 
}

排查方向及可能遗漏的配置

  • 检查Token传递格式:确保请求头的Authorization字段严格遵循Bearer <token>格式,Bearer与Token之间必须有一个空格,不能有多余的换行或空格。
  • 验证Token的有效性:
    • 确认使用的是Access Token而非ID Token:调用API接口需要用Access Token,ID Token仅用于身份验证场景。
    • 解码Token查看payload:检查aud(受众)字段是否与你的clientID完全一致,iss(签发者)是否为https://login.microsoftonline.com/${tenantID}/v2.0,exp(过期时间)是否未过期。
  • 补充BearerStrategy关键配置:当前配置缺少验证开关和日志,建议添加以下参数:
    super({
      identityMetadata: `https://login.microsoftonline.com/${tenantID}/v2.0/.well-known/openid-configuration`,
      clientID,
      validateIssuer: true, // 开启签发者验证
      issuer: `https://login.microsoftonline.com/${tenantID}/v2.0`, // 指定合法签发者
      loggingLevel: 'info', // 开启日志,输出验证过程的细节
      passReqToCallback: false,
    });
    
  • 确认Passport模块注册:在根模块(如AppModule)中必须注册PassportModule并引入AzureAdStrategy:
    import { Module } from '@nestjs/common';
    import { PassportModule } from '@nestjs/passport';
    import { AzureAdStrategy } from './azure-ad.guard';
    
    @Module({
      imports: [PassportModule],
      providers: [AzureAdStrategy],
      exports: [AzureAdStrategy],
    })
    export class AuthModule {}
    
    确保该AuthModule被导入到使用AzureADGuard的模块(如ContactsModule)中。
  • 检查Azure AD应用配置:
    • 确认应用注册的API权限已正确添加,且已获得管理员同意(如果是需要管理员授权的权限)。
    • 检查应用的「令牌配置」,确保启用了必要的声明,保证Token包含验证所需的信息。
  • 查看验证日志:开启loggingLevel后,查看应用运行日志,Passport会输出验证失败的具体原因(如签名无效、受众不匹配等),这是定位问题的核心依据。

内容的提问来源于stack exchange,提问作者XRJPK

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 21:13:18