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

如何让AWS Cognito接受外部OIDC(Azure AD)颁发的客户端凭证模式令牌以访问REST API Gateway?

如何让AWS Cognito接受外部OIDC(Azure AD)颁发的客户端凭证模式令牌以访问REST API Gateway?

先直接回应你的核心疑问——Cognito的用户池联邦机制确实主要针对带用户交互的浏览器/移动应用流,并不适配服务对服务的客户端凭证模式,所以你之前尝试用外部OIDC令牌直接走Cognito客户端凭证流程遇到401是正常的。下面给你两个可行的解决方案,完全适配你的CLI无浏览器场景:

方案一:给REST API Gateway配置自定义Lambda授权器(推荐)

这是最贴合你需求的方案,既满足REST API支持WAF的要求,又能完全自定义验证逻辑,适配服务对服务的令牌验证场景。

具体步骤:

  1. 编写Lambda验证函数
    核心逻辑是解析请求头里的Bearer令牌,验证它是否由Azure AD合法签发,检查issuer、audience、过期时间等关键字段。这里给你一个Node.js的示例代码(你也可以用Python/Java等其他语言实现):
    const jwt = require('jsonwebtoken');
    const jwksClient = require('jwks-rsa');
    
    // 替换成你的Azure AD租户ID和客户端ID
    const AZURE_TENANT_ID = '你的租户ID';
    const AZURE_CLIENT_ID = '你的Azure AD应用注册客户端ID';
    
    const client = jwksClient({
      jwksUri: `https://login.microsoftonline.com/${AZURE_TENANT_ID}/discovery/v2.0/keys`
    });
    
    function getSigningKey(header, callback) {
      client.getSigningKey(header.kid, function(err, key) {
        const signingKey = key.getPublicKey();
        callback(null, signingKey);
      });
    }
    
    exports.handler = async (event) => {
      // 提取Bearer令牌
      const authHeader = event.authorizationToken;
      if (!authHeader || !authHeader.startsWith('Bearer ')) {
        return generateDenyPolicy('invalid-header', event.methodArn);
      }
      const token = authHeader.replace('Bearer ', '');
    
      try {
        // 验证JWT令牌的签名、签发者、受众等信息
        await new Promise((resolve, reject) => {
          jwt.verify(token, getSigningKey, {
            issuer: `https://login.microsoftonline.com/${AZURE_TENANT_ID}/v2.0`,
            audience: AZURE_CLIENT_ID,
            algorithms: ['RS256']
          }, (err, decoded) => {
            if (err) reject(err);
            else resolve(decoded);
          });
        });
    
        // 验证通过,生成允许访问的策略
        return generateAllowPolicy('azure-ad-service-principal', event.methodArn);
      } catch (err) {
        console.error('令牌验证失败:', err);
        return generateDenyPolicy('invalid-token', event.methodArn);
      }
    };
    
    // 辅助函数:生成允许访问的IAM策略
    function generateAllowPolicy(principalId, resource) {
      return {
        principalId: principalId,
        policyDocument: {
          Version: '2012-10-17',
          Statement: [
            {
              Action: 'execute-api:Invoke',
              Effect: 'Allow',
              Resource: resource
            }
          ]
        }
      };
    }
    
    // 辅助函数:生成拒绝访问的IAM策略
    function generateDenyPolicy(principalId, resource) {
      return {
        principalId: principalId,
        policyDocument: {
          Version: '2012-10-17',
          Statement: [
            {
              Action: 'execute-api:Invoke',
              Effect: 'Deny',
              Resource: resource
            }
          ]
        }
      };
    }
    
  2. 配置API Gateway的自定义授权器
    • 进入API Gateway控制台,找到你的REST API,在「授权器」页面创建新授权器,类型选「令牌」,身份源填method.request.header.Authorization,选择你刚才创建的Lambda函数,按需勾选「Lambda代理集成」。
    • 给需要保护的API方法绑定这个授权器。
  3. 测试验证
    用户用Azure AD的客户端凭证流拿到令牌后,直接在请求头里带上Authorization: Bearer <你的Azure AD令牌>调用API,Lambda验证通过后就会允许访问。

额外提醒:可以在授权器设置里开启缓存,减少重复验证的开销;如果需要支持多个Azure AD客户端或租户,可以在Lambda里扩展验证逻辑,允许多个合法的issuer和audience。

方案二:尝试用Cognito身份池交换令牌(不推荐,适配性差)

如果一定要依赖Cognito生态,你可以尝试用Azure AD的客户端凭证令牌去交换Cognito身份池的临时AWS凭证,但这个方案更偏向于获取AWS服务权限,而非直接用Bearer令牌访问API,而且因为是无用户的服务主体,适配性远不如方案一:

  1. 在Cognito身份池里添加Azure AD作为OIDC身份提供者,配置好issuer、客户端ID等信息(需确保Azure AD应用注册允许Cognito的访问)。
  2. 用Azure AD拿到的JWT,调用Cognito的GetId API,传入身份池ID和外部令牌,获取Cognito身份ID。
  3. 再调用GetCredentialsForIdentity获取临时AWS凭证,然后用这些凭证通过IAM授权访问API Gateway(需要给API Gateway配置IAM授权)。

为什么你之前的联邦尝试失败?

你提到用外部OIDC令牌访问API Gateway时收到401,核心原因是:Cognito用户池的OIDC联邦是为用户登录流(授权码、隐式流)设计的,它只认可通过用户池联邦流程生成的令牌,而外部直接用客户端凭证拿到的令牌,Cognito无法验证其合法性,所以会拒绝访问。

备注:内容来源于stack exchange,提问作者Max Allan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.23 07:18:14