How do I read the NameID element as a claim in a B

2019-05-26 13:00发布

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.

3条回答
看我几分像从前
2楼-- · 2019-05-26 13:48

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 the OutputClaim claim element.

<OutputClaims>
    <!-- Other claims -->
    <OutputClaim ClaimTypeReferenceId="employeeId" 
        PartnerClaimType="assertionSubjectName" />
</OutputClaims>

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.

查看更多
疯言疯语
3楼-- · 2019-05-26 13:49

In my case, I was trying to extract the NameID from a SAML response where the NameID element had an SPNameQualifier attribute. Using assertionSubjectName was not working.

However, what did work was using the SPNameQualifier attribute value.

For example, suppose your SAML response looks like

<saml:Subject>
  <saml:NameID SPNameQualifier="https://bar.com/realms/foo">emp99999</saml:NameID>
</saml:Subject>

To extract the NameID value you can set your claim mapping as

<OutputClaims>
  <!-- Other claims -->
  <OutputClaim ClaimTypeReferenceId="employeeId" PartnerClaimType="https://bar.com/realms/foo" />
</OutputClaims>
查看更多
贪生不怕死
4楼-- · 2019-05-26 13:51

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:

 <Subject>
            <NameID>foo@bar.com</NameID>

This will NOT map to your output claim:

<Subject>
    <NameID NameQualifier="https://bar.com/realms/foo">foo@bar.com</NameID>

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.

查看更多
登录 后发表回答