DateTime as OutputClaim from a RestfulProvider technical profile - azure-ad-b2c

I have a technical profile that is attempting to use a datetime as an output claim.
I have defined a claim called Dob
<ClaimType Id="Dob">
<DisplayName>Dob</DisplayName>
<DataType>dateTime</DataType>
</ClaimType>
Here is the tecnical profile that uses it:
<TechnicalProfile Id="UserApi-GetUserDob">
<DisplayName>Get User Dob From 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">URL-HERE</Item>
<Item Key="AuthenticationType">None</Item>
<Item Key="SendClaimsIn">Body</Item>
</Metadata>
<InputClaims>
<InputClaim ClaimTypeReferenceId="Username" />
</InputClaims>
<OutputClaims>
<OutputClaim ClaimTypeReferenceId="Dob"/>
</OutputClaims>
</TechnicalProfile>
I have done a sample request and here is the format of the Dob field in the API
{
"Dob": "1989-01-01T00:00:00"
}
Using the B2C User Journey Player i have found that the error that is being raised is the following:
Exception:
A self-asserted send response has failed with reason 'Internal Server Error'.
So my question is do i have the datetime in the correct format for B2C to consume it?

According to TrustFrameworkPolicy_0.3.0.0.xsd, there are the following data types:
boolean
date
int
long
string
stringCollection
Try using date.
BTW, you can wire up VS Code to give you this data "inline":

Related

Is there a way to display data returned from an API REST response in Azure AD B2C?

I'm working on a password reset flow and I need to display a custom message returned by an API response, but I can't find a way to display this message. I've tried the following.
<ClaimType Id="userMessage">
<DisplayName>userMessage</DisplayName>
<DataType>string</DataType>
<UserInputType>Paragraph</UserInputType>
</ClaimType>
<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">SomeUrl</Item>
<Item Key="AuthenticationType">ApiKeyHeader</Item>
<Item Key="SendClaimsIn">Body</Item>
</Metadata>
<InputClaims>
<InputClaim ClaimTypeReferenceId="email" />
</InputClaims>
<OutputClaims>
<OutputClaim ClaimTypeReferenceId="userMessage" />
</OutputClaims>
</TechnicalProfile>
But it doesn't show anything.
Have your API return a HTTP 409 error response code. The flow will not continue after this point, until your API responds with HTTP 200 upon the user submitting the page again.
https://learn.microsoft.com/en-us/azure/active-directory-b2c/restful-technical-profile#error-handling
You cannot display a message from the API, unless the API responds with HTTP 409 error status code.
If you want to display a message on success, then localise the message for the display control for send code:
https://learn.microsoft.com/en-us/azure/active-directory-b2c/localization-string-ids#verification-display-control-user-interface-elements

B2C Sign-up screen shows {OIDC:LoginHint} instead of the login

I am passing an email of a prospective member in the login_hint from my website to B2C. In my custom policy I am setting the email claim of the "SignUp" TechnicalProfile to {OIDC:LoginHint}
<TechnicalProfile Id="CustomLocalAccountSignUpWithLogonEmail">
<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>
</Metadata>
<CryptographicKeys>
<Key Id="issuer_secret" StorageReferenceId="B2C_1A_TokenSigningKeyContainer" />
</CryptographicKeys>
<InputClaims>
<InputClaim ClaimTypeReferenceId="email" DefaultValue="{OIDC:LoginHint}" />
</InputClaims>
<OutputClaims>
But instead of seeing the user's email, the string {OIDC:LoginHint} is displayed in the form:
There is a similar question from 2018 with a suggested workaround of using JavaScript to populate the email field on the Sign Up form. But, I don't use custom templates, so the JavaScript workaround won't work for me.
All I need is to populate the email claim with the value passed in {OIDC:LoginHint}. Is there any way to solve this in the policy XML?
Thank you
In a selfAsserted technical profile, you must:
The IncludeClaimResolvingInClaimsHandling metadata must be set to true.
The input or output claims attribute AlwaysUseDefaultValue must be set to true.
https://learn.microsoft.com/en-us/azure/active-directory-b2c/claim-resolver-overview#using-claim-resolvers
An example of using both settings is here
https://learn.microsoft.com/en-us/azure/active-directory-b2c/claim-resolver-overview#restful-technical-profile

Sending a Claim in a validation Technical Profile

I am dong a validation check to our database during our password forget policy.
During this process, it calls and API and needs a bearer token. I already have a technical profile to do this we use in another step.
So in this process, It keeps failing to look for the bearer token. It is saying the only token available in the email.
I need to do a step in between to get the bearer token, but I'm not sure how to do that since I'm doing a validation...
Here is what I have. After I type in the email to validate it.
<ClaimsProvider>
<DisplayName>REST API to Check Member</DisplayName>
<TechnicalProfiles>
<TechnicalProfile Id="LocalAccountDiscoveryUsingEmailAddress">
<ValidationTechnicalProfiles>
<ValidationTechnicalProfile ReferenceId="REST-CheckMemberAccountHolder" ContinueOnError="false"/>
</ValidationTechnicalProfiles>
</TechnicalProfile>
<TechnicalProfile Id="REST-CheckMemberAccountHolder">
<DisplayName>Rest API call to Check Member status</DisplayName>
<Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.RestfulProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
<Metadata>
<Item Key="ServiceUrl">{API}</Item>
<Item Key="SendClaimsIn">Body</Item>
<Item Key="AuthenticationType">Bearer</Item>
<Item Key="UseClaimAsBearerToken">bearerToken</Item>
<Item Key="AllowInsecureAuthInProduction">false</Item>
</Metadata>
<InputClaims>
<InputClaim ClaimTypeReferenceId="email" PartnerClaimType="emailaddress"/>
<InputClaim ClaimTypeReferenceId="bearerToken" />
</InputClaims>
</TechnicalProfile>
</TechnicalProfiles>
</ClaimsProvider>
I need it to call
<TechnicalProfile Id="REST-AcquireAccessToken">
To get the bearertoken for the REST call in the validation.
I cant seem to figure out how to do it.
As per this, I assume you had something like:
<OutputClaims>
<OutputClaim ClaimTypeReferenceId="bearerToken" PartnerClaimType="access_token" />
</OutputClaims>
when you acquired the token?
Is this all part of the same user journey?
What do you mean by "saying the only token available in the email"?

Getting access token for an api protected by B2C, using custom policies

I have an api that is protected using ADB2C authentication. I need to call this api via custom policies. I followed the documentation enter link description here and have added the two technical profiles as validation technical profile of a self asserted profile.
I am getting an access token returned by the below technical profile :
<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://login.microsoftonline.com/{tenant id here}/oauth2/v2.0/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="grant_type" DefaultValue="client_credentials" />
<InputClaim ClaimTypeReferenceId="scope" DefaultValue="{app id uri for protected resource}/.default" />
</InputClaims>
<OutputClaims>
<OutputClaim ClaimTypeReferenceId="bearerToken" PartnerClaimType="access_token" />
</OutputClaims>
<UseTechnicalProfileForSessionManagement ReferenceId="SM-Noop" />
</TechnicalProfile>
And then making the rest api call using below profile :
<TechnicalProfile Id="UserMigrationViaLegacyIdp">
<DisplayName>REST API call to communicate with Legacy IdP</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://99a0a14a6402.ngrok.io/api/Identity/SignUpAsync
</Item>
<Item Key="AuthenticationType">Bearer</Item>
<Item Key="SendClaimsIn">Header</Item>
<Item Key="AllowInsecureAuthInProduction">false</Item>
<Item Key="UseClaimAsBearerToken">bearerToken</Item>
</Metadata>
<InputClaims>
<InputClaim ClaimTypeReferenceId="bearerToken"/>
</InputClaims>
<OutputClaims>
<OutputClaim ClaimTypeReferenceId="phonePresent"/>
</OutputClaims>
<UseTechnicalProfileForSessionManagement ReferenceId="SM-Noop" />
</TechnicalProfile>
However, scopes are missing from the returned access token, hence token validation is failing on the api.
Is my call to get access token missing anything?
For the client credentials grant flow, the API permissions must be created as roles (see How to: Add app roles to your application and receive them in the token) and then granted admin consent (see Admin consent button).
As result, the bearer token contains the roles claim, rather than the scp claim.
The API application checks access using this roles claim (see Verify app roles in APIs called by daemon apps).

Azure AD B2C - call rest api with parameter in header

I'm trying to call a rest api in a technical profile which requires parameters to be passed to it through the header, but I'm unable to do so. I have:
<TechnicalProfile Id="techProfile1">
<DisplayName>Technical Profile 1</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://xxxxxxx.azurewebsites.net/api/controller/action</Item>
<Item Key="AuthenticationType">Basic</Item>
<Item Key="SendClaimsIn">Header</Item>
<Item Key="AllowInsecureAuthInProduction">true</Item>
</Metadata>
<CryptographicKeys>
<Key Id="BasicAuthenticationUsername" StorageReferenceId="xxxxxx" />
<Key Id="BasicAuthenticationPassword" StorageReferenceId="xxxxxx" />
</CryptographicKeys>
<InputClaims>
<InputClaim ClaimTypeReferenceId="claimName1" PartnerClaimType="paramName1" />
</InputClaims>
<OutputClaims>
<OutputClaim ClaimTypeReferenceId="output1"/>
</OutputClaims>
<UseTechnicalProfileForSessionManagement ReferenceId="SM-Noop" />
</TechnicalProfile>
Where the value I'm trying to pass in is the ClaimName1 claim, and the parameter name is paramName1. Am I correct in using the InputClaim section for this?
The response back that I get is: AADB2C90075: The claims exchange 'techProfile1' specified in step '3' returned HTTP error response with Code 'InternalServerError' and Reason 'Internal Server Error'.
Am I right in assuming that the parameter is not being passed to the api? When I change the ServiceUrl to: https://xxxxxxx.azurewebsites.net/api/controller/action?paramName1=yyyy (where yyyy is the value held in the claimName1 claim), then it works as expected.
<Item Key="SendClaimsIn">Header</Item>
instead of the above one try the below one
<Item Key="SendClaimsIn">QueryString</Item>
This will add the input claim as query param.

Resources