在Strapi中验证Azure AD B2C idToken有效性的技术问询
验证Azure AD B2C idToken的Strapi中间件实现方案
方案一:手动用JWT库结合JWKS验证
Azure AD B2C的idToken是标准JWT,可通过其公开的JWKS端点获取公钥,验证签名和核心声明。
步骤:
- 安装依赖包
npm install jsonwebtoken jwks-rsa
- 创建Strapi自定义中间件
在src/middlewares/azure-b2c-auth/index.js中写入以下代码:
const jwt = require('jsonwebtoken'); const jwksClient = require('jwks-rsa'); // 替换成你的Azure B2C配置 const AZURE_B2C_CONFIG = { tenantName: 'your-tenant-name', policyName: 'your-signup-signin-policy', clientId: 'your-app-client-id', }; const client = jwksClient({ jwksUri: `https://${AZURE_B2C_CONFIG.tenantName}.b2clogin.com/${AZURE_B2C_CONFIG.tenantName}.onmicrosoft.com/${AZURE_B2C_CONFIG.policyName}/discovery/v2.0/keys` }); function getKey(header, callback) { client.getSigningKey(header.kid, function(err, key) { const signingKey = key.getPublicKey(); callback(null, signingKey); }); } module.exports = (strapi) => { return { async resolve(ctx, next) { // 从请求头获取token const token = ctx.request.headers['x-activedirectory-token']; if (!token) { return ctx.unauthorized('No token provided'); } try { // 验证token await new Promise((resolve, reject) => { jwt.verify(token, getKey, { audience: AZURE_B2C_CONFIG.clientId, issuer: `https://${AZURE_B2C_CONFIG.tenantName}.b2clogin.com/${AZURE_B2C_CONFIG.tenantName}.onmicrosoft.com/${AZURE_B2C_CONFIG.policyName}/v2.0/`, algorithms: ['RS256'] }, (err, decoded) => { if (err) return reject(err); // 将解码后的用户信息挂载到ctx,后续业务可用 ctx.state.user = decoded; resolve(); }); }); await next(); } catch (err) { return ctx.unauthorized('Invalid token: ' + err.message); } } }; };
- 启用中间件
在config/middlewares.js中添加该中间件:
module.exports = [ // 其他中间件... 'global::azure-b2c-auth', ];
方案二:用koa-jwt适配Koa生态
Strapi基于Koa,koa-jwt可以直接结合JWKS自动处理公钥获取和验证。
步骤:
- 安装依赖包
npm install koa-jwt jwks-rsa
- 创建自定义中间件封装koa-jwt
在src/middlewares/azure-b2c-auth/index.js中写入:
const jwt = require('koa-jwt'); const jwksRsa = require('jwks-rsa'); const AZURE_B2C_CONFIG = { tenantName: 'your-tenant-name', policyName: 'your-signup-signin-policy', clientId: 'your-app-client-id', }; module.exports = (strapi) => { return { resolve(ctx, next) { const middleware = jwt({ secret: jwksRsa.koaJwtSecret({ jwksUri: `https://${AZURE_B2C_CONFIG.tenantName}.b2clogin.com/${AZURE_B2C_CONFIG.tenantName}.onmicrosoft.com/${AZURE_B2C_CONFIG.policyName}/discovery/v2.0/keys`, cache: true, cacheMaxEntries: 5, cacheMaxAge: 600000, }), audience: AZURE_B2C_CONFIG.clientId, issuer: `https://${AZURE_B2C_CONFIG.tenantName}.b2clogin.com/${AZURE_B2C_CONFIG.tenantName}.onmicrosoft.com/${AZURE_B2C_CONFIG.policyName}/v2.0/`, algorithms: ['RS256'], getToken: (ctx) => ctx.request.headers['x-activedirectory-token'], }); return middleware(ctx, next); } }; };
- 同样在
config/middlewares.js中启用该中间件即可。
关键验证注意点
- 确保
issuer完全匹配Azure B2C策略的颁发者,格式不能错 audience必须是你在Azure AD B2C中注册的应用客户端ID- 验证算法固定为
RS256,Azure AD B2C默认用这个算法签名idToken - 缓存JWKS公钥可以减少对Azure端点的请求次数,提升性能
内容的提问来源于stack exchange,提问作者EmJee
相关产品推荐
相关产品推荐

