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

如何配置node-oidc-provider使id_token包含acr claim?

问题

我在Node应用中集成node-oidc-provider库搭建IDP服务器,配置如下:

{
    oidc: {
      clients: [
        {
          client_id: '',
          client_secret: '',
          grant_types: ['implicit', 'authorization_code', 'refresh_token'],
          redirect_uris: [''],
          response_types: ['code', 'id_token'],
          id_token_signed_response_alg: 'RS256',
          token_endpoint_auth_method: 'client_secret_basic',
        },
      ],
      findAccount: (ctx, id) => {
        return Account.findAccount(ctx, id, app);
      },
      conformIdTokenClaims: false,
      acrValues: ['auth_my_idp'],
      claims: {
        openid: ['sub', 'username'],
        email: ['email', 'email_verified'],
        profile: ['family_name', 'given_name']
      },
      clientDefaults: {
        grant_types: ['authorization_code', 'refresh_token'],
        id_token_signed_response_alg: 'RS256',
        response_types: ['code', 'id_token'],
        token_endpoint_auth_method: 'client_secret_basic',
      },
      interactions: {
        url(ctx, interaction) {
          return `/token/${interaction.uid}`;
        },
        proxy: false,
        forceHTTPS: true,
      },
      pkce: {
        required: () => false,
      },
      features: {
        devInteractions: { enabled: false },
        claimsParameter: {
          enabled: true,
        },
      },
      adapter: getRedisAdapter(),
      // setting very short time on sessions
      ttl: {
        AccessToken: function AccessTokenTTL() {
          return 300; 
        },
        AuthorizationCode: 300,
        BackchannelAuthenticationRequest: function BackchannelAuthenticationRequestTTL() {
          return 300; 
        },
        ClientCredentials: function ClientCredentialsTTL() {
          return 300; 
        },
        DeviceCode: 300,
        Grant: 300,
        IdToken: 300,
        Interaction: 300,
        RefreshToken: function RefreshTokenTTL() {
          return 300;
        },
        Session: 300,
      },
    },
  };

findAccount函数实现如下:

static async findAccount(ctx, id, app) {
    let response;
    await app.sql.Person.findOne({
      where: { id: id, deleted_at: null },
    }).then(person => {
      response = {
        accountId: id,
        async claims(use, scope) {
          return {
            sub: person?.email,
            email: person?.email,
          };
        },
      };
    });
    if (!response) {
      return undefined;
    }
    return response;
  }

我先发起授权请求获取授权码,请求地址为:

http://localhost:3000/oidc/auth?client_id=oidc_client_id&redirect_uri=http://localhost:8080&state=<state value>&response_type=code&scope=openid%20offline_access%20profile%20email&acr_values=auth_my_idp&nonce=<nonce>&prompt=consent

授权码成功返回至指定重定向地址http://localhost:8080后,我通过Postman调用http://localhost:3000/oidc/token接口获取到id_token,响应如下:

{
    "access_token": "an access token",
    "expires_in": 300,
    "id_token": "an id token",
    "scope": "openid offline_access profile email",
    "token_type": "Bearer"
}

但解码id_token后发现其中不存在acr claim。我尝试在findAccount的claims方法中显式返回acr也无效:

async claims(use, scope) {
          return {
            sub: person?.email,
            email: person?.email,
            acr: 'auth_my_idp'
          };
        },

请问需要添加什么配置,才能让oidc-provider将acr作为claim包含在id_token中?


解决方案

要让acr claim出现在id_token中,你需要明确:acr是认证上下文引用,属于描述认证方式的元数据,而非用户自身属性,所以不能通过findAccount的claims方法返回,必须在认证流程中主动注入到id_token的声明里。

具体配置步骤:

  1. 添加认证后钩子注入acr
    在oidc配置中新增hooks配置,利用postAuthentication钩子在认证完成后将acr值写入id_token的声明:
{
  oidc: {
    // 保留原有所有配置...
    hooks: {
      postAuthentication: async (ctx, session) => {
        // 从请求参数中获取传入的acr_values,或直接指定固定值
        const requestedAcr = ctx.oidc.params.acr_values || 'auth_my_idp';
        session.idTokenClaims.acr = requestedAcr;
      },
    },
    // 保留原有所有配置...
  }
}
  1. 确保认证流程匹配acr值
    oidc-provider默认只会在实际使用了与acr_values对应的认证方式时,才会自动添加acr声明。如果你有自定义的认证逻辑(比如对应auth_my_idp的认证步骤),要确保该逻辑被正确触发,这样钩子中的值才符合实际认证上下文。

  2. 检查conformIdTokenClaims配置
    你当前设置了conformIdTokenClaims: false,这个配置关闭了严格的OIDC规范兼容,不会自动过滤标准声明,所以无需额外调整claims列表,但如果有自定义的声明过滤逻辑,要确保没有排除acr。

另外,如果你是通过交互页面(/token/${interaction.uid})处理认证逻辑,也可以在完成认证时直接将acr设置到session的idTokenClaims中,效果和钩子一致。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 06:29:53