Connecting Azure AD B2C to ADFS via SAML 2.0 and custom policies

Rory Braybrook
The new control plane
4 min readJun 10, 2019

There’s a good write-up on this here but it has some pieces missing so I thought I would write this up.

I found a few errors and omissions in the article when I was working through so it so I submitted a few PR — which is something I encourage everyone to do. It makes docs.microsoft better for everyone.

Whenever I run up a VM in Azure to install ADFS, I always use a self-signed certificate for SSL. B2C will not accept this — it has to be a proper CA certificate.

If you want a free certificate, have a look at Let’s Encrypt. I followed this article on how to install a Let’s Encrypt certificate with ADFS.

In terms of a custom policy, note that B2C regards federation as the same as social. This connection won’t work if you use “LocalAccounts”. You need to use “SocialAndLocalAccounts”. Then you have to remove the default Facebook element. The write-up above assumes that you followed the “Getting started” article and that assumes that you are using the “SocialAndLocalAccounts” accounts template.

In terms of configuring ADFS, the write-up shows:

Note that the outgoing claim types are not selected from the drop-down. They are typed into the “dropdown” text box. That’s right, folks. The drop-down is editable! Just double-click in the text box.

My configuration looks like:

Notice that I have used “display_name” instead of “name”. That’s because whenever I typed “name”, the system would save it as “Name” which is a known claim type URI i.e.

“http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name"

My XML is then:

<OutputClaim ClaimTypeReferenceId=”issuerUserId” PartnerClaimType=”userPrincipalName” />
<OutputClaim ClaimTypeReferenceId=”givenName” PartnerClaimType=”given_name”/>
<OutputClaim ClaimTypeReferenceId=”surname” PartnerClaimType=”family_name”/>
<OutputClaim ClaimTypeReferenceId=”email” PartnerClaimType=”email”/>
<OutputClaim ClaimTypeReferenceId=”displayName” PartnerClaimType=”display_name”/>

Using the “Run now” feature, the user see the B2C login screen:

and then they click the “Staff” button to go to the ADFS login screen.

That just seems like an extra click. Is it possible to go directly to ADFS? Turns out you can via the “domain_hint” option.

The URL is then:

https://my-tenant.b2clogin.com/my-tenant.onmicrosoft.com/oauth2/v2.0/authorize
?p=B2C_1A_signup_signin_adfs
&client_id=56b34axxx8b25fc2f0d
&nonce=defaultNonce
&redirect_uri=https%3A%2F%2Fjwt.io
&scope=openid
&response_type=id_token
&prompt=login
&domain_hint=Staff

In the custom policy claims provider for ADFS:

<ClaimsProvider>
<Domain>Staff</Domain>
<DisplayName>MyDC ADFS</DisplayName>
<TechnicalProfiles>
<TechnicalProfile Id=”MyDC-SAML2">
<DisplayName>Staff</DisplayName>
<Description>Login with your ADFS account</Description>
<Protocol Name=”SAML2"/>

set this value in the “Domain” element.

The user then goes directly to the ADFS login page. They don’t see the B2C login screen. Nice!

The first time the user logs in via ADFS, they will see this screen in B2C:

This contains the details that were derived from the ADFS claims rules. Clicking “Continue” takes the user to the application.

An entry is created in B2C as a place holder:

Notice that user3 has a “Source” of “Other” as opposed to testuser2 that has a source of “Azure Active Directory”.

testuser2 went through the B2C sign-up flow and is a local account. This user can log directly into B2C.

user3 is a placeholder for a federated user via ADFS. This user cannot log directly into B2C. For a start, they don’t have a local password.

Let’s try with a dummy password.

B2C is telling us that there is no local account for user3.

The basic rule of thumb is that to logon through B2C, you have to sign-up through B2C.

All good!

--

--

Rory Braybrook
The new control plane

NZ Microsoft Identity dude and MVP. Azure AD/B2C/ADFS/Auth0/identityserver. StackOverflow: https://bit.ly/2XU4yvJ Presentations: http://bit.ly/334ZPt5