我正在尝试使用https://github.com/azure-ad-b2c/samples/tree/master/policies/username-discovery配置忘记的用户名流,用户可以在其中提供电子邮件,它将发现用户名,并在策略中调用REST技术配置文件发送电子邮件,但仍然会出现以下错误:
声明交换步骤'2‘中指定的'REST-RestoreUsername’返回的HTTP错误响应,代码'BadRequest‘和原因’坏请求‘.
不知道是什么导致了这个问题。
API { "toEmails": [ "string" ], "templateName": "string", "emailParam": [ "string" ] }
所需的JSON有效载荷
不确定是否正确定义了声明转换
<ClaimsTransformation Id="GenerateRequestBody" TransformationMethod="GenerateJson">
<InputClaims>
<InputClaim ClaimTypeReferenceId="email" TransformationClaimType="toEmails" />
<InputClaim ClaimTypeReferenceId="forgotuserid" TransformationClaimType="templateName" />
<InputClaim ClaimTypeReferenceId="givenName" TransformationClaimType="emailParam" />
<InputClaim ClaimTypeReferenceId="surname" TransformationClaimType="emailParam" />
<InputClaim ClaimTypeReferenceId="signInNames.userName" TransformationClaimType="emailParam" />
</InputClaims>
<OutputClaims>
<OutputClaim ClaimTypeReferenceId="forgotuserid" TransformationClaimType="outputClaim" />
</OutputClaims>
</ClaimsTransformation>
TP:
<!-- this technical profile collects the user's email address, call
validation technical profile to discover the user name and send the
email with the username to the end user -->
<TechnicalProfile Id="SelfAsserted-UsernameDiscovery">
<DisplayName>Forgot your username?</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</Item>
</Metadata>
<OutputClaims>
<OutputClaim ClaimTypeReferenceId="email" PartnerClaimType="email" />
<OutputClaim ClaimTypeReferenceId="displayName" />
<OutputClaim ClaimTypeReferenceId="surname" />
<OutputClaim ClaimTypeReferenceId="signInNames.userName" />
</OutputClaims>
<ValidationTechnicalProfiles>
<ValidationTechnicalProfile ReferenceId="AAD-UserReadUsingEmailAddress-NoError" />
<ValidationTechnicalProfile ReferenceId="REST-RestoreUsername" ContinueOnError="true">
<Preconditions>
<Precondition Type="ClaimsExist" ExecuteActionsIf="false">
<Value>signInNames.userName</Value>
<Action>SkipThisValidationTechnicalProfile</Action>
</Precondition>
</Preconditions>
</ValidationTechnicalProfile>
</ValidationTechnicalProfiles>
<UseTechnicalProfileForSessionManagement ReferenceId="SM-Noop" />
</TechnicalProfile>
<TechnicalProfile Id="SelfAsserted-UserMessage">
<DisplayName>UserNameDiscoveryMessage</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</Item>
<!-- hide the continue and cancel buttons -->
<Item Key="setting.showContinueButton">false</Item>
<Item Key="setting.showCancelButton">false</Item>
</Metadata>
<InputClaimsTransformations>
<InputClaimsTransformation ReferenceId="GetUserMessage" />
</InputClaimsTransformations>
<InputClaims>
<InputClaim ClaimTypeReferenceId="userMessage" />
</InputClaims>
<OutputClaims>
<!-- Show the paragraph claim with the message to the user -->
<OutputClaim ClaimTypeReferenceId="userMessage" />
</OutputClaims>
<UseTechnicalProfileForSessionManagement ReferenceId="SM-Noop" />
</TechnicalProfile>
REST:
<ClaimsProvider>
<DisplayName>REST APIs</DisplayName>
<TechnicalProfiles>
<!-- Custom Restful service that sends emails -->
<TechnicalProfile Id="REST-RestoreUsername">
<DisplayName>Validate user input data and return loyaltyNumber claim</DisplayName>
<Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.RestfulProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
<Metadata>
<!--Action required: value of the ServiceUrl according to your application location-->
<Item Key="ServiceUrl">http://XXXXXXXXXXX/api/v1/Email/SendEmail</Item>
<Item Key="SendClaimsIn">Body</Item>
<Item Key="AuthenticationType">None</Item>
<Item Key="allowInsecureAuthInProduction">true</Item>
<Item Key="DebugMode">true</Item>
<!--<Item Key="DefaultUserMessageIfRequestFailed">Cannot process your request right now, please try again later.</Item>-->
</Metadata>
<InputClaimsTransformations>
<InputClaimsTransformation ReferenceId="GenerateRequestBody" />
</InputClaimsTransformations>
<InputClaims>
<InputClaim ClaimTypeReferenceId="forgotuserid" />
</InputClaims>
<UseTechnicalProfileForSessionManagement ReferenceId="SM-Noop" />
</TechnicalProfile>
</TechnicalProfiles>
</ClaimsProvider>
编制步骤:
<UserJourneys>
<UserJourney Id="SignUpOrSignInMFAOption" DefaultCpimIssuerTechnicalProfileReferenceId="JwtIssuer">
<OrchestrationSteps>
<OrchestrationStep Order="1" Type="CombinedSignInAndSignUp" ContentDefinitionReferenceId="api.signuporsignin">
<ClaimsProviderSelections>
<ClaimsProviderSelection ValidationClaimsExchangeId="LocalAccountSigninUsernameExchange" />
<ClaimsProviderSelection TargetClaimsExchangeId="ForgotPasswordExchange" />
<ClaimsProviderSelection TargetClaimsExchangeId="SelfAssertedUsernameDiscoveryExchange" />
</ClaimsProviderSelections>
<ClaimsExchanges>
<ClaimsExchange Id="LocalAccountSigninUsernameExchange" TechnicalProfileReferenceId="SelfAsserted-LocalAccountSignin-Username" />
</ClaimsExchanges>
</OrchestrationStep>
<!-- Check if the user has selected to sign in using one of the social providers -->
<OrchestrationStep Order="2" Type="ClaimsExchange">
<Preconditions>
<Precondition Type="ClaimsExist" ExecuteActionsIf="true">
<Value>objectId</Value>
<Action>SkipThisOrchestrationStep</Action>
</Precondition>
</Preconditions>
<ClaimsExchanges>
<ClaimsExchange Id="SignUpWithLogonUsernameExchange" TechnicalProfileReferenceId="LocalAccountSignUpWithLogonName" />
<ClaimsExchange Id="ForgotPasswordExchange" TechnicalProfileReferenceId="ForgotPassword" />
<ClaimsExchange Id="SelfAssertedUsernameDiscoveryExchange" TechnicalProfileReferenceId="SelfAsserted-UsernameDiscovery" />
</ClaimsExchanges>
</OrchestrationStep>
<OrchestrationStep Order="3" Type="InvokeSubJourney">
<Preconditions>
<Precondition Type="ClaimsExist" ExecuteActionsIf="false">
<Value>isForgotPassword</Value>
<Action>SkipThisOrchestrationStep</Action>
</Precondition>
</Preconditions>
<JourneyList>
<Candidate SubJourneyReferenceId="PasswordReset" />
</JourneyList>
</OrchestrationStep>
<!-- This step reads any user attributes that we may not have received when authenticating using ESTS so they can be sent
in the token. -->
<OrchestrationStep Order="4" Type="ClaimsExchange">
<Preconditions>
<Precondition Type="ClaimEquals" ExecuteActionsIf="true">
<Value>authenticationSource</Value>
<Value>socialIdpAuthentication</Value>
<Action>SkipThisOrchestrationStep</Action>
</Precondition>
</Preconditions>
<ClaimsExchanges>
<ClaimsExchange Id="AADUserReadWithObjectId" TechnicalProfileReferenceId="AAD-UserReadUsingObjectId" />
</ClaimsExchanges>
</OrchestrationStep>
<OrchestrationStep Order="5" Type="ClaimsExchange">
<Preconditions>
<Precondition Type="ClaimsExist" ExecuteActionsIf="true">
<Value>extension_mfaByPhoneOrEmail</Value>
<Action>SkipThisOrchestrationStep</Action>
</Precondition>
</Preconditions>
<ClaimsExchanges>
<ClaimsExchange Id="SelfAsserted-Select-MFA-Method" TechnicalProfileReferenceId="SelfAsserted-Select-MFA-Method" />
</ClaimsExchanges>
</OrchestrationStep>
<!-- Throw error if control was bypassed -->
<OrchestrationStep Order="6" Type="SendClaims" CpimIssuerTechnicalProfileReferenceId="Return-MFA-Method-Incorrect-Error">
<Preconditions>
<Precondition Type="ClaimEquals" ExecuteActionsIf="true">
<Value>extension_mfaByPhoneOrEmail</Value>
<Value>email</Value>
<Action>SkipThisOrchestrationStep</Action>
</Precondition>
<Precondition Type="ClaimEquals" ExecuteActionsIf="true">
<Value>extension_mfaByPhoneOrEmail</Value>
<Value>phone</Value>
<Action>SkipThisOrchestrationStep</Action>
</Precondition>
</Preconditions>
</OrchestrationStep>
<!-- Phone verification: If MFA is not required, the next three steps (#5-#7) should be removed.
This step checks whether there's a phone number on record, for the user. If found, then the user is challenged to verify it. -->
<OrchestrationStep Order="7" Type="ClaimsExchange">
<Preconditions>
<Precondition Type="ClaimsExist" ExecuteActionsIf="true">
<Value>isActiveMFASession</Value>
<Action>SkipThisOrchestrationStep</Action>
</Precondition>
<!-- If the preferred MFA method is not 'phone' skip this orchestration step-->
<Precondition Type="ClaimEquals" ExecuteActionsIf="false">
<Value>extension_mfaByPhoneOrEmail</Value>
<Value>phone</Value>
<Action>SkipThisOrchestrationStep</Action>
</Precondition>
</Preconditions>
<ClaimsExchanges>
<ClaimsExchange Id="PhoneFactor-Verify" TechnicalProfileReferenceId="PhoneFactor-InputOrVerify" />
</ClaimsExchanges>
</OrchestrationStep>
<!-- Save MFA phone number: The precondition verifies whether the user provided a new number in the
previous step. If so, then the phone number is stored in the directory for future authentication
requests. -->
<OrchestrationStep Order="8" Type="ClaimsExchange">
<Preconditions>
<Precondition Type="ClaimsExist" ExecuteActionsIf="false">
<Value>newPhoneNumberEntered</Value>
<Action>SkipThisOrchestrationStep</Action>
</Precondition>
</Preconditions>
<ClaimsExchanges>
<ClaimsExchange Id="AADUserWriteWithObjectId" TechnicalProfileReferenceId="AAD-UserWritePhoneNumberUsingObjectId" />
</ClaimsExchanges>
</OrchestrationStep>
<!-- MFA with email-->
<OrchestrationStep Order="9" Type="ClaimsExchange">
<Preconditions>
<Precondition Type="ClaimEquals" ExecuteActionsIf="false">
<Value>extension_mfaByPhoneOrEmail</Value>
<Value>email</Value>
<Action>SkipThisOrchestrationStep</Action>
</Precondition>
</Preconditions>
<ClaimsExchanges>
<ClaimsExchange Id="Email-Verify" TechnicalProfileReferenceId="EmailVerifyOnSignIn" />
</ClaimsExchanges>
</OrchestrationStep>
<!-- check if change password is required. If yes, ask the user to reset the password-->
<OrchestrationStep Order="10" Type="ClaimsExchange">
<Preconditions>
<Precondition Type="ClaimEquals" ExecuteActionsIf="true">
<Value>authenticationSource</Value>
<Value>socialIdpAuthentication</Value>
<Action>SkipThisOrchestrationStep</Action>
</Precondition>
<Precondition Type="ClaimEquals" ExecuteActionsIf="true">
<Value>skipPasswordReset</Value>
<Value>True</Value>
<Action>SkipThisOrchestrationStep</Action>
</Precondition>
</Preconditions>
<ClaimsExchanges>
<ClaimsExchange Id="NewCredentials" TechnicalProfileReferenceId="LocalAccountWritePasswordUsingObjectId" />
</ClaimsExchanges>
</OrchestrationStep>
<OrchestrationStep Order="11" Type="SendClaims" CpimIssuerTechnicalProfileReferenceId="JwtIssuer" />
</OrchestrationSteps>
<ClientDefinition ReferenceId="DefaultWeb" />
</UserJourney>
发布于 2022-08-30 08:53:56
您在示例中编译了REST并将其部署到可以公开访问的地方吗?
如果你和邮递员一起测试它会起作用吗?
该示例使用SendGrid。你把SendGrid设置成正确无误了吗
更新
根据有效载荷,它应该如下所示:
<ClaimsTransformation Id="GenerateRequestBody" TransformationMethod="GenerateJson">
<InputClaims>
<InputClaim ClaimTypeReferenceId="email" TransformationClaimType="toEmails.0.email"/>
<InputClaim ClaimTypeReferenceId="forgotuserid" TransformationClaimType="templateName"/>
<InputClaim ClaimTypeReferenceId="givenName" TransformationClaimType="emailParam.0.givenName"/>
<InputClaim ClaimTypeReferenceId="surname" TransformationClaimType="emailParam.0.surname"/>
<InputClaim ClaimTypeReferenceId="signInNames.userName" TransformationClaimType="emailParam.0.userName"/>
</InputClaims>
<OutputClaims>
<OutputClaim ClaimTypeReferenceId="request" TransformationClaimType="outputClaim"/>
</OutputClaims>
</ClaimsTransformation>
最好能看到预期输出的样本。
更新2
<ClaimsTransformation Id="GenerateRequestBody" TransformationMethod="GenerateJson">
<InputClaims>
<InputClaim ClaimTypeReferenceId="email" TransformationClaimType="toEmails.0.email"/>
<InputClaim ClaimTypeReferenceId="givenName" TransformationClaimType="emailParam.0.givenName"/>
<InputClaim ClaimTypeReferenceId="surname" TransformationClaimType="emailParam.0.surname"/>
<InputClaim ClaimTypeReferenceId="signInNames.userName" TransformationClaimType="emailParam.0.userName"/>
</InputClaims>
<InputParameters>
<InputParameter Id="templateName"" DataType="string" Value="forgotuserid"/>
</InputParameters>
<OutputClaims>
<OutputClaim ClaimTypeReferenceId="request" TransformationClaimType="outputClaim"/>
</OutputClaims>
</ClaimsTransformation>
发布于 2022-09-05 08:06:04
@rbrayb -谢谢你的帮助,非常感谢。已经在CT下面使用了。
<ClaimsTransformation Id="CreateJSONBody" TransformationMethod="GenerateJson">
<InputClaims>
<InputClaim ClaimTypeReferenceId="email" TransformationClaimType="toEmails.0" />
<InputClaim ClaimTypeReferenceId="givenName" TransformationClaimType="emailParam.0" />
<InputClaim ClaimTypeReferenceId="surName" TransformationClaimType="emailParam.1" />
<InputClaim ClaimTypeReferenceId="signInNames.userName" TransformationClaimType="emailParam.2"/>
</InputClaims>
<InputParameters>
<InputParameter Id="templateName" DataType="string" Value="forgotuserid" />
</InputParameters>
<OutputClaims>
<OutputClaim ClaimTypeReferenceId="RequestPayload" TransformationClaimType="outputClaim" />
</OutputClaims>
</ClaimsTransformation>
这解决了这个问题。
再次感谢。
https://stackoverflow.com/questions/73538422
复制相似问题