ConnectionTimeOut in AD B2C Rest API call to get Access Token - azure-ad-b2c

I want to generate access token as the output claim in the below technical profile. I am connecting to a mulesoft api endpoint(https://example.com/ct-oauth2provider-app-xyz/token) which accepts client_id and client_secret in header(client credential flow). But I am getting "ConnectionTimeOut: An exception has occurred." immediately. Any help is greatly appreciated!
I referred : https://learn.microsoft.com/en-us/azure/active-directory-b2c/secure-rest-api?tabs=windows&pivots=b2c-custom-policy#using-oauth2-bearer
<TechnicalProfiles>
<TechnicalProfile Id="API-AcquireAccessToken">
<DisplayName></DisplayName>
<Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.RestfulProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
<Metadata>
<Item Key="ServiceUrl">https://example.com/ct-oauth2provider-app-xyz/token</Item>
<Item Key="AuthenticationType">Basic</Item>
<Item Key="SendClaimsIn">Form</Item>
</Metadata>
<CryptographicKeys>
<Key Id="BasicAuthenticationUsername" StorageReferenceId="B2C_1A_SecureRESTClientId" />
<Key Id="BasicAuthenticationPassword" StorageReferenceId="B2C_1A_SecureRESTClientSecret" />
</CryptographicKeys>
<InputClaims>
<InputClaim ClaimTypeReferenceId="client_id" DefaultValue="lgk" />
<InputClaim ClaimTypeReferenceId="client_secret" DefaultValue="kgf" />
<InputClaim ClaimTypeReferenceId="grant_type" DefaultValue="client_credentials" />
<InputClaim ClaimTypeReferenceId="scope" DefaultValue="https://graph.microsoft.com/.default" />
</InputClaims>
<OutputClaims>
<OutputClaim ClaimTypeReferenceId="bearerToken" PartnerClaimType="access_token" />
</OutputClaims>
<UseTechnicalProfileForSessionManagement ReferenceId="SM-Noop" />
</TechnicalProfile>

For my case, it is because the certificate that bind to your example public url has expired.
The issue solved after I bind a new and updated certificate to my example site.

Related

Why doesn't FormatLocalizedString work in Azure AD B2C custom policies?

I need to display a custom message after the code is sent in the password reset flow, I have tried following this https://learn.microsoft.com/en-us/azure/active-directory-b2c/string-transformations#formatlocalizedstring but it does not work. I am doing the following, very similar to the reference.
I add the same claimTransformation
<ClaimsTransformation Id="SetResponseMessageForOTPSent" TransformationMethod="FormatLocalizedString">
<InputClaims>
<InputClaim ClaimTypeReferenceId="email" />
</InputClaims>
<InputParameters>
<InputParameter Id="stringFormatId" DataType="string" Value="ResponseMessage_EmailExists" />
</InputParameters>
<OutputClaims>
<OutputClaim ClaimTypeReferenceId="responseMsg" TransformationClaimType="outputClaim" />
</OutputClaims>
</ClaimsTransformation>
And the localized string
<LocalizedString ElementType="FormatLocalizedStringTransformationClaimType" StringId="ResponseMessage_EmailExists">Code sent to "{0}"</LocalizedString>
Finally I refer to the claimTransformation from a technicalProfile
<TechnicalProfile Id="SendOtp">
<DisplayName>Send Otp</DisplayName>
<Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.RestfulProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
<Metadata>
<Item Key="ServiceUrl">Url</Item>
<Item Key="AuthenticationType">ApiKeyHeader</Item>
<Item Key="SendClaimsIn">Body</Item>
<Item Key="ContentDefinitionReferenceId">api.localaccountpasswordreset</Item>
</Metadata>
<InputClaims>
<InputClaim ClaimTypeReferenceId="email" />
</InputClaims>
<OutputClaimsTransformations>
<OutputClaimsTransformation ReferenceId="SetResponseMessageForOTPSent" />
</OutputClaimsTransformations>
</TechnicalProfile>
But it doesn't work, it always shows the message "Unable to validate the information provided". What am I doing wrong?

Calling secure REST API from Azure B2C custom policy to embed claims

I am trying to consume a Azure B2C secured API as part of the user journey by creating custom policies. I have created a claims provider to procure a bearer token as below
<ClaimsProvider>
<DisplayName>REST APIs</DisplayName>
<TechnicalProfiles>
<TechnicalProfile Id="SecureREST-AccessToken">
<DisplayName></DisplayName>
<Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.RestfulProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
<Metadata>
<Item Key="ServiceUrl">https://***.b2clogin.com/***.onmicrosoft.com/B2C_1A_SignUpOrSignIn/oauth2/v2.0/authorize</Item>
<Item Key="AuthenticationType">Basic</Item>
<Item Key="SendClaimsIn">Form</Item>
</Metadata>
<CryptographicKeys>
<Key Id="BasicAuthenticationUsername" StorageReferenceId="B2C_1A_SecureRESTClientId" />
<Key Id="BasicAuthenticationPassword" StorageReferenceId="B2C_1A_SecureRESTClientSecret" />
</CryptographicKeys>
<InputClaims>
<InputClaim ClaimTypeReferenceId="grant_type" DefaultValue="client_credentials" />
<InputClaim ClaimTypeReferenceId="scope" DefaultValue="https://***.onmicrosoft.com/profileapi/profileapi-scope" />
</InputClaims>
<OutputClaims>
<OutputClaim ClaimTypeReferenceId="bearerToken" PartnerClaimType="access_token" />
</OutputClaims>
<UseTechnicalProfileForSessionManagement ReferenceId="SM-Noop" />
</TechnicalProfile>
</TechnicalProfiles>
</ClaimsProvider>
And another claims provider to call my secure REST API as below
<ClaimsProvider>
<DisplayName>REST APIs</DisplayName>
<TechnicalProfiles>
<TechnicalProfile Id="AzureFunctions-GetRole">
<DisplayName>Get Roles </DisplayName>
<Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.RestfulProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
<Metadata>
<Item Key="ServiceUrl">https://***.azurewebsites.net/api/UserProfiles/CheckAdminUser</Item>
<Item Key="AuthenticationType">Bearer</Item>
<Item Key="SendClaimsIn">Body</Item>
<Item Key="AllowInsecureAuthInProduction">false</Item>
</Metadata>
<InputClaims>
<InputClaim ClaimTypeReferenceId="email" PartnerClaimType="email" />
<InputClaim ClaimTypeReferenceId="signInNames.emailAddress" PartnerClaimType="email" />
<InputClaim ClaimTypeReferenceId="bearerToken"/>
</InputClaims>
<OutputClaims>
<OutputClaim ClaimTypeReferenceId="IsAdminUser" PartnerClaimType="IsAdminUser" />
</OutputClaims>
<UseTechnicalProfileForSessionManagement ReferenceId="SM-Noop" />
</TechnicalProfile>
</TechnicalProfiles>
</ClaimsProvider>
How do I tie these two up? Should these be two steps in the user journey?
AAD B2C endpoint doesn’t support client credentials flow. Your initial call to get a token should model AAD client credentials flow:
https://learn.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-client-creds-grant-flow
You would call these technical profiles from the user journey if they return no possibility of an error to the user. Or otherwise as validation technical profiles referenced from a self asserted technical profile.

Calling Rest Api from Custom Policy

I'm having problems calling a rest api from a custom policy. I need the data sent into the rest api like the following
{
"correlationId": "123456",
"message": {
"email": "test#somedomain.com"
}
}
I have the following Claims Transformation
<ClaimsTransformation Id="GenerateGetAadRequestBody" TransformationMethod="GenerateJson">
<InputClaims>
<InputClaim ClaimTypeReferenceId="email" TransformationClaimType="message.emailAddress" />
<InputClaim ClaimTypeReferenceId="correlationId" TransformationClaimType="correlationId" />
</InputClaims>
<OutputClaims>
<OutputClaim ClaimTypeReferenceId="getAadRequestBody" TransformationClaimType="outputClaim"/>
</OutputClaims>
</ClaimsTransformation>
And I'm making the Rest Api call using the following Claims Provider
<ClaimsProvider>
<DisplayName>Custom REST API</DisplayName>
<TechnicalProfiles>
<TechnicalProfile Id="RestApiGetAad">
<DisplayName>Call the Rest API</DisplayName>
<Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.RestfulProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
<Metadata>
<Item Key="ServiceUrl">{Settings:RestApiGetAadUrl}</Item>
<Item Key="AuthenticationType">Basic</Item>
<Item Key="SendClaimsIn">Body</Item>
<Item Key="ClaimUsedForRequestPayload">getAadRequestBody</Item>
<Item Key="ResolveJsonPathsInJsonTokens">true</Item>
<Item Key="DebugMode">{Settings:RestDebugMode}</Item>
<Item Key="DefaultUserMessageIfRequestFailed">Cannot process your request right now, please try again later.</Item>
</Metadata>
<CryptographicKeys>
<Key Id="BasicAuthenticationUsername" StorageReferenceId="{Settings:RestApiUserName}" />
<Key Id="BasicAuthenticationPassword" StorageReferenceId="{Settings:RestApiPassword}" />
</CryptographicKeys>
<InputClaimsTransformations>
<InputClaimsTransformation ReferenceId="GenerateGetAadRequestBody" />
</InputClaimsTransformations>
<InputClaims>
<InputClaim ClaimTypeReferenceId="getAadRequestBody" />
</InputClaims>
<OutputClaims>
<OutputClaim ClaimTypeReferenceId="useAAD" PartnerClaimType="content.UseAad" Required="true" />
</OutputClaims>
<UseTechnicalProfileForSessionManagement ReferenceId="SM-Noop" />
</TechnicalProfile>
</TechnicalProfiles>
</ClaimsProvider>
It looks like the call is being made, however, there is nothing being sent in the body. Any idea what I'm doing wrong?
Unfortunatly, this was issuing the wrong error code. Should have been PEBCAK, as I did not have the claims that I was trying to use in the ClaimsTransformation. Think that posting here gave me a bit of Rubber Duck Debugging, and I walked the flow again spotting the issue

Azure B2C MFA phone factor verification retry handling in custom policy

When using the phone factor technical profile for MFA, the default behavior after 3 incorrect code entries is to redirect the user back to the specified URI with an error saying maximum retries for MFA exceeded. However, the default behavior for email MFA is to simply show an error message and give the user an option to send a new code or cancel.
Is there a way to specify the allowed number of retries for phone MFA or to specify that the phone MFA should display an error in the template without redirecting with an error code?
My phonefactor technical profile:
<TechnicalProfile Id="PhoneFactor-InputOrVerify">
<DisplayName>PhoneFactor</DisplayName>
<Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.PhoneFactorProtocolProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
<Metadata>
<Item Key="ContentDefinitionReferenceId">api.phonefactor</Item>
<Item Key="ManualPhoneNumberEntryAllowed">true</Item>
</Metadata>
<CryptographicKeys>
<Key Id="issuer_secret" StorageReferenceId="B2C_1A_TokenSigningKeyContainer" />
</CryptographicKeys>
<InputClaimsTransformations>
<InputClaimsTransformation ReferenceId="CreateUserIdForMFA" />
</InputClaimsTransformations>
<InputClaims>
<InputClaim ClaimTypeReferenceId="userIdForMFA" PartnerClaimType="UserId" />
<InputClaim ClaimTypeReferenceId="strongAuthenticationPhoneNumber" />
</InputClaims>
<OutputClaims>
<OutputClaim ClaimTypeReferenceId="Verified.strongAuthenticationPhoneNumber" PartnerClaimType="Verified.OfficePhone" />
<OutputClaim ClaimTypeReferenceId="newPhoneNumberEntered" PartnerClaimType="newPhoneNumberEntered" />
</OutputClaims>
<UseTechnicalProfileForSessionManagement ReferenceId="SM-MFA" />
</TechnicalProfile>
Example error from phone MFA: https://jwt.ms/#error=server_error&error_description=AADB2C90151%3a+User+has+exceeded+the+maximum+number+for+retries+for+multi-factor+authentication.%0d%0aCorrelation+ID%3a+0815e707-54b1-4a67-913e-7682742d1c65%0d%0aTimestamp%3a+2019-11-13+14%3a13%3a39Z%0d%0a

Custom Email verification in a single orchestration step in AD B2C Custom policies

I have a multi-step custom policy that first collects email from user and sends a verification code to the user when user clicks continue. The journey works fine. But the thing is validation of code is happening in next step. I need to bring that code validation in to the first orchestration step. I'm following the below doc to implement this journey:
"https://github.com/yoelhor/aadb2c-verification-code"
My technical profile is like the following:
<TechnicalProfile Id="LocalAccountSignUpWithLogonEmail-FirstStep">
<DisplayName>Email signup</DisplayName>
<Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.SelfAssertedAttributeProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
<Metadata>
<Item Key="IpAddressClaimReferenceId">IpAddress</Item>
<Item Key="ContentDefinitionReferenceId">api.localaccountsignup</Item>
<Item Key="language.button_continue">Send verification email</Item>
<Item Key="EnforceEmailVerification">False</Item>
</Metadata>
<CryptographicKeys>
<Key Id="issuer_secret" StorageReferenceId="B2C_1A_TokenSigningKeyContainer" />
</CryptographicKeys>
<InputClaims>
<InputClaim ClaimTypeReferenceId="email" />
</InputClaims>
<OutputClaims>
<OutputClaim ClaimTypeReferenceId="email" PartnerClaimType="Verified.Email" Required="true" />
<OutputClaim ClaimTypeReferenceId="verificationCode" />
</OutputClaims>
<OutputClaimsTransformations>
<OutputClaimsTransformation ReferenceId="CopyEmailAsReadOnly" />
</OutputClaimsTransformations>
<ValidationTechnicalProfiles>
<ValidationTechnicalProfile ReferenceId="REST-API-SendVerificationEmail" />
</ValidationTechnicalProfiles>
<UseTechnicalProfileForSessionManagement ReferenceId="SM-AAD" />
</TechnicalProfile>
and the validation tech profile as follows:
<TechnicalProfile Id="REST-API-SendVerificationEmail">
<DisplayName>Sign-Up send link</DisplayName>
<Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.RestfulProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
<Metadata>
<Item Key="ServiceUrl">https://myweb.azurewebsites.net/api/Identity/SendVerificationCode</Item>
<Item Key="AuthenticationType">None</Item>
<Item Key="SendClaimsIn">Body</Item>
<Item Key="AllowInsecureAuthInProduction">true</Item>
</Metadata>
<InputClaims>
<InputClaim ClaimTypeReferenceId="email" />
</InputClaims>
<OutputClaims>
<OutputClaim ClaimTypeReferenceId="verificationCode" />
</OutputClaims>
<UseTechnicalProfileForSessionManagement ReferenceId="SM-Noop" />
</TechnicalProfile>
It cant be achieved currently, to call the REST API, the form must be submitted and that will cause the orchestration step to complete and move to the next one.
In a few weeks we will release how to achieve this, and without the use of an external REST API to generate and verify the OTP Codes. Stay tuned.

Resources