使用Zitadel与openid-client获取M2M Token时遇assertion缺失错误
解决Zitadel M2M令牌获取时的"assertion missing"错误
核心问题
你遇到的invalid_request (assertion missing)错误源于两个关键问题:
- 错误传递客户端断言参数:
openid-client的grant方法不会识别你传入的clientAssertionPayload,导致Zitadel未接收到必要的断言数据。 - 手动生成JWT完全多余:
openid-client会根据你配置的private_key_jwt认证方式和客户端密钥,自动生成并传递符合规范的客户端断言,无需手动构造。
修正步骤
1. 简化私钥导入流程
Zitadel下载的JSON密钥文件中,key字段本身就是PKCS8格式的私钥,无需通过NodeRSA转换,直接用jose的importPKCS8导入即可。
2. 移除手动生成JWT的代码
删除所有构造、签名JWT的代码,这部分工作由openid-client自动完成。
3. 修正grant方法调用
仅在grant方法中传入grant_type(可选添加权限范围scope),无需额外传递客户端断言相关参数。
修改后的完整代码
/* tslint:disable:no-console */ import { importPKCS8 } from 'jose'; import { Issuer } from 'openid-client'; import fs from 'fs'; import path from 'path'; const getToken = async () => { const clientId = '27700000000000000'; // 1. 发现Zitadel的OIDC配置 const oidcIssuer = await Issuer.discover('https://xxxxxx-xxxxxx.zitadel.cloud'); // 2. 导入Zitadel提供的PKCS8私钥 const keyJson = JSON.parse(fs.readFileSync(path.join(__dirname, '27700000000000001.json'), 'utf8')); const privateKey = await importPKCS8(keyJson.key, 'RSA256'); // 3. 创建OIDC客户端,配置认证方式并添加私钥 const client = new oidcIssuer.Client({ client_id: clientId, token_endpoint_auth_method: 'private_key_jwt', // 指定私钥JWT认证方式 }); // 添加私钥并指定keyId(与Zitadel后台配置的密钥ID一致) client.addKey(privateKey, { kid: keyJson.keyId }); // 4. 请求M2M访问令牌 const tokenSet = await client.grant({ grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer', // 可选:添加需要的权限范围,比如你的API权限 // scope: 'your-api-scope-1 your-api-scope-2' }); console.log('Access Token:', tokenSet.access_token); }; getToken();
额外验证点
- 确认Zitadel后台的API客户端配置中,
Token Endpoint Auth Method已设置为Private Key JWT。 - 确认密钥文件中的
keyId与Zitadel后台生成的密钥ID完全一致。 - 确保
clientId与Zitadel中创建的API客户端ID匹配。
内容的提问来源于stack exchange,提问作者physicalattraction
相关产品推荐
相关产品推荐

