How to work with a null claim returned by rest API in Azure AD B2C? - azure-ad-b2c

In Azure AD B2C I have a string type user extension claim: extension_test
In my user flow, I call a Rest API which will return a string claim: test
If test is null then I do not want to overwrite extension_test, otherwise I want the value of test to overwrite the value currently in extension_test. If it helps, the string value is actually a JSON formatted string array, i.e. [\"app1\", \"app2\"].
I would like to accomplish this in the most direct and simple way possible, which sometimes seems challenging in Azure AD B2C. I have tried the following on the output claim:
<OutputClaim ClaimTypeReferenceId="extension_test" PartnerClaimType="test" DefaultValue="{Claim:extension_test}" />
But extension_test is nulled.
I have looked for claims transformations that could "copy claim if not null", but didn't find anything. I am currently updating the API to not return the test claim if it is null, but that also adds complexity. I'm looking to tackle this from the Azure B2C side if it is simple and I am overlooking something?

Related

Email claim missing in Azure B2C User Flow

I have B2C tenant xxx.onmicrosoft.com and account admin#xxx.onmicrosoft.com.
I have API Connector (Azure Function called B2CRoleAssignment) that gets triggered before including application claims in token (Preview).
When I first attempt to sign into my SPA application with admin#xxx.onmicrosoft.com this is the following payload my API Connector (Azure Function) receives:
{
"step":"PreTokenIssuance",
"client_id":"XXXXYYYY-XXXX-YYYY-ZZZZ-d6b8da8e942a",
"ui_locales":"en-US",
"email":"admin#xxx.onmicrosoft.com",
"objectId":"AAAABBBB-CCCC-DDDD-EEEE-ad37b0ec108e",
"displayName":"admin"
}
When I close my SPA application and open it again, this is the payload API Connector (Azure Function) receives:
{
"step":"PreTokenIssuance",
"client_id":"XXXXYYYY-XXXX-YYYY-ZZZZ-d6b8da8e942a",
"ui_locales":"en-US",
"objectId":"AAAABBBB-CCCC-DDDD-EEEE-ad37b0ec108e",
"displayName":"admin"
}
How come the email claim is missing? On my Sign up and sign in User Flow I have selected Email Addresses application claim, but that doesn't seem to be working or doing anything at all.
The interesting thing is, this appears to only be a problem with accounts ending with #xxx.onmicrosoft.com.
• The email claim is missing during the sign in and signup user flow when selecting the API connector because the Azure function app is being considered by the Azure AD B2C as an untrusted domain website/application since the session is interrupted by closing and reopening the same due to which the session token might be considered expired/invalid immediately. As a result of which, the ‘email’ claim is omitted.
Thus, because of this, the email claim attribute might be returned null in the ‘application/json’ file as its value in the column might be missing or unknown. Hence, I would suggest you to please use the custom policies for signin or signup instead of default user flows in the Azure AD B2C console. Also, ensure that in the sign in and sign-up custom policy starter pack or the default custom policy in which editing needs to be done, do add the below claims in the custom policy output claims such that you will get the ‘email’ as an attribute in the response decoded token since adding the below claims will allow you to sign in through multiple claim attributes and you might not be getting email claim when using other claim types other than email.
<!-- This was already here -->
<OutputClaim ClaimTypeReferenceId="email" />
<!-- Added claim -->
<OutputClaim ClaimTypeReferenceId="signInNames.emailAddress"
PartnerClaimType="email" />
To find the default custom policy starter pack, refer the below link for more details: -
https://github.com/Azure-Samples/active-directory-b2c-custom-policy-starterpack
Also, to know more regarding the above issue and its accepted solution, kindly refer to the below community link: -
Why is email not returned with api connector when SSO with azure b2c?

Read and Update Azure AD B2C extension attributes

I have a trust framework SignUpOrSignIn custom policy user flow which sets 3 extension attributes for an app.
I can see these 3 claims and their default values in the token.
However, when I GET the user via MS Graph API (https://graph.microsoft.com/beta/{tenantId}/users/{userId}), I do not see these extension attributes.
Once I PATCH the user, I can then see the value via the GET to the {userId} segment as expected.
PATCH
{
"extension_{appId}_subscription_expiry":"2020-04-10"
}
Why are any extension attributes not returned until they've been subsequently PATCHed?
Although you have set default values for the 3 extension attributes in your custom policy, you can only see them in the token after your sign-up at that time. But you didn't store them into Azure AD.
I guess that you just add such a code <OutputClaim ClaimTypeReferenceId="extension_subscription_expiry" AlwaysUseDefaultValue="true" DefaultValue="xxx" /> in your SignUpOrSignIn.xml file.
But if you want to store the values into Azure AD, you should write the custom claim to the user profile by using AAD-UserWriteUsingLogonEmail TechnicalProfile. See Read and write a claim.
You should finish all the steps listed in this document: Add claims and customize user input using custom policies in Azure Active Directory B2C

Capturing Policy Url on CombinedSignInAndSignUp page in Azure B2C custom policy

I'm trying to capture the URL of the Azure B2C custom policy as user lands on the first page. This is the CombinedSignInAndSignUp orchestration step (the first combined signup/sign-in page). I want to use this url at later stage during the user journey.
I'm fiddling with the idea of displaying a pop-up with custom message if anything goes wrong and journey can not be continued further.
Current recommendation from Microsoft is that it throws an error and backend application should handle that error and take appropriate action (like in the case of Forgot Password link). I'm trying to handle this situation slightly different in the sense that I'd rather show this message to the user and redirect back to the policy (sign-up or password reset).
I have tried to setup extra input controls on CombinedSignInAndSignUp step but it doesn't seem to support that, it's only showing username and password controls. The idea was I capture current url (via JavaScript), store it in that input control (claim) and carry it forward in the journey and use it when needed to redirect the user back to that policy.
Any suggestion on how this can be achieved?
Thanks
Sanjay
I am not sure if the url can be captured or not but its easy o construct it using claims transformations and claim resolver.
Following will be the format of the policy url with all the claim resolver mentioned. You will need a claims transformation to format the final url .
https://{Policy:RelyingPartyTenantId}.b2clogin.com/{Policy:RelyingPartyTenantId}.onmicrosoft.com/oauth2/v2.0/authorize?p={Policy:PolicyId}&client_id={OIDC:ClientId}&nonce={OIDC:Nonce}&redirect_uri=https%3A%2F%2Fjwt.ms&scope{OIDC:scope}&response_type=id_token&prompt={OIDC:Prompt}&ui_locales={Culture:LanguageName}
There are two variables which currently are not available in custom policy as a claims resolver- redirect_uri and responseType. For them you have two options
- Hard code them
- duplicate them into other query string param to the policy url and then extract them as claims resolver. B2C has claims resolver which can get value from query string params it's called {OAUTH-KV} claims resolver. example for a query string parameter testReplyUrl.
<OutputClaim ClaimTypeReferenceId="replyUrl" DefaultValue="{OAUTH-KV:testReplyUrl}" AlwaysUseDefaultValue="true" />
<BuildingBlocks>
<ClaimsSchema>
<ClaimType Id="replyUrl">
<DisplayName>redirect uri</DisplayName>
<DataType>string</DataType>
<AdminHelpText>Reply url</AdminHelpText>
<UserHelpText>ReplyUrl.</UserHelpText>
</ClaimType>
</ClaimsSchema>
</BuildingBlocks>

Rest API call during Azure AD B2C SignIN in Custom Policy

Is there a way to do Rest API calls during Sign In in Azure AD B2C policy?
I want to add few properties in claims at the time when user sign in to the application. I can see that it is possible while sign up
https://learn.microsoft.com/en-us/azure/active-directory-b2c/active-directory-b2c-rest-api-step-custom
But is it possible during Sign In as well ?
If you are using custom policy, it's very similar to Sign-up. You create the technical profile for your REST endpoint and use it either as a ValidationTechnicalProfile in your 'sign-in' technical profile or add it as an orchestration step - depends what you want to do.
Any particular problem you are facing while adding this in your sign-in journey?
I don't have any issue while I am adding sing-in journey.
can call REST API successfully and can received other input values except password value.
Below is the output result from my function app:
GetExternalSystemIdOnLogin got request body:
{
"email": "xxxx#test.com",
"objectId": "dec23a2c-64c3-49c4-9943-4cfe0cffa0ed"
}

Azure B2C with Salesforce, missing "objectId"

I'm testing Azure B2C with Salesforce as IdP, and the login process works fine from Salesforce perspective (Salesforce Identity Provider Event Log show "success" for sing-on attempts), but redirection back to simple testing web application ends up to error page such as
/redirect.html#error=server_error&error_description=AADB2C90037%3a+An+error+occurred+while+processing+the+request.+Please+contact+administrator+of+the+site+you+are+trying+to+access.%0d%0aCorrelation+ID%3a+f0292157-ffad-472d-8119-3cd05518654c%0d%0aTimestamp%3a+2018-02-13+15%3a01%3a54Z%0d%0a
Looking at Application Insights, I see error:
A claim could not be found for lookup claim with id "objectId" defined in
technical profile with id "AAD-UserReadUsingObjectId" policy
"B2C_1A_SignUpOrSignInUsingSalesforce" of tenant "xyz.onmicrosoft.com".
I've followed the tutorial here and double checked lots of things, but not sure it this issue is due to invalid UserJourney or ClaimsProvider/TechnicalProfile. Or is it just that I'm missing respective user in Azure B2C that I have in Salesforce?
I don't at least see 'objectId' incoming in saml:Assertion:
<saml:Assertion xmlns:samlp=\""urn:oasis:names:tc:SAML:2.0:protocol\"" xmlns:xsi=\""http://www.w3.org/2001/XMLSchema-instance\"" ID=\""_b0b0193ce1e861e13ec39f9a991cb3501518533690616\"" Version=\""2.0\"" IssueInstant=\""2018-02-13T14:54:50.616Z\"" xmlns:saml=\""urn:oasis:names:tc:SAML:2.0:assertion\""><saml:Issuer Format=\""urn:oasis:names:tc:SAML:2.0:nameid-format:entity\"">https://XYZ.my.salesforce.com</saml:Issuer><saml:Subject><saml:NameID Format=\""urn:oasis:names:tc:SAML:2.0:nameid-format:transient\"">jussi.palo#XYZ.com</saml:NameID><saml:SubjectConfirmation Method=\""urn:oasis:names:tc:SAML:2.0:cm:bearer\""><saml:SubjectConfirmationData NotOnOrAfter=\""2018-02-13T14:59:50.616Z\"" Recipient=\""https://login.microsoftonline.com/te/XYZauthdev.onmicrosoft.com/B2C_1A_TrustFrameworkBase/samlp/sso/assertionconsumer\"" InResponseTo=\""_50a752dd-244c-4447-9ac9-6338e8bb692e\"" /></saml:SubjectConfirmation></saml:Subject><saml:Conditions NotBefore=\""2018-02-13T14:54:20.616Z\"" NotOnOrAfter=\""2018-02-13T14:59:50.616Z\""><saml:AudienceRestriction><saml:Audience>https://login.microsoftonline.com/te/XYZauthdev.onmicrosoft.com/B2C_1A_TrustFrameworkBase</saml:Audience></saml:AudienceRestriction></saml:Conditions><saml:AuthnStatement AuthnInstant=\""2018-02-13T14:54:50.616Z\""><saml:AuthnContext><saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified</saml:AuthnContextClassRef></saml:AuthnContext></saml:AuthnStatement><saml:AttributeStatement><saml:Attribute Name=\""userId\"" NameFormat=\""urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified\""><saml:AttributeValue xsi:type=\""xs:anyType\"">0050N0000060rpy</saml:AttributeValue></saml:Attribute><saml:Attribute Name=\""username\"" NameFormat=\""urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified\""><saml:AttributeValue xsi:type=\""xs:anyType\"">jussi.palo#XYZ.com</saml:AttributeValue></saml:Attribute><saml:Attribute Name=\""email\"" NameFormat=\""urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified\""><saml:AttributeValue xsi:type=\""xs:anyType\"">jussi.palo#XYZ.com</saml:AttributeValue></saml:Attribute><saml:Attribute Name=\""is_portal_user\"" NameFormat=\""urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified\""><saml:AttributeValue xsi:type=\""xs:anyType\"">false</saml:AttributeValue></saml:Attribute></saml:AttributeStatement></saml:Assertion>
For some reason, the User Journey Player isn't showing anything, so I'm thus far been stuck with Application Insights.
Looks like it was confusion on what Starter Pack policy files should be used with the Salesforce instructions. Turned out using "SocialAndLocalAccounts" policy files as a basis did the trick, so my UserJourney was not right at first.
I will leave the question here for anyone else running into similar error messages.

Resources