Wednesday, April 13, 2016

ADFS : Authenticating with LDAP

This is for Active Directory Federation Services on Server 2016 Technical Preview 4.

Just to re-iterate - the ADFS has to be Server 2016 - TP4 and above. This will not work on Server 2012 R2 - ADFS 3.0.

I used the following for reference:
To sum up the main points:

"AD FS supports any LDAP v3-compliant directory.

In order for AD FS to authenticate users from an LDAP directory, you must connect this LDAP directory to your AD FS farm by creating a local claims provider trust.

You can support multiple LDAP directories, each with its own configuration, within the same AD FS farm by adding multiple local claims provider trusts. In addition, AD DS forests that are not trusted by the forest that AD FS lives in can also be modelled as local claims provider trusts. You can create local claims provider trusts by using Windows PowerShell.

LDAP directories (local claims provider trusts) can co-exist with AD directories (claims provider trusts) on the same AD FS server, within the same AD FS farm, therefore, a single instance of AD FS is capable of authenticating and authorising access for users that are stored in both AD and non-AD directories.

Only forms-based authentication is supported for authenticating users from LDAP directories.

Certificate-based and Integrated Windows authentication are not supported for authenticating users in LDAP directories.

All passive authorisation protocols that are supported by AD FS, including SAML, WS-Federation, and OAuth are also supported for identities that are stored in LDAP directories.

The WS-Trust active authorisation protocol is also supported for identities that are stored in LDAP directories."

And:

"In ADFS v1.0 and ADFS v1.1 it was possible to use both AD and AD LDS / ADAM as an identity store. One of the very common scenarios is to use the AD identity store for internal users and use the AD LDS / ADAM identity store for external users (e.g. partners, customers, vendors, etc.). 

All the ADFS versions starting with ADFS v2.0 and higher only supported AD as the identity store and nothing else. That could be one of the reasons why some companies remained using ADFS v1.x.

If you would like to support a similar scenario, where you would like to have a separate identity store for externals, you would need to either:
  • Configure a separate AD with its own ADFS infrastructure and configure federation between them
  • Use Azure AD to store those identities and configure federation"
With Server 2016 and ADFS vNext or 4.0 or whatever it is going to be called, the last paragraph is no longer true.

AD LDS is an instance of an LDAP and hence can be supported by ADFS 4.0. This means you can finally retire that instance of ADFS 1.x. Cue massive applause :-)

The previous post detailed how to run up an instance of AD LDS on Server 2016.

This all has to be done with PowerShell. The instance names are as per that previous post.

 $DirectoryCred = Get-Credential

This pops up FBA. I used my domain admin. account.

$vendorDirectory = New-AdfsLdapServerConnection –HostName my-adfs.dev.local –Port 50000 –SslMode None –AuthenticationMethod Basic –Credential $DirectoryCred

$GivenName = New-AdfsLdapAttributeToClaimMapping –LdapAttribute givenName –ClaimType “http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname”

$CommonName = New-AdfsLdapAttributeToClaimMapping –LdapAttribute cn –ClaimType “http://schemas.xmlsoap.org/claims/CommonName”

$Surname = New-AdfsLdapAttributeToClaimMapping –LdapAttribute sn –ClaimType “http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname”


Add-AdfsLocalClaimsProviderTrust –Name "AD LDS" –Identifier "TP4-1" –Type Ldap -LdapServerConnection $vendorDirectory –UserObjectClass user –UserContainer "CN=ADFS,DC=dev,DC=local" –LdapAuthenticationMethod Basic  –AnchorClaimLda
pAttribute mail –AnchorClaimType "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn" –LdapAttributeToClaimMapping @($GivenName, $Surname, $CommonName) -AcceptanceTransformRules "@RuleName = `"Issue All Mapped Claims`"`nc:[] => is
sue(claim = c);" –Enabled $true


This will give a warning:

"WARNING: PS0245: Because no organizational account suffixes were specified, this claims provider trust will not be accessible by requests that use the active profile."

If you want this, you need:

Set-AdfsClaimsProviderTrust -TargetName "AD LDS" -OrganizationalAccountSuffix @("dev.local")

Note that the HRD screens will then be slightly different. You can see examples of this in the second article above.

When I setup the local CP trust, I got an error around invalid credentials. I eventually noticed that I had omitted to define $Surname. Once I fixed that, the error went away. That error is very misleading!

Also note that the new CP will not be displayed in the ADFS wizard.

You can, however, see it with:
Get-AdfsLocalClaimsProviderTrust

UserObjectClass             : user
UserContainer               : CN=ADFS,DC=dev,DC=local
AnchorClaimLdapAttribute    : mail
LdapAuthenticationMethod    : Basic
LdapServerConnection        : {my-adfs.dev.local}
LdapAttributeToClaimMapping : {Microsoft.IdentityServer.Management.Resources.LdapAttributeToClaimMapping, Microsoft.IdentityServer.Management.Resources.LdapAttributeToClaimMapping,
                              Microsoft.IdentityServer.Management.Resources.LdapAttributeToClaimMapping}
LocalClaimsProviderType     : Ldap
AnchorClaimType             : http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn
IdentifierType              : http://schemas.microsoft.com/ws/2009/12/identityserver/principaltypes/uri
Identities                  : {http://schemas.microsoft.com/ws/2009/12/identityserver/TP4-1}
AcceptanceTransformRules    : @RuleName = "Issue All Mapped Claims"
                              c:[]
                               => issue(claim = c);

OrganizationalAccountSuffix : {}
Enabled                     : True
IsLocal                     : True
Identifier                  : TP4-1
Name                        : AD LDS
Notes                       :
ProtocolProfile             : WsFed-SAML
To test this I used the OpenID Connect sample referred to in one of my previous posts. Yes, you read that correctly. Not only are we going to authenticate on AD LDS with ADFS, we are going to use the OpenID Connect protocol. Neat!

(This makes sense when you remember that AD LDS is just the Identity repository. The actual protocol layer is handled by ADFS).

When we run up the sample, we see the expected HRD.


 Authenticating with "adamuser1@dev.local" we get the expected JWT claims:


Goodbye ADFS 1.x!

Enjoy!

3 comments:

Anonymous said...

Is there a download for that app that dumps the content of a JWT token? I'm not a dev and I don't know how to create it myself.
Thank you

nzpcmad said...

Not at the moment - these examples are mostly web apps which can't really be downloaded.

I'll have a think about it.

Erwin Vos said...

I'd like to pass AD LDS group membership information as token-groups claim. How can I do this?