Revisiting the Microsoft Online immutable ID design decision

Some time back I posted about Azure Active Directory synchronisation using Forefront Identity Manager (FIM) 2010 R2 and the Azure AD Connector.  My focus was multi-forest deployments, but as we know this topology was required for several advanced scenarios too.  Microsoft have since shipped Azure AD Synchronization Services (AADSync), soon to be rebranded Azure AD Connect (AAD Connect), which negates the need for FIM for most deployments and further solidifies the mentality that the Azure AD identity bridge should be separate from the enterprise identity management solution.

Having deployed quite a few FIM and AAD Connector topologies for large, enterprise customers, and having been involved in planning and design, implementation and deployment and post go live support and transfer to operations I have learned, the hard way, that the immutable ID design artefact is a massive consideration, too often overlooked and not understood.  I talked about this in my post Windows Azure Active Directory Connector part 3: immutable ID but need to revisit the subject.  As an identity guy, I believe getting this particular design artefact right is the most fundamental aspect of an organisations journey to the Microsoft cloud.

My opinion on the matter is that you quite simply must generate your own unique identifier and write it back anywhere and everywhere you can.  Seriously.  You cannot trust other processes to do this for you!  You have to take charge of this yourself.

I have come to the conclusion that the approach I describe at the end of my previous post on this subject is the right and only approach.  I have tried to depend on upstream processes and have been bitten too many times.  There are simply too many anomalies, exceptions and inconsistencies.

The answer then is simple.  When you first project your metaverse object generate a unique ID and use it when you provision your AAD connector.  Write that value back to the source object in each connected directory.  If you are simply doing an advanced directory synchronisation, i.e. on-premises AD DS to Azure AD, the immutable ID should be written to both the AD DS and AAD connectors.  If you’re doing a resource and account forest model, that immutable ID needs to be written back to each on-premises AD DS domain and the AAD.  And if you’re doing some advanced identity date aggregation using on-premises AD DS and some LDAP directory or SQL store then you need to send that immutable ID right back into that data store.

In short, a provisioned, synchronised connector should look like this.

image

What have I drawn?  The most complex topology.  But it works for the simplest too (drawing below):

  1. The source of authority (AD DS account forest) contributes some unique value, e.g. objectGUID or csObjectGuid or mvObjectID or Guid.New()
  2. Each data contributor, e.g. resource forest (mailboxes), LDAP identity store (AD LDS or IBM Tivoli Directory Server), Oracle database, SQL database, SAP, whatever, contributes what they need to contribute and gets the some unique value from step 1 written back.
  3. Azure AD immutable ID/source anchor is the some unique value from step 1.

For simpler topologies, e.g. one forest (pictured below), the same logic is absolutely true.

image

  1. The source of authority (AD DS account forest) contributes some unique value, e.g. objectGUID or mvObjectGuid or csObjectGuid or Guid.New()
  2. Azure AD immutable ID/source anchor is the some unique value from step 1.

All good so far?  The only missing detail here is the big orange arrow in the next drawing.

image

Write that value back to the source of authority.  Don’t just use the objectGUID and be done with it.  Or the csObjectGuid.  Take the value, or just generate a new GUID, and write it into the MV object when the MV attribute is null and null only, i.e. never write it again.  Also write it back to the source object.  This way as all the drawings show, the value exists everywhere.  Now you can easily recover this value, write it back, and re-join without fuss.

Why and how?

That’s the theory done.  So why are we doing this and how are we going to do it?

Why?  Because GUIDs are easy to generate or source from somewhere and can be applicable to all user types not just mailboxes and mail users, i.e. this is consistent across user objects that represent people, administrators, service accounts, shared user accounts – basically anything that might want to logon to an online service.

Why write it back?  Because if you accidently delete the object, or you migrate the object, or you find some other crazy reason to need to repurpose the object as a different identity you have a supported, writeable attribute that will still marry-up with the cloud and anywhere else your identity data needs to come from.

Trust me.  I’ve seen duplicate immutable IDs, deleted immutable IDs, missing immutable IDs, objects that simply don’t get immutable IDs.  All of which means someone, somewhere either can’t logon or can’t be emailed or can’t access their data.

OK, that makes sense.  So how do we do it?  How do we write it back?

That depends on the tool.

I summarise it in my previous post.  Roelf Zomerman has detailed how to do it using AADSync in his excellent post ImmutableID – mS-DS-ConsistencyGuid – AADSync.

Please do this.  It will make your life as an Microsoft cloud services architect or designer easier; it will make your life as an hybrid identity bridge support engineer easier; it will make your life as a project manager easier; and it will make your life as an operations manager easier.  Because no matter what happens, there’s always a GUID and once you write it back to a writeable attribute, you always have the flexibility and freedom to write it again, or move it elsewhere, etc.

OK, I get it and I will do it!  What about my SAML tokens?  What impact here?

Yes, the rule that adds the immutable ID claim or assertion into the SAML token your on-premises federation services issues needs to be sending the write-back value, e.g. msDS-ConsistencyGuid.  How you configure that depends on the toolset.  If you’re using Active Directory Federation Services (AD FS) 2.0, 2.1, 3.0 or 3.1 (Win 10 Server preview) then the answer is here.

In summary, you change this issuance transform rule on the urn:federation:microsoftonline relying party (RP) trust:

c:[Type == “http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname”%5D => issue(store = “Active Directory”, types = ( “http://schemas.xmlsoap.org/claims/UPN”, “http://schemas.microsoft.com/LiveID/Federation/2008/05/ImmutableID”), query = “samAccountName={0};userPrincipalName,objectGUID;{1}”, param = regexreplace(c.Value, “(?[^\\]+)\\(?.+)”, “${user}”), param = c.Value);

To this:

c:[Type == “http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname”%5D => issue(store = “Active Directory”, types = ( “http://schemas.xmlsoap.org/claims/UPN”, “http://schemas.microsoft.com/LiveID/Federation/2008/05/ImmutableID”), query = “samAccountName={0};userPrincipalName,msDS-ConsistencyGuid;{1}”, param = regexreplace(c.Value, “(?[^\\]+)\\(?.+)”, “${user}”), param = c.Value);

What if I don’t want to use binary attributes?  I don’t like working in binary!  Strings are just easier!

That’s fine too.  Just make sure that the format used in sourceAnchor in FIM/AADSync and the value used in AD FS match, and remember this is case sensitive.  A good idea might be to Base64 encode your GUID or CS object GUID or New GUID and write it back to a string attribute.  Just make sure that the attribute you write it back to does not have the 0x10 (16) searchFlags defined in the AD DS schema.  That is, you do not want CP (fCopy), defined on your attributeSchema definition.

Hope this helps.