I followed the example in Set up sign-in with a Salesforce SAML provider by using custom policies in Azure Active Directory B2C and was able to successfully SSO from Salesforce into Azure B2C. However, I would also like to retrieve the value of the NameID element from the SAML Assertion as a claim. Is this possible?
For example, say that the incoming SAML 2.0 Assertion posted to B2C's assertion consumer endpoint looks something like this simplified XML.
<saml:Assertion>
<saml:Issuer>https://mytestinstance-dev-ed.my.salesforce.com</saml:Issuer>
<saml:Subject>
<saml:NameID>emp99999</saml:NameID>
</saml:Subject>
<saml:AuthnStatement AuthnInstant="2018-10-04T16:56:44.192Z">
<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">
<saml:AttributeValue>009f90000099zzz</saml:AttributeValue>
</saml:Attribute>
<saml:Attribute Name="username">
<saml:AttributeValue>user000@example.com</saml:AttributeValue>
</saml:Attribute>
<saml:Attribute Name="email">
<saml:AttributeValue>user000@example.com</saml:AttributeValue>
</saml:Attribute>
<saml:Attribute Name="">
<saml:AttributeValue>false</saml:AttributeValue>
</saml:Attribute>
</saml:AttributeStatement>
</saml:Assertion>
The TechnicalProfile lets you access any Attribute from the AttributeStatement as a claim by referencing its Name in the PartnerClaimType in an OutputClaim element. For example, with the TechnicalProfile below, the socialIdpUserId claim is set to the value of the userId attribute from the SAML Assertion, "009f90000099zzz". What I would like to have is is a claim named employeeId that is set to "emp99999," the value of the NameID element.
<TechnicalProfile Id="salesforce">
<DisplayName>Salesforce</DisplayName>
<Description>Login with your Salesforce account</Description>
<Protocol Name="SAML2"/>
<Metadata>
<Item Key="RequestsSigned">false</Item>
<Item Key="WantsEncryptedAssertions">false</Item>
<Item Key="WantsSignedAssertions">false</Item>
<Item Key="PartnerEntity">https://mytestinstance-dev-ed.my.salesforce.com/.well-known/samlidp/TestB2C.xml</Item>
</Metadata>
<!-- <CryptographicKeys> -->
<OutputClaims>
<OutputClaim ClaimTypeReferenceId="socialIdpUserId" PartnerClaimType="userId"/>
<OutputClaim ClaimTypeReferenceId="email" PartnerClaimType="email"/>
<OutputClaim ClaimTypeReferenceId="displayName" PartnerClaimType="username"/>
<OutputClaim ClaimTypeReferenceId="authenticationSource" DefaultValue="socialIdpAuthentication"/>
<OutputClaim ClaimTypeReferenceId="identityProvider" DefaultValue="SAMLIdp" />
<!-- We want the Subject/NameID value as a custom employeeId claim. URI reference doesn't work. -->
<OutputClaim ClaimTypeReferenceId="employeeId"
PartnerClaimType="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier" />
</OutputClaims>
<!--<OutputClaimsTransformations> -->
<UseTechnicalProfileForSessionManagement ReferenceId="SM-Noop"/>
</TechnicalProfile>
I tried using PartnerClaimType values like "NameID", "NameIdentifier", as well as the well-known URI for NameIdentifier and none of these seemed to work.
I also saw some references to the use of the SubjectNamingInfo element and experimented with it, but that only seems relevant in defining the token sent to a RelyingParty and not in reading claims from a token received from an IDP.
Also, what about any other Assertion elements? For example, depending on how an IDP uses it, I could see a need to read the AuthnContextClassRef value to make a decision about whether to issue an MFA challenge.
For the SAML2 protocol, the value of the NameID element can be accessed by using a
PartnerClaimType
with the value "assertionSubjectName". This is mentioned in the "Specifying a technical profile for a SAML 2.0 claims provider" section of Features part 6 in the Advanced Policies Git repo.For example, to map the NameID from the SAML Assertion to the "employeeId" claim, set its
PartnerClaimType
to "assertionSubjectName" in theOutputClaim
claim element.Another example can be found in Specifying a technical profile for a SAML 2 excerpt from documentation.docx.
Edit
Per Adam C's answer, this is now documented at Define a SAML technical profile in an Azure Active Directory B2C custom policy. He also notes that B2C will not map NameID to your output claim if the NameID element has a "NameQualifier" attribute.
In my case, I was trying to extract the NameID from a SAML response where the NameID element had an
SPNameQualifier
attribute. UsingassertionSubjectName
was not working.However, what did work was using the
SPNameQualifier
attribute value.For example, suppose your SAML response looks like
To extract the NameID value you can set your claim mapping as
The solution to use assertionSubjectName is definitely correct. In fact, MSFT updated their main documentation page on Dec 20th 2018 to add further information: Define a SAML Technical Profile. That being said - I wanted to add one more note that may help others who come across this behavior. It appears that Azure will NOT map the NameID to your output claim if the NameID element has a "NameQualifier" attribute.
Example - this will map to your output claim:
This will NOT map to your output claim:
Hopefully this will be helpful to anyone who has run into a situation where "assertionSubjectName" does not appear to work. That being said - it seems that this behavior is not all that desirable and I have reached out to MSFT to find out if this is WAD or not.