Azure AD B2C自定义策略TOTP设置:二维码不显示且qrCodeContent格式错误
Azure AD B2C自定义策略TOTP二维码无法渲染问题解决
在Azure AD B2C自定义策略中实现TOTP多因素认证时,EnableOTPAuthentication页面的二维码无法渲染,且qrCodeContent声明值格式错误。
当前qrCodeContent值为:
otpauth:totp
期望格式(符合RFC 6238及Google Authenticator规范):
otpauth://totp/test:steveTest@gmail.com?secret=K6L7OZ5P4LJZVQ34&issuer=test
策略详情
- 租户:
test.onmicrosoft.com - 策略ID:
B2C_1A_TrustFrameworkExtensions - 用户旅程:
SignUpWithInviteToken - 技术配置文件:
EnableOTPAuthentication - 显示控件:
totpQrCodeControl - 问题位置:ClaimsTransformation
CreateQrCodeUri
问题原因
此前在ClaimsTransformation中添加了以下代码行:
<InputParameter Id="host" DataType="string" Value="totp" />
但BuildUri转换不支持host参数,添加该参数会破坏URI生成逻辑,导致仅保留scheme部分(otpauth:)。
当前相关代码
CreateQrCodeUri转换代码
<ClaimsTransformation Id="CreateQrCodeUri" TransformationMethod="BuildUri"> <InputClaims> <InputClaim ClaimTypeReferenceId="totpLabel" TransformationClaimType="label" /> <InputClaim ClaimTypeReferenceId="secretKey" TransformationClaimType="secret" /> <InputClaim ClaimTypeReferenceId="totpIssuer" TransformationClaimType="issuer" /> </InputClaims> <InputParameters> <InputParameter Id="scheme" DataType="string" Value="otpauth" /> <InputParameter Id="path" DataType="string" Value="totp/{label}" /> <InputParameter Id="querystringParameter1" DataType="string" Value="secret={secret}" /> <InputParameter Id="querystringParameter2" DataType="string" Value="issuer={issuer}" /> </InputParameters> <OutputClaims> <OutputClaim ClaimTypeReferenceId="qrCodeContent" TransformationClaimType="outputClaim" /> </OutputClaims> </ClaimsTransformation>
totpQrCodeControl显示控件代码
<DisplayControl Id="totpQrCodeControl" UserInterfaceControlType="QrCodeControl"> <InputClaims> <InputClaim ClaimTypeReferenceId="qrCodeContent" /> </InputClaims> <DisplayClaims> <DisplayClaim ClaimTypeReferenceId="qrCodeContent" ControlClaimType="QrCodeContent" /> </DisplayClaims> </DisplayControl>
EnableOTPAuthentication技术配置文件代码
<TechnicalProfile Id="EnableOTPAuthentication"> <DisplayName>Enable Authenticator app</DisplayName> <Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.SelfAssertedAttributeProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" /> <Metadata> <Item Key="ContentDefinitionReferenceId">api.selfasserted.totp</Item> <Item Key="language.button_continue">Continue</Item> </Metadata> <CryptographicKeys> <Key Id="issuer_secret" StorageReferenceId="B2C_1A_TokenSigningKeyContainer" /> </CryptographicKeys> <InputClaimsTransformations> <!-- Set secretKey first --> <InputClaimsTransformation ReferenceId="CopyInviteTokenToSecretKey" /> <!-- Set totpIssuer (static or from claim) --> <InputClaimsTransformation ReferenceId="SetTotpIssuer" /> <!-- Format totpLabel --> <InputClaimsTransformation ReferenceId="FormatTotpLabel" /> <!-- Build the QR code URI --> <InputClaimsTransformation ReferenceId="CreateQrCodeUri" /> </InputClaimsTransformations> <InputClaims> <InputClaim ClaimTypeReferenceId="QrCodeScanInstruction" DefaultValue="Scan this QR code with your Authenticator app" /> <InputClaim ClaimTypeReferenceId="qrCodeContent" /> <InputClaim ClaimTypeReferenceId="secretKey" /> <InputClaim ClaimTypeReferenceId="totpIssuer" /> </InputClaims> <DisplayClaims> <DisplayClaim DisplayControlReferenceId="authenticatorAppIconControl" /> <DisplayClaim ClaimTypeReferenceId="QrCodeScanInstruction" /> <DisplayClaim DisplayControlReferenceId="totpQrCodeControl" /> <DisplayClaim DisplayControlReferenceId="authenticatorInfoControl" /> </DisplayClaims> <OutputClaims> <OutputClaim ClaimTypeReferenceId="objectId" /> <OutputClaim ClaimTypeReferenceId="secretKey" /> <OutputClaim ClaimTypeReferenceId="qrCodeContent" /> </OutputClaims> <UseTechnicalProfileForSessionManagement ReferenceId="SM-MFA-TOTP" /> </TechnicalProfile>
TOTP-Verify技术配置文件代码
<TechnicalProfile Id="TOTP-Verify"> <DisplayName>Verify Authenticator code</DisplayName> <Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.TotpProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" /> <Metadata> <Item Key="ManualCodeEntryAllowed">true</Item> <Item Key="EnforceVerification">true</Item> </Metadata> <InputClaims> <InputClaim ClaimTypeReferenceId="userId" /> </InputClaims> <OutputClaims> <OutputClaim ClaimTypeReferenceId="totpSecret" /> <OutputClaim ClaimTypeReferenceId="authenticationSource" DefaultValue="totp" /> </OutputClaims> </TechnicalProfile>
解决方法
由于BuildUri转换不支持host参数,需调整CreateQrCodeUri的配置,将host部分整合到path参数中,以此生成符合规范的otpauth URI。
修改后的CreateQrCodeUri代码:
<ClaimsTransformation Id="CreateQrCodeUri" TransformationMethod="BuildUri"> <InputClaims> <InputClaim ClaimTypeReferenceId="totpLabel" TransformationClaimType="label" /> <InputClaim ClaimTypeReferenceId="secretKey" TransformationClaimType="secret" /> <InputClaim ClaimTypeReferenceId="totpIssuer" TransformationClaimType="issuer" /> </InputClaims> <InputParameters> <InputParameter Id="scheme" DataType="string" Value="otpauth" /> <InputParameter Id="path" DataType="string" Value="//totp/{label}" /> <InputParameter Id="querystringParameter1" DataType="string" Value="secret={secret}" /> <InputParameter Id="querystringParameter2" DataType="string" Value="issuer={issuer}" /> </InputParameters> <OutputClaims> <OutputClaim ClaimTypeReferenceId="qrCodeContent" TransformationClaimType="outputClaim" /> </OutputClaims> </ClaimsTransformation>
同时需确保以下声明值正确:
totpLabel需为{issuer}:{username}格式(如test:steveTest@gmail.com)secretKey必须是有效的Base32编码密钥totpIssuer需与URI中的issuer参数值一致
修改后重新发布策略,qrCodeContent将生成符合期望的格式,二维码即可正常渲染。
内容的提问来源于stack exchange,提问作者Ret 2
相关产品推荐
相关产品推荐

