How to use AD B2C Automation to get a Token with custom claims - azure-ad-b2c

I am using the techniques described in AD B2C->Automation->Account Management to get an Access token for an application. This is working fine, but I want to add some custom claims to the returned token. Is there some way I can use Custom Policies to add custom claims when an application requests a token?
Note: I already have custom policies that I use for interactive signons, which add claims to the returned token. I would like to somehow use these in a non-interactive mode.

I already have custom policies... I would like to somehow use these in a non-interactive mode.
For non-interactive authentication/authorization w/ B2C that would the ROPC (Resource Owner Password Credentials) flow.
In the relying party file you can output custom claims:
<OutputClaim ClaimTypeReferenceId="sub" />
<OutputClaim ClaimTypeReferenceId="objectId" />
<OutputClaim ClaimTypeReferenceId="myCustomClaim" DefaultValue="" />

Related

Understanding responses from just in time migration custom policy in Azure B2C

I have been slowly working through a custom policy to handle a JIT migration of an external IDP users to Azure B2C. It has been a long journey because there are many complexities in sorting out the components and the configuration steps using XML is a bit of a challenge. I am making some progress.
The basic use case is this: At sign in, the user/password is first checked against the B2C AD and if the user already exists just continue to sign in. If the user isn't in B2C AD, then check the external IDP with a REST call. I planned the response from the external IDP to be used in a binary way: If I get a 200 response, then add the user to B2C AD. If an error is returned then the user will be told to create an account.
I started with a couple of samples from a JIT Migration that I found. I had some difficulty navigating all the components with the social media logins, etc that I then reverted back to the "Local Accounts" sample found in the custom policy starterpack. I got the basic steps to work with no modification. I then added the technical profiles for the REST calls to the extensions file. I used the extension from one of the JIT migration samples and at least got the uploads to work. I am able to present a login prompt.
These are the scenarios and responses I see: 1) A user that I know is in B2C returns an error of "Unable to validate the information provided." 2) A user that I know is in the external IDP but not in B2C returns "We can't seem to find your account". 3) If I try a completely made up account that exists in neither, I see "The claims exchange 'REST-UserMigration-LocalAccount-SignIn' specified in step '1' returned HTTP error response with Code 'BadRequest' and Reason ''. "
So the question/struggle is how do I best sort out what is failing in each step. I have added app insights to the environment. I do see the traces in VS Code. But what should I look for? Here is the short responses ("Exceptions") for each of the errors listed above:
Scenario 1: The claim type "signInNames.emailAddress", designated as the identifier claim type, could not be found in the claims collection for the claims principal in tenant id "B2C_1A_JITMigration_signup_signin"
Scenario 2: A user with the specified credential could not be found.
Scenario 3: ErrorCodes: AADB2C90075
Rather than post of the code, here is the link to what I copied: https://github.com/azure-ad-b2c/user-migration/blob/master/jit-migration-v2/policy/TrustFrameworkExtensions.xml I can post up my exact code but basically I changed the tenant and the REST call. The Technical profile for the REST call snippet is:
<InputClaims>
<InputClaim ClaimTypeReferenceId="signInName" PartnerClaimType="username"/>
<InputClaim ClaimTypeReferenceId="password" />
</InputClaims>
<OutputClaims>
<OutputClaim ClaimTypeReferenceId="needToMigrate" />
<OutputClaim ClaimTypeReferenceId="email" />
<OutputClaim ClaimTypeReferenceId="newPassword" />
<OutputClaim ClaimTypeReferenceId="displayName" />
<OutputClaim ClaimTypeReferenceId="givenName" />
<OutputClaim ClaimTypeReferenceId="surname" />
</OutputClaims>
<UseTechnicalProfileForSessionManagement ReferenceId="SM-Noop" />
</TechnicalProfile>
The input claims are fine but I am not sure how to modify the output claims. The REST API returns a single value of an authentication token which I don't need but is an indication that the authentication succeeded. It returns an error if the authentication fails. Basically an HTTP 200 is good, an HTTP 400 means the user doesn't exist. The goal is to use that API call as a binary indicator to either migrate or not migrate the user. Perhaps I cannot use the API in that way.
My hope is to solve each scenario step by step. Figure out why the scenario 1 doesn't work although the credential are correct. Then figure out why scenario 2 is correctly identifying that the user isn't found but wasn't automatically migrated. Finally, to figure out how to manage the 400 error returned by the API when the user doesn't exist in the external IDP.
I might need to tweak the user journeys or orchestration steps? Taking baby steps here.
Thanks

Adding Application Claims from User Flow into AAD B2C Custom Policy

This is the Azure B2C User Flow’s Application claims, where I can tick the Email Addresses and save it.
UserFlow Application Claims
How can I do this in custom policy? I am trying to add Multi-Tenant login to AAD B2C via custom policies and I need to select this ‘Email Addresses’ in the Application Claims from User Flow.
How can I select or activate this same ‘Email Addresses’ in custom policy XML files?
So far I tried adding -->> OutputClaim ClaimTypeReferenceId="signInNames.emailAddress" <<-- to the technical profiles, but still no luck.
The claim you want is "preferred_username".
Try to add <OutputClaim ClaimTypeReferenceId="email" PartnerClaimType="preferred_username" />.

How can I see data for users created by a custom policy?

I have Signup and Sinin custom policy that allow users to signup or signin. It works well.
The policy uses the following claims:
<OutputClaim ClaimTypeReferenceId="extension_firstName" />
<OutputClaim ClaimTypeReferenceId="extension_lastName" />
<OutputClaim ClaimTypeReferenceId="extension_organizationName" />
<OutputClaim ClaimTypeReferenceId="extension_contactPhoneNumber" />
<OutputClaim ClaimTypeReferenceId="extension_selectRole" />
<OutputClaim ClaimTypeReferenceId="extension_terms" />
When I goto B2C portal, find the user and look the user details, none of the extension_* claims (attributes or properties) appear there.
Then I use Microsoft Graph, issue this query:
https://graph.microsoft.com/v1.0/users/[user Object ID]
I get minimal data for the user. None of the extension_* calim data appears there.
How can I see all the extension_* claim data with a give user created by custom policy?
The Azure portal doesn't display the extension properties for users.
For the Microsoft Graph query, you must add the $select parameter in order to include the extension properties, such as:
GET https://graph.microsoft.com/v1.0/users/{id}?$select=extension_{b2cExtensionsAppClientId}_firstName,extension_{b2cExtensionsAppClientId}_lastName,...
where {b2cExtensionsAppClientId} is the application (client) identifier (without hyphens) for [the b2c-extensions-app application}(https://learn.microsoft.com/en-us/azure/active-directory-b2c/extensions-app) that is registered in your Azure AD B2C tenant such as:
extension_b2ba52d57b074a5e8fa2d8b35f5a1347_firstName

Azure B2C custom saml policy: Different claims per App

I followed this manual to register SAML to my azure b2c: https://learn.microsoft.com/en-us/azure/active-directory-b2c/connect-with-saml-service-providers
With this I am able to define SAML claims in my new TechnicalProfile with for example
<OutputClaim ClaimTypeReferenceId="surname"/>
Now, I have application which expects EXACTLY some attributes with a specific name. Setting PartnerClaimType to some custom string will result in a saml attribute with that string as attribut name:
<OutputClaim ClaimTypeReferenceId="surname" PartnerClaimType="LastName" />
This will result in:
<saml:Attribute Name="LastName"
NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic"
FriendlyName="Surname">
<saml:AttributeValue xsi:type="xs:string">Peters</saml:AttributeValue>
</saml:Attribute>
But I can just configure claims on that profile - I need to specify it in the app registration in azure.
So the 1st application needs attribute "surname", next needs "FamilyName" and 3rd needs "LastName".
How can I use the claim defined in the policy and change it in the app? I saw there is some property "optionalClaims" in the manifest and there are "saml2Token". But the documentation of this did not helped me (https://learn.microsoft.com/de-de/azure/active-directory/develop/active-directory-optional-claims).
If you are connecting 3 SAML Relying Parties, you would have 3 Application Registrations, and 3 Relying Party technical profiles as part of your Custom Policy. Each Relying party section would have the required claims mappings.

Azure AD B2C Add Claims to id_token in custom policy

I have created custom policies for social and local accounts based on the example from the Active Directory B2C custom policy starter pack for social and local accounts. I have enabled the login with Microsoft and Google and tested that both work, I have also enabled logging in with a local account.
When I log in with google I get the following claims
exp,nbf,ver,iss,sub,aud,acr,nonce,iat,auth_time,email,given_name,family_name,name,idp,at_hash
When I log into a custom Azure AD tenant the set of claims is missing 'email', but the email is listed in the 'name' claim
exp,nbf,ver,iss,sub,aud,acr,nonce,iat,auth_time,given_name,family_name, name,idp,at_hash
When I log in as a local account the set of claims is missing 'email' and there is no email listed in any of the fields.
exp,nbf,ver,iss,sub,aud,acr,nonce,iat,auth_time,given_name, family_name,name,at_hash
Finally, when I look at the list of users in the B2C admin, these are all different user entries...even though the email address is the same. So I have 2 questions,
How do I get a consistent set of claims in the id_token
How do I link all these accounts together at registration time (Same UPN)
I believe these may be related, which is why I am asking them together.
You probably want to see the policies, but I assure you they are exactly the same as the policies in the starter pack, all I've done is change the tenant names and added google and azure in the trust framework extensions file.
For the Azure AD email claim, add the following <OutputClaim /> to the Azure AD OpenID Connect technical profile:
<OutputClaim ClaimTypeReferenceId="email" PartnerClaimType="unique_name" />
For the local account email claim, add the following <OutputClaim /> to the AAD-UserReadUsingObjectId technical profile:
<OutputClaim ClaimTypeReferenceId="email" PartnerClaimType="signInNames.emailAddress" />

Resources