如何在msal-browser的loginRedirect中自定义code_challenge参数
解决方案
问题根因
@azure/msal-browser公开的loginRedirect入参类型RedirectRequest未开放codeChallenge配置字段,直接在请求参数中添加该字段不会被MSAL识别。MSAL默认会在内部自动生成PKCE校验对,并存到浏览器缓存中用于后续兑换令牌,自行外部生成的PKCE对如果没有同步到MSAL的缓存逻辑中,也会导致后续令牌兑换失败。
实现方案
通过MSAL官方开放的自定义加密实现接口,覆盖默认的PKCE生成逻辑,即可完全控制code_challenge和对应的code_verifier的生成,是无侵入的兼容方案,步骤如下:
步骤1:实现自定义加密类
仅需覆盖generatePkceCodes方法返回你自定义的PKCE对,其余加密方法可直接复用MSAL默认实现:
import * as msal from "@azure/msal-browser"; import pkceChallenge from "pkce-challenge" class CustomPKCECrypto { constructor() { // 初始化MSAL默认加密实现,用于兜底其他加密方法 this.defaultCrypto = new msal.CryptoProvider(); } // 覆盖PKCE生成逻辑,返回自定义的校验对 async generatePkceCodes() { // 这里替换为你自己的生成逻辑,示例直接使用pkce-challenge包生成 const pkce = pkceChallenge(); return { verifier: pkce.code_verifier, challenge: pkce.code_challenge }; } // 剩余加密方法直接转发给默认实现即可,无需修改 async sha256Digest(content) { return this.defaultCrypto.sha256Digest(content); } base64Encode(content, urlSafe) { return this.defaultCrypto.base64Encode(content, urlSafe); } generateRandomValues(length) { return this.defaultCrypto.generateRandomValues(length); } }
步骤2:初始化MSAL时注入自定义加密实现
在MSAL配置的system字段中传入你实现的自定义加密实例:
const msalConfig = { auth: { clientId: "GUID", // 替换为你的应用ID authority: "https://{tenant}.b2clogin.com/{tenant}.onmicrosoft.com/B2C_signin_flow", // 替换为你的B2C用户流地址 knownAuthorities: ["https://{tenant}.b2clogin.com/{tenant}.onmicrosoft.com/B2C_signin_flow"], // 替换为你的租户授权地址 redirectUri: "http://localhost:6420", // 替换为你登记的回调地址 }, system: { // 注入自定义加密实现 cryptoImpl: new CustomPKCECrypto() } }; const b2cScopes = [ "https://{tenant}.onmicrosoft.com/010eb29e-d42b-4ca3-9c16-1961a528ce67/tasks.read", "https://{tenant}.onmicrosoft.com/010eb29e-d42b-4ca3-9c16-1961a528de77/tasks.write" ]; const myMSALObj = new msal.PublicClientApplication(msalConfig);
步骤3:正常发起登录请求
无需再在登录请求参数中添加codeChallenge字段,MSAL会自动调用你自定义的PKCE生成逻辑获取参数:
const loginRequest = { scopes: ["openid", ...b2cScopes] } myMSALObj.loginRedirect(loginRequest);
注意事项
- 该方案兼容
@azure/msal-browserv2.x及以上所有正式版本,属于官方支持的扩展能力,不会因版本升级出现兼容性问题 - 自定义生成的PKCE对必须符合RFC7636规范:
code_verifier长度为43~128字符,仅允许包含大小写字母、数字、-、.、_、~字符;code_challenge为code_verifier的SHA256哈希值经过URL安全Base64编码生成,你使用的pkce-challenge包默认生成的结果符合规范,可直接使用 - 不建议使用固定值的PKCE对,会降低认证流程的安全性,存在CSRF攻击风险
内容的提问来源于stack exchange,提问作者Mateen-Hussain
相关产品推荐
相关产品推荐

