Jorge's Quest For Knowledge!

All About Identity And Security On-Premises And In The Cloud – It's Just Like An Addiction, The More You Have, The More You Want To Have!

Archive for the ‘Azure AD Join’ Category

(2019-10-12) Gradually Or Specifically Configuring Your Windows Machines For Hybrid Azure AD Join

Posted by Jorge on 2019-10-12


If you have read this blog post, at some point you will need to create a Service Connection Point (SCP), so that your clients know where to find the Azure AD Tenant those clients should register in. In that blog post, and that was the only possibility since the beginning, you create the SCP in the configuration partition of the AD forest.

If your AD forest had to be serviced by just a single Azure AD tenant, you were good to go. If not, you would have a problem.

If you wanted to have all your Windows clients register at at once in the Azure AD tenant you were good to go. If you wanted to deploy in a phased manner, you would have a problem!

Therefore if you need to deploy different Hybrid Azure AD Join settings to your Windows clients, and/or you need to deploy in a phased manner, you can provide the SCP settings in a GPO to configure the required REGISTRY settings.

Clear the SCP from AD

Use the Active Directory Services Interfaces Editor (ADSI Edit) to modify the SCP objects in AD.

  1. Launch the ADSI Edit desktop application from and administrative workstation or a domain controller as an Enterprise Administrator.
  2. Connect to the Configuration Naming Context of your domain.
  3. Browse to CN=Configuration,DC=contoso,DC=com > CN=Services > CN=Device Registration Configuration
  4. Right click on the leaf object under CN=Device Registration Configuration and select Properties
    1. Select keywords from the Attribute Editor window and click Edit
    2. Select the values of azureADId and azureADName (one at a time) and click Remove
  5. Close ADSI Edit

Configure client-side registry setting for SCP

Use the following example to create a Group Policy Object (GPO) to deploy a registry setting configuring an SCP entry in the registry of your devices.

  1. Open a Group Policy Management console and create a new Group Policy Object in your domain.
    1. Provide your newly created GPO a name (for example, ClientSideSCP).
  2. Edit the GPO and locate the following path: Computer Configuration > Preferences > Windows Settings > Registry
  3. Right-click on the Registry and select New > Registry Item
    1. On the General tab, configure the following
      1. Action: Update
      2. Hive: HKEY_LOCAL_MACHINE
      3. Key Path: SOFTWARE\Microsoft\Windows\CurrentVersion\CDJ\AAD
      4. Value name: TenantId
      5. Value type: REG_SZ
      6. Value data: The GUID or Directory ID of your Azure AD instance (This value can be found in the Azure portal > Azure Active Directory > Properties > Directory ID)
    2. Click OK
  4. Right-click on the Registry and select New > Registry Item
    1. On the General tab, configure the following
      1. Action: Update
      2. Hive: HKEY_LOCAL_MACHINE
      3. Key Path: SOFTWARE\Microsoft\Windows\CurrentVersion\CDJ\AAD
      4. Value name: TenantName
      5. Value type: REG_SZ
      6. Value data: Your verified domain name if you are using federated environment such as AD FS. Your verified domain name or your onmicrosoft.com domain name for example, contoso.onmicrosoft.com if you are using managed environment (in case of PHS or PTA as the primary Auth)
    2. Click OK
  5. Close the editor for the newly created GPO
  6. Link the newly created GPO to the desired OU containing domain-joined computers that belong to your controlled rollout population

PS: if you are using ADFS, that same GPO must ALSO target the ADFS Servers!

More information: Controlled validation of hybrid Azure AD join

Cheers,

Jorge

————————————————————————————————————————————————————-
This posting is provided "AS IS" with no warranties and confers no rights!
Always evaluate/test everything yourself first before using/implementing this in production!
This is today’s opinion/technology, it might be different tomorrow and will definitely be different in 10 years!
DISCLAIMER:
https://jorgequestforknowledge.wordpress.com/disclaimer/
————————————————————————————————————————————————————-
########################### Jorge’s Quest For Knowledge ##########################
####################
http://JorgeQuestForKnowledge.wordpress.com/ ###################
————————————————————————————————————————————————————-

Posted in Active Directory Domain Services (ADDS), ADSIEDIT, Azure AD Join, Windows Azure Active Directory, Windows Client, Windows Server | Leave a Comment »

(2019-10-08) Synched Computers/Devices Being Cleaned Up From Azure AD

Posted by Jorge on 2019-10-08


Starting with version 1.4.18.0 and higher of Azure AD Connect, you may see some or all of their Windows devices disappear from Azure AD after upgrade to that version and executing a sync cycle. This is not a cause for concern, as these device identities are not used by Azure AD during conditional access authorization. This change won’t delete any Windows devices that were correctly registered with Azure AD for Hybrid Azure AD Join.

If you see the deletion of device objects in Azure AD exceeding the Export Deletion Threshold, it is advised that the customer allow the deletions to go through. How To: allow deletes to flow when they exceed the deletion threshold

Nevertheless you may want to analyze the deletion first. You can read the following blog post to see how you could do that: (2019-10-06) Examining Pending Export Deletions In Azure AD Connect

More information about this can be found through Understanding Azure AD Connect 1.4.xx.x and device disappearance

To verify which devices in your AD are candidates to be deleted in Azure AD, you can use the following PowerShell script: Export Hybrid Azure AD join computer certificates report

This script generates a report about certificates stored in Active Directory Computer objects, specifically, certificates issued by the Hybrid Azure AD join feature. It checks the certificates present in the UserCertificate property of a Computer object in AD and, for each non-expired certificate present, validates if the certificate was issued for the Hybrid Azure AD join feature (i.e. Subject Name matches CN={ObjectGUID}). Before, Azure AD Connect would synchronize to Azure AD any Computer that contained at least one valid certificate but starting on Azure AD Connect version 1.4, the synchronization engine can identify Hybrid Azure AD join certificates and will ‘cloudfilter’ the computer object from synchronizing to Azure AD unless there’s a valid Hybrid Azure AD join certificate. Azure AD Devices that were already synchronized to AD but do not have a valid Hybrid Azure AD join certificate will be deleted by the sync engine as these will be filtered from being synched to Azure AD (CloudFiltered=TRUE).

Now this script works great! But….unfortunately it does not work correctly with an AD forest where you may have multiple AD domains. Besides that, there is a cosmetic issue. So, let’s start with the easy part!

The script allows you to specify the distinguished name of a single object or the distinguished name of an OU. However, if you want to query the complete AD domain instead of just a single OU, you may think that’s not possible. Nope, that’s still possible. The original writer of the script chose to name the variable “DN” for just a single object (computer) and “OU” when query for computers in an OU. This last one may mislead due to its chosen name. Nevertheless, instead of the DN of an OU, you can also specify the DN of a container or the DN of a domain.

In a single AD domain environment, this will work flawlessly. However, in a multiple AD domain environment it may not. Due to historic reasons many companies may still have AD forests with multiple AD domains for which it is not cost effective to consolidate. For example, if you have the AD forest COMPANY.COM, with the following AD domains: COMPANY.COM, CHILD1.COMPANY.COM and CHILD2.COMPANY.COM. If you are COMPANY.COM and you need to query for objects in CHILD1.COMPANY.COM through PowerShell while not specifying the server variable (as in this script), it will throw an error due to a so called redirection. To query for an object from another AD domain you need to also target a DC from that same AD domain. If you need to query multiple AD domains you will be dancing all over the place! Sometimes, there is no other way, but in this case there is! And what if you want to query the complete AD forest while having multiple AD domains? You can always query every individual AD domain, but wouldn’t it be nice to just perform a single AD query that targets the complete AD forest? That is also possible!

When querying AD, especially when having an AD forest with multiple AD domains you always need to think about: (1) is all the data in my LDAP filter in the global catalog or not?, and (2) is the data that I’m looking for in the global catalog?

Then you need to ask yourself: “where to start searching?”. The closer to the objects you want, the better!

Rest assured! All domains objects are in the global catalog! The question is: “which attribute values of those objects are also replicated to the global catalog?”

Any attribute that has the property “isMemberOfPartialAttributeSet” set to “TRUE” also replicates its value(s) to all global catalogs in the AD forest. To find all the attributes in the AD schema for which its value(s) replicate to the global catalog, you can have a look at the following blog post (2015-01-05) Finding Attributes Marked As Members Of Partial Attribute Set (PAS). It has examples with ADFIND, PowerShell and ADSI.

Now looking at this script, the attribute of interest is “userCertificate”.

To see if an attribute value replicates to the global catalog, you can use:

Get-ADObject -SearchBase $((Get-ADRootDSE).schemaNamingContext) -LDAPFilter "(&(objectClass=attributeSchema)(lDAPDisplayName=<LDAP DisplayName>))" –Property lDAPDisplayName,isMemberOfPartialAttributeSet

To see if the “userCertificate” attribute value replicates to the global catalog, you can use:

Get-ADObject -SearchBase $((Get-ADRootDSE).schemaNamingContext) -LDAPFilter "(&(objectClass=attributeSchema)(lDAPDisplayName=userCertificate))" –Property lDAPDisplayName,isMemberOfPartialAttributeSet

image

Figure 1: Partial Schema Info Of The “userCertificate” Attribute

Or you could visit https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-ada3/f9e923d6-c512-4beb-b963-afd695cea8ac, which will show you

image

Figure 2: AD Schema Definition Of The “userCertificate” Attribute

Guess what?! It does replicate to the global catalog! So, in this case the answer to both questions above is “YES”, therefore we can use the global catalog to perform this query

When you need to query the AD forest, you could start searching in the forest root AD domain and hopefully the client you are using supports Referral Chasing. If it does not, it may throw an error telling you it does not support it, or it just does not do anything. Wouldn’t it be nice to have something represent the AD forest? well, there is something like that, which is called a Phantom Root and it is specified by just 2 quotes and you can only use it when querying against the Global Catalog!

Now for all this to work, some adjustments are needed in the original script! I’ll guide you through that to get a new working script.

First things first. Download the PowerShell script: Export Hybrid Azure AD join computer certificates report 

Replace…

.EXAMPLE
   .\Export-ADSyncToolsHybridAzureADjoinCertificateReport.ps1 -DN ‘CN=Computer1,OU=SYNC,DC=Fabrikam,DC=com’
.EXAMPLE
   .\Export-ADSyncToolsHybridAzureADjoinCertificateReport.ps1 -OU ‘OU=SYNC,DC=Fabrikam,DC=com’ -Filename "MyHybridAzureADjoinReport.csv" -Verbose

…with

.EXAMPLE
    Looking at a specific computer

   .\Export-ADSyncToolsHybridAzureADjoinCertificateReport.ps1 -DN ‘CN=Computer1,OU=SYNC,DC=Fabrikam,DC=com’
.EXAMPLE
    Looking at computer objects within a specific OU
   
   .\Export-ADSyncToolsHybridAzureADjoinCertificateReport.ps1 -DN ‘OU=SYNC,DC=Fabrikam,DC=com’ -Filename "MyHybridAzureADjoinReport.csv" -Verbose
.EXAMPLE
    Looking at computer objects within a specific AD domain
   
   .\Export-ADSyncToolsHybridAzureADjoinCertificateReport.ps1 -DN ‘DC=child,DC=Fabrikam,DC=com’ -Filename "MyHybridAzureADjoinReport.csv" -Verbose
.EXAMPLE
    Looking at computer objects within a specific AD forest
   
   .\Export-ADSyncToolsHybridAzureADjoinCertificateReport.ps1 -DN PhantomRoot -Filename "MyHybridAzureADjoinReport.csv" -Verbose

Replace…

Param
(
    # Computer DistinguishedName
    [Parameter(ParameterSetName=’SingleObject’,
               Mandatory=$true,
                ValueFromPipelineByPropertyName=$true,
               Position=0)]
    [String]
    $DN,

    # AD OrganizationalUnit
    [Parameter(ParameterSetName=’MultipleObjects’,
               Mandatory=$true,
               ValueFromPipelineByPropertyName=$true,
               Position=0)]
    [String]
    $OU,

    # Output CSV filename (optional)
    [Parameter(Mandatory=$false,
                ValueFromPipelineByPropertyName=$false,
               Position=1)]
    [String]
    $Filename

)

…with

Param
(
    # DistinguishedName of computer, OU, or domain
    [Parameter(Mandatory=$true,
               ValueFromPipelineByPropertyName=$true,
               Position=0)]
    [String]
    $DN,

    # Output CSV filename (optional)
    [Parameter(Mandatory=$false,
                ValueFromPipelineByPropertyName=$false,
               Position=1)]
    [String]
    $Filename
)

Replace…

# Read AD object(s)
If ($PSCmdlet.ParameterSetName -eq ‘SingleObject’)
{
    $directoryObjs = @(Get-ADObject $DN -Properties UserCertificate)
     Write-Verbose "Starting report for a single object ‘$DN’"
}
Else
{
    $directoryObjs = Get-ADObject -Filter { ObjectClass -like ‘computer’ } -SearchBase $OU -Properties UserCertificate
    Write-Verbose "Starting report for $($directoryObjs.Count) computer objects in OU ‘$OU’"
}

…with

# Retrieve Object Type Of DN
If ($DN -ne "PhantomRoot")
{
    $objectType = (Get-ADObject -LDAPFilter "(distinguishedname=$DN)").objectClass # Do not use Get-ADObject $DN as it will throw an error if the object does not exist (even with ErrorAction defined)!
}
Else
{
    $objectType = "forestDNS" # Madeup, not for real!
    $DN = ""
}

   
# Read AD object(s)
If ($objectType -eq "computer")
{
    $domainFQDN = $($DN.SubString($DN.IndexOf(",DC=") + 1)).Replace(",DC=",".").Replace("DC=","")
    $directoryObjs = @(Get-ADObject $DN -Properties userCertificate -Server $domainFQDN)
}
ElseIf ($objectType -eq "domainDNS" -Or $objectType -eq "organizationalUnit" -Or $objectType -eq "container" -Or $objectType -eq "forestDNS")
{
    $gcFQDN = $(Get-ADDomainController -Discover -Service GlobalCatalog).HostName[0]
    $directoryObjs = Get-ADObject -Filter { ObjectClass -like ‘computer’ } -SearchBase $DN -Properties userCertificate -Server $gcFQDN`:3268
}
Else{
    Write-Host "Specified DN ‘$DN’" -Foregroundcolor Red
    Write-Host "Incorrect object type of specified DN or DN does not exist!" -Foregroundcolor Red
    Write-Host "Aborting Script…" -Foregroundcolor Red
   
    EXIT
}

UPDATE 2019-10-12: or get the updated version of the script from here

Hopefully this works for you in your AD environment!

Cheers,

Jorge

————————————————————————————————————————————————————-
This posting is provided "AS IS" with no warranties and confers no rights!
Always evaluate/test everything yourself first before using/implementing this in production!
This is today’s opinion/technology, it might be different tomorrow and will definitely be different in 10 years!
DISCLAIMER:
https://jorgequestforknowledge.wordpress.com/disclaimer/
————————————————————————————————————————————————————-
########################### Jorge’s Quest For Knowledge ##########################
####################
http://JorgeQuestForKnowledge.wordpress.com/ ###################
————————————————————————————————————————————————————-

Posted in Active Directory Users And Computers, AD Queries, Azure AD Connect, Azure AD Join, Conditional Access, Windows Azure Active Directory, Windows Client, Windows Server | Leave a Comment »

(2018-10-22) Cloning Windows 10 Or Windows Server 2016 May Break Hybrid Azure AD Domain Join

Posted by Jorge on 2018-10-22


When cloning Windows computers you are basically copying everything from some source computer to one or more target computers. One of the benefits is the speed in deployment and the time you same to have to configure stuff every single time. Are there downsides? Yes, there are, at least if you do not take some risk mitigating measures. One of those is the SID of the local computer. Every time you deploy a cloned version of Windows you MUST execute SYSPREP to make the clone gets its own unique SID. If you don’t at the beginning and along the way things may appear to be correct. However, at some point in time you may find yourself with a huge headache trying to understand why something does not work or shows weird behavior.

Recently I found another downside of cloning, that in the end can be mitigated with some post-deployment actions.

For more info about Hybrid Azure AD Domain Join (HAADJ) please also have a look at

I was trying to Hybrid Azure AD Domain Join (HAADJ) a AD domain joined Windows Server 2016 by logging on and waiting for the scheduled task to kick in and checking the correct Event Logs, and later on under the context of “NT AUTHORITY\SYSTEM” by running DSREGCMD.EXE /DEBUG. When running that last command I kept seeing the following error at the end:

DsrDeviceAutoJoinFederated failed with -2146893802
wmain: failed with error code 0x80090016.

After some troubleshooting I discovered that Windows was a cloned deployment. One of the thing that is also cloned is the key material. The key material is in the folder “C:\ProgramData\Microsoft\Crypto\Keys” to “C:\ProgramData\Microsoft\Crypto\Keys”. The solution therefore is to get rid of the old key material and start fresh from the beginning. You can do that by running the following PowerShell commands:

# Rename The “Keys” Folder To “KeysOLD”

Rename-Item -Path "C:\ProgramData\Microsoft\Crypto\Keys" -NewName "KeysOLD"

# Create A New “Keys” Folder

New-Item -Path "C:\ProgramData\Microsoft\Crypto\Keys" -ItemType Directory

# Copy The ACL From The “KeysOLD” Folder To The New “Keys” Folder

Get-Acl -Path "C:\ProgramData\Microsoft\Crypto\KeysOLD" | Set-Acl -Path "C:\ProgramData\Microsoft\Crypto\Keys"

Now retry HAADJ by rebooting the Windows computers and logging on, or executing DSREGCMD.EXE /DEBUG under the context of  “NT AUTHORITY\SYSTEM”. It should work now!

REMARK: If you did not know it yet, you can get into the context of “NT AUTHORITY\SYSTEM” by using PSEXEC and running the following command: PSEXEC –i –s CMD.EXE

Cheers,
Jorge

————————————————————————————————————————————————————-
This posting is provided "AS IS" with no warranties and confers no rights!
Always evaluate/test everything yourself first before using/implementing this in production!
This is today’s opinion/technology, it might be different tomorrow and will definitely be different in 10 years!
DISCLAIMER:
https://jorgequestforknowledge.wordpress.com/disclaimer/
————————————————————————————————————————————————————-
########################### Jorge’s Quest For Knowledge ##########################
####################
http://JorgeQuestForKnowledge.wordpress.com/ ###################
————————————————————————————————————————————————————-

Posted in Azure AD Join, Windows Azure Active Directory, Windows Client, Windows Server | 3 Comments »

(2017-09-07) Claims Rules Set For Your AAD/O365 RP Trust To Support User And Device Authentication

Posted by Jorge on 2017-09-07


On the page “How to configure hybrid Azure Active Directory joined devices” Microsoft explains how to setup Domain Join ++, currently a.k.a. Hybrid AAD Join. This post is about, hopefully giving additional, clarification on how to setup the claims rules in ADFS. All the scenarios listed below work, it just on your scenario. Feel free to leave any comments if unclear. The import of the rules below should replace your current rules for the AAD RP Trust, and where applicable add rules to your AD CP trust. A final note, is that these rule sets are based upon Microsoft’s rule in the previous article.

Make sure to test this first in your test environment!

You may also want to have a look at the following blog post:

(2016-12-16) Automatic Azure AD Join With ADFS v3.0 And Higher And Conditional Access – What You Really Need In Detail

[OPTION 1]

The following works if you have claims rules in place on the AD CP trust that output the following claim types. This is true if you are using the default claim rule set in ADFSv3/ADFSv4:

Assumptions here:

  • You have one ADFS environment servicing all the federated domains in AAD
  • The federation identifier being used on your federated domains in AAD is default
  • The primary group was not changed for any user or any computer
  • The objectGUID is the attribute being used for the Immutable ID for users
  • The objectGUID is the attribute being used for the Immutable ID for computers
  • On-premises UPN is also the UPN used in AAD
  • Whether or not you have multiple federated domains, the config below for the IssuerID for users works as long as the UPN of the user matches one of the federated domains in AAD
  • You will replace FEDERATED-DOMAIN with one of the federated domains in AAD. It does not matter which one
  • You will replace NAME-OF-AAD/O365-RP-TRUST with the actual name of the RP trust for AAD/O365

Remarks:

  • Leave a comment if you have any deviation of the assumptions above

Thoughts here:

  • It is making multiple LDAP calls to AD, and is therefore not that optimized. It works though!
  • Still using groupsid claim type

Link to claims rules below: https://www.dropbox.com/s/vgzvnwhku2adp39/AzureAD-RP-Trust-Issuance-Rules1.txt

$aadRPTrustIssuanceRules = @"

@RuleName = "Issue UPN And ImmutableID (Domain User Only)"

c1:[Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/groupsid&quot;, Value =~ "-513$", Issuer =~ "^(AD AUTHORITY|SELF AUTHORITY|LOCAL AUTHORITY)$"] &&

c2:[Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname"%5D

=> issue(store = "Active Directory", types = ("http://schemas.xmlsoap.org/claims/UPN&quot;, "http://schemas.microsoft.com/LiveID/Federation/2008/05/ImmutableID&quot;), query = ";userPrincipalName,objectGUID;{0}", param = c2.Value);

@RuleName = "Issue IssuerID (Domain User Only)"

c:[Type == "http://schemas.xmlsoap.org/claims/UPN"%5D

=> issue(Type = "http://schemas.microsoft.com/ws/2008/06/identity/claims/issuerid&quot;, Value = regexreplace(c.Value, ".+@(?<domain>.+)", http://${domain}/adfs/services/trust/));

@RuleName = "Issue ImmutableID (Domain Joined Computer Only)"

c1:[Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/groupsid&quot;, Value =~ "-515$", Issuer =~ "^(AD AUTHORITY|SELF AUTHORITY|LOCAL AUTHORITY)$"] &&

c2:[Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname&quot;, Issuer =~ "^(AD AUTHORITY|SELF AUTHORITY|LOCAL AUTHORITY)$"]

=> issue(store = "Active Directory", types = ("http://schemas.microsoft.com/LiveID/Federation/2008/05/ImmutableID&quot;), query = ";objectguid;{0}", param = c2.Value);

@RuleName = "Issue Account Type (Domain Joined Computer Only)"

c:[Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/groupsid&quot;, Value =~ "-515$", Issuer =~ "^(AD AUTHORITY|SELF AUTHORITY|LOCAL AUTHORITY)$"]

=> issue(Type = "http://schemas.microsoft.com/ws/2012/01/accounttype&quot;, Value = "DJ");

@RuleName = "Issue ObjectGUID (Domain Joined Computer Only)"

c1:[Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/groupsid&quot;, Value =~ "-515$", Issuer =~ "^(AD AUTHORITY|SELF AUTHORITY|LOCAL AUTHORITY)$"] &&

c2:[Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname&quot;, Issuer =~ "^(AD AUTHORITY|SELF AUTHORITY|LOCAL AUTHORITY)$"]

=> issue(store = "Active Directory", types = ("http://schemas.microsoft.com/identity/claims/onpremobjectguid&quot;), query = ";objectguid;{0}", param = c2.Value);

@RuleName = "Issue ObjectSID (Domain Joined Computer Only)"

c1:[Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/groupsid&quot;, Value =~ "-515$", Issuer =~ "^(AD AUTHORITY|SELF AUTHORITY|LOCAL AUTHORITY)$"] &&

c2:[Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/primarysid&quot;, Issuer =~ "^(AD AUTHORITY|SELF AUTHORITY|LOCAL AUTHORITY)$"]

=> issue(claim = c2);

@RuleName = "Issue IssuerID (Domain Joined Computer Only)"

c:[Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/groupsid&quot;, Value =~ "-515$", Issuer =~ "^(AD AUTHORITY|SELF AUTHORITY|LOCAL AUTHORITY)$"]

=> issue(Type = "http://schemas.microsoft.com/ws/2008/06/identity/claims/issuerid&quot;, Value = http://FEDERATED-DOMAIN/adfs/services/trust/);

@RuleName = "Issue NameID (Domain User and Domain Joined Computer)"

c:[Type == "http://schemas.microsoft.com/LiveID/Federation/2008/05/ImmutableID"%5D

=> issue(Type = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier&quot;, Value = c.Value, Properties["http://schemas.xmlsoap.org/ws/2005/05/identity/claimproperties/format"%5D = "urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified");

@RuleName = "Issue AuthN Methods References (Domain User and Domain Joined Computer)"

c:[Type == "http://schemas.microsoft.com/claims/authnmethodsreferences"%5D

=> issue(claim = c);

"@

Set-AdfsRelyingPartyTrust -TargetName "NAME-OF-AAD/O365-RP-TRUST" -IssuanceTransformRules $aadRPTrustIssuanceRules

[OPTION 2]

The following works if you have claims rules in place on the AD CP trust that output the following claim types. This is true if you are using the default claim rule set in ADFSv3/ADFSv4:

Assumptions here:

  • You have one ADFS environment servicing all the federated domains in AAD
  • The federation identifier being used on your federated domains in AAD is default
  • The primary group was not changed for any user or any computer
  • The objectGUID is the attribute being used for the Immutable ID for users
  • The objectGUID is the attribute being used for the Immutable ID for computers
  • On-premises UPN is also the UPN used in AAD
  • Whether or not you have multiple federated domains, the config below for the IssuerID for users works as long as the UPN of the user matches one of the federated domains in AAD
  • You will replace FEDERATED-DOMAIN with one of the federated domains in AAD. It does not matter which one
  • You will replace NAME-OF-AAD/O365-RP-TRUST with the actual name of the RP trust for AAD/O365

Remarks:

  • Leave a comment if you have any deviation of the assumptions above

Thoughts here:

  • Although a few LDAP calls less, it is still making LDAP calls to AD. It works though!
  • Still using groupsid claim type

Link to claims rules below: https://www.dropbox.com/s/udn1rudm5bgv7jq/AzureAD-RP-Trust-Issuance-Rules2.txt

$aadRPTrustIssuanceRules = @"

@RuleName = "Issue UPN (Domain User Only)"

c1:[Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/groupsid&quot;, Value =~ "-513$", Issuer =~ "^(AD AUTHORITY|SELF AUTHORITY|LOCAL AUTHORITY)$"] &&

c2:[Type == "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn"%5D

=> issue(Type = "http://schemas.xmlsoap.org/claims/UPN&quot;, Issuer = c2.Issuer, OriginalIssuer = c2.OriginalIssuer, Value = c2.Value, ValueType = c2.ValueType);

@RuleName = "Issue IssuerID (Domain User Only)"

c:[Type == "http://schemas.xmlsoap.org/claims/UPN"%5D

=> issue(Type = "http://schemas.microsoft.com/ws/2008/06/identity/claims/issuerid&quot;, Value = regexreplace(c.Value, ".+@(?<domain>.+)", http://${domain}/adfs/services/trust/));

@RuleName = "Issue Account Type (Domain Joined Computer Only)"

c:[Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/groupsid&quot;, Value =~ "-515$", Issuer =~ "^(AD AUTHORITY|SELF AUTHORITY|LOCAL AUTHORITY)$"]

=> issue(Type = "http://schemas.microsoft.com/ws/2012/01/accounttype&quot;, Value = "DJ");

@RuleName = "Issue ObjectGUID (Domain Joined Computer Only)"

c1:[Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/groupsid&quot;, Value =~ "-515$", Issuer =~ "^(AD AUTHORITY|SELF AUTHORITY|LOCAL AUTHORITY)$"] &&

c2:[Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname&quot;, Issuer =~ "^(AD AUTHORITY|SELF AUTHORITY|LOCAL AUTHORITY)$"]

=> issue(store = "Active Directory", types = ("http://schemas.microsoft.com/identity/claims/onpremobjectguid&quot;), query = ";objectguid;{0}", param = c2.Value);

@RuleName = "Issue ObjectSID (Domain Joined Computer Only)"

c1:[Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/groupsid&quot;, Value =~ "-515$", Issuer =~ "^(AD AUTHORITY|SELF AUTHORITY|LOCAL AUTHORITY)$"] &&

c2:[Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/primarysid&quot;, Issuer =~ "^(AD AUTHORITY|SELF AUTHORITY|LOCAL AUTHORITY)$"]

=> issue(claim = c2);

@RuleName = "Issue IssuerID (Domain Joined Computer Only)"

c:[Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/groupsid&quot;, Value =~ "-515$", Issuer =~ "^(AD AUTHORITY|SELF AUTHORITY|LOCAL AUTHORITY)$"]

=> issue(Type = "http://schemas.microsoft.com/ws/2008/06/identity/claims/issuerid&quot;, Value = http://FEDERATED-DOMAIN/adfs/services/trust/);

@RuleName = "ImmutableID (Domain User And Domain Joined Computer)"

c:[Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname"%5D

=> issue(store = "Active Directory", types = ("http://schemas.microsoft.com/LiveID/Federation/2008/05/ImmutableID&quot;), query = ";objectGUID;{0}", param = c.Value);

@RuleName = "Issue NameID (Domain User and Domain Joined Computer)"

c:[Type == "http://schemas.microsoft.com/LiveID/Federation/2008/05/ImmutableID"%5D

=> issue(Type = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier&quot;, Value = c.Value, Properties["http://schemas.xmlsoap.org/ws/2005/05/identity/claimproperties/format"%5D = "urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified");

@RuleName = "Issue AuthN Methods References (Domain User and Domain Joined Computer)"

c:[Type == "http://schemas.microsoft.com/claims/authnmethodsreferences"%5D

=> issue(claim = c);

"@

Set-AdfsRelyingPartyTrust -TargetName "NAME-OF-AAD/O365-RP-TRUST" -IssuanceTransformRules $aadRPTrustIssuanceRules

[OPTION 3]

The following works if you have claims rules in place on the AD CP trust that output the following claim types. This is true if you are using the default claim rule set in ADFSv3/ADFSv4:

For the last claim type you would need the following claim rule on the AD CP trust if you are not already extracting additional data from AD

$additionalADCPTrustRule = @"
@RuleTemplate = "LdapClaims"
@RuleName = "Extract Extra Data From AD"
c:[Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname&quot;, Issuer == "AD AUTHORITY"]
  => issue(store = "Active Directory", types = ("http://temp.org/identity/claims/objectGUID&quot;), query = ";objectguid;{0}", param = c.Value);
"@

$existingADCPtrustAcceptRuleSet = (Get-AdfsClaimsProviderTrust -Name "Active Directory").AcceptanceTransformRules

$newADCPtrustAcceptRuleSet = $existingADCPtrustAcceptRuleSet + $additionalADCPTrustRule

Set-AdfsClaimsProviderTrust -TargetName "Active Directory" -AcceptanceTransformRules $newADCPtrustAcceptRuleSet

If you are already extracting additional data from AD, you need to add the claim type and attribute to that existing extraction

Assumptions here:

  • You have one ADFS environment servicing all the federated domains in AAD
  • The federation identifier being used on your federated domains in AAD is default
  • The primary group was not changed for any user or any computer
  • The objectGUID is the attribute being used for the Immutable ID for users
  • The objectGUID is the attribute being used for the Immutable ID for computers
  • On-premises UPN is also the UPN used in AAD
  • Whether or not you have multiple federated domains, the config below for the IssuerID for users works as long as the UPN of the user matches one of the federated domains in AAD
  • You will replace FEDERATED-DOMAIN with one of the federated domains in AAD. It does not matter which one
  • You will replace NAME-OF-AAD/O365-RP-TRUST with the actual name of the RP trust for AAD/O365

Remarks:

  • Leave a comment if you have any deviation of the assumptions above

Thoughts here:

  • No LDAP calls!
  • Still using groupsid claim type

Link to claims rules below: https://www.dropbox.com/s/8cicjpyusapsarj/AzureAD-RP-Trust-Issuance-Rules3.txt

$aadRPTrustIssuanceRules = @"

@RuleName = "Issue UPN (Domain User Only)"

c1:[Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/groupsid&quot;, Value =~ "-513$", Issuer =~ "^(AD AUTHORITY|SELF AUTHORITY|LOCAL AUTHORITY)$"] &&

c2:[Type == "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn"%5D

=> issue(Type = "http://schemas.xmlsoap.org/claims/UPN&quot;, Issuer = c2.Issuer, OriginalIssuer = c2.OriginalIssuer, Value = c2.Value, ValueType = c2.ValueType);

@RuleName = "Issue IssuerID (Domain User Only)"

c:[Type == "http://schemas.xmlsoap.org/claims/UPN"%5D

=> issue(Type = "http://schemas.microsoft.com/ws/2008/06/identity/claims/issuerid&quot;, Value = regexreplace(c.Value, ".+@(?<domain>.+)", http://${domain}/adfs/services/trust/));

@RuleName = "Issue Account Type (Domain Joined Computer Only)"

c:[Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/groupsid&quot;, Value =~ "-515$", Issuer =~ "^(AD AUTHORITY|SELF AUTHORITY|LOCAL AUTHORITY)$"]

=> issue(Type = "http://schemas.microsoft.com/ws/2012/01/accounttype&quot;, Value = "DJ");

@RuleName = "Issue ObjectGUID (Domain Joined Computer Only)"

c1:[Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/groupsid&quot;, Value =~ "-515$", Issuer =~ "^(AD AUTHORITY|SELF AUTHORITY|LOCAL AUTHORITY)$"] &&

c2:[Type == "http://temp.org/identity/claims/objectGUID"%5D

=> issue(Type = "http://schemas.microsoft.com/identity/claims/onpremobjectguid&quot;, Issuer = c2.Issuer, OriginalIssuer = c2.OriginalIssuer, Value = c2.Value, ValueType = c2.ValueType);

@RuleName = "Issue ObjectSID (Domain Joined Computer Only)"

c1:[Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/groupsid&quot;, Value =~ "-515$", Issuer =~ "^(AD AUTHORITY|SELF AUTHORITY|LOCAL AUTHORITY)$"] &&

c2:[Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/primarysid&quot;, Issuer =~ "^(AD AUTHORITY|SELF AUTHORITY|LOCAL AUTHORITY)$"]

=> issue(claim = c2);

@RuleName = "Issue IssuerID (Domain Joined Computer Only)"

c:[Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/groupsid&quot;, Value =~ "-515$", Issuer =~ "^(AD AUTHORITY|SELF AUTHORITY|LOCAL AUTHORITY)$"]

=> issue(Type = "http://schemas.microsoft.com/ws/2008/06/identity/claims/issuerid&quot;, Value = http://FEDERATED-DOMAIN/adfs/services/trust/);

@RuleName = "ImmutableID (Domain User And Domain Joined Computer)"

c:[Type == "http://temp.org/identity/claims/objectGUID"%5D

=> issue(Type = "http://schemas.microsoft.com/LiveID/Federation/2008/05/ImmutableID&quot;, Issuer = c.Issuer, OriginalIssuer = c.OriginalIssuer, Value = c.Value, ValueType = c.ValueType);

@RuleName = "Issue NameID (Domain User and Domain Joined Computer)"

c:[Type == "http://schemas.microsoft.com/LiveID/Federation/2008/05/ImmutableID"%5D

=> issue(Type = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier&quot;, Value = c.Value, Properties["http://schemas.xmlsoap.org/ws/2005/05/identity/claimproperties/format"%5D = "urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified");

@RuleName = "Issue AuthN Methods References (Domain User and Domain Joined Computer)"

c:[Type == "http://schemas.microsoft.com/claims/authnmethodsreferences"%5D

=> issue(claim = c);

"@

Set-AdfsRelyingPartyTrust -TargetName "NAME-OF-AAD/O365-RP-TRUST" -IssuanceTransformRules $aadRPTrustIssuanceRules

[OPTION 4]

The following works if you have claims rules in place on the AD CP trust that output the following claim types.  This is true if you are using the default claim rule set in ADFSv3/ADFSv4 for the first 2 claim types, but not for the last 2 claim types. My main reason for not using groupsid is that the amount of values can be so huge it may not fit on a cookie and the browser chokes. Because of that, when not using the groupsid claim type, you need to design a better model to extract group data from AD and use authorization based claims types from that data. If you are not using the groupsid claim type you can also not identify the difference between a user and a computer. That’s why you can then specifically extract the primaryGroupID.:

For the last 2 claim types you would need the following claim rule on the AD CP trust if you are not already extracting additional data from AD

$additionalADCPTrustRule = @"
@RuleTemplate = "LdapClaims"
@RuleName = "Extract Extra Data From AD"
c:[Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname&quot;, Issuer == "AD AUTHORITY"]
  => issue(store = "Active Directory", types = ("http://temp.org/identity/claims/objectGUID&quot;,"http://temp.org/identity/claims/primaryGroupID&quot;), query = ";objectguid,primaryGroupID;{0}", param = c.Value);
"@

$existingADCPtrustAcceptRuleSet = (Get-AdfsClaimsProviderTrust -Name "Active Directory").AcceptanceTransformRules

$newADCPtrustAcceptRuleSet = $existingADCPtrustAcceptRuleSet + $additionalADCPTrustRule

Set-AdfsClaimsProviderTrust -TargetName "Active Directory" -AcceptanceTransformRules $newADCPtrustAcceptRuleSet

If you are already extracting additional data from AD, you need to add the claim type and attribute to that existing extraction

Assumptions here:

  • You have one ADFS environment servicing all the federated domains in AAD
  • The federation identifier being used on your federated domains in AAD is default
  • The primary group was not changed for any user or any computer
  • The objectGUID is the attribute being used for the Immutable ID for users
  • The objectGUID is the attribute being used for the Immutable ID for computers
  • On-premises UPN is also the UPN used in AAD
  • Whether or not you have multiple federated domains, the config below for the IssuerID for users works as long as the UPN of the user matches one of the federated domains in AAD
  • You will replace FEDERATED-DOMAIN with one of the federated domains in AAD. It does not matter which one
  • You will replace NAME-OF-AAD/O365-RP-TRUST with the actual name of the RP trust for AAD/O365

Remarks:

  • Leave a comment if you have any deviation of the assumptions above

Thoughts here:

  • No LDAP calls!
  • No groupsid claim type!

Link to claims rules below: https://www.dropbox.com/s/6nbwuuxl677wb3p/AzureAD-RP-Trust-Issuance-Rules4.txt

$aadRPTrustIssuanceRules = @"

@RuleName = "Issue UPN (Domain User Only)"

c1:[Type == "http://temp.org/identity/claims/primaryGroupID&quot;, Value =~ "^513$"] &&

c2:[Type == "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn"%5D

=> issue(Type = "http://schemas.xmlsoap.org/claims/UPN&quot;, Issuer = c2.Issuer, OriginalIssuer = c2.OriginalIssuer, Value = c2.Value, ValueType = c2.ValueType);

@RuleName = "Issue IssuerID (Domain User Only)"

c:[Type == "http://schemas.xmlsoap.org/claims/UPN"%5D

=> issue(Type = "http://schemas.microsoft.com/ws/2008/06/identity/claims/issuerid&quot;, Value = regexreplace(c.Value, ".+@(?<domain>.+)", http://${domain}/adfs/services/trust/));

@RuleName = "Issue Account Type (Domain Joined Computer Only)"

c:[Type == "http://temp.org/identity/claims/primaryGroupID&quot;, Value =~ "^515$"]

=> issue(Type = "http://schemas.microsoft.com/ws/2012/01/accounttype&quot;, Value = "DJ");

@RuleName = "Issue ObjectGUID (Domain Joined Computer Only)"

c1:[Type == "http://temp.org/identity/claims/primaryGroupID&quot;, Value =~ "^515$"] &&

c2:[Type == "http://temp.org/identity/claims/objectGUID"%5D

=> issue(Type = "http://schemas.microsoft.com/identity/claims/onpremobjectguid&quot;, Issuer = c2.Issuer, OriginalIssuer = c2.OriginalIssuer, Value = c2.Value, ValueType = c2.ValueType);

@RuleName = "Issue ObjectSID (Domain Joined Computer Only)"

c1:[Type == "http://temp.org/identity/claims/primaryGroupID&quot;, Value =~ "^515$"] &&

c2:[Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/primarysid&quot;, Issuer =~ "^(AD AUTHORITY|SELF AUTHORITY|LOCAL AUTHORITY)$"]

=> issue(claim = c2);

@RuleName = "Issue IssuerID (Domain Joined Computer Only)"

c:[Type == "http://temp.org/identity/claims/primaryGroupID&quot;, Value =~ "^515$"]

=> issue(Type = "http://schemas.microsoft.com/ws/2008/06/identity/claims/issuerid&quot;, Value = http://FEDERATED-DOMAIN/adfs/services/trust/);

@RuleName = "ImmutableID (Domain User And Domain Joined Computer)"

c:[Type == "http://temp.org/identity/claims/objectGUID"%5D

=> issue(Type = "http://schemas.microsoft.com/LiveID/Federation/2008/05/ImmutableID&quot;, Issuer = c.Issuer, OriginalIssuer = c.OriginalIssuer, Value = c.Value, ValueType = c.ValueType);

@RuleName = "Issue NameID (Domain User and Domain Joined Computer)"

c:[Type == "http://schemas.microsoft.com/LiveID/Federation/2008/05/ImmutableID"%5D

=> issue(Type = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier&quot;, Value = c.Value, Properties["http://schemas.xmlsoap.org/ws/2005/05/identity/claimproperties/format"%5D = "urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified");

@RuleName = "Issue AuthN Methods References (Domain User and Domain Joined Computer)"

c:[Type == "http://schemas.microsoft.com/claims/authnmethodsreferences"%5D

=> issue(claim = c);

"@

Set-AdfsRelyingPartyTrust -TargetName "NAME-OF-AAD/O365-RP-TRUST" -IssuanceTransformRules $aadRPTrustIssuanceRules

Hopefully this blog post gives you the information you need to understand what is needed

Cheers,
Jorge

————————————————————————————————————————————————————-
This posting is provided "AS IS" with no warranties and confers no rights!
Always evaluate/test everything yourself first before using/implementing this in production!
This is today’s opinion/technology, it might be different tomorrow and will definitely be different in 10 years!
DISCLAIMER:
https://jorgequestforknowledge.wordpress.com/disclaimer/
————————————————————————————————————————————————————-
########################### Jorge’s Quest For Knowledge ##########################
####################
http://JorgeQuestForKnowledge.wordpress.com/ ###################
————————————————————————————————————————————————————-

Posted in Active Directory Federation Services (ADFS), Azure AD / Office 365, Azure AD Join, Claim Types, Claims, Claims Rule Language, Windows Azure Active Directory | 2 Comments »

(2016-12-28) Joining Devices To Azure AD – The Options And The Differences

Posted by Jorge on 2016-12-28


This blog post is about joining/registering devices to Azure and the differences between them.

The following types of relations exist between a device and Azure AD:

[A] “AD Domain Join” + “Auto Registration for AAD” (a.k.a. just AAD Domain Join):

This is the traditional way of joining a computer to an AD domain. If auto registration for AAD has been configured in the AD domain for Windows computers, then Win7/8.1/10 devices will also register in AAD automatically. The way how this is done differs for the windows versions. The device is managed through GPOs and/or SCCM on-premises.

In AAD the status of the device is:

  • DeviceTrustType = Domain Joined”
  • “DeviceTrustLevel = Managed”.

Due to the trust type “Domain Joined”, the device would be able to access resources configured with conditional access. If you computer joined to your AD domain, then you should use this option. You can read more about it in the following blog post (2016-12-16) Automatic Azure AD Join With ADFS v3.0 And Higher And Conditional Access – What You Really Need In Detail.

[B] “Azure AD Join”:

This setting is the online version of joining a device to an AD domain. Instead of joining the device to the AD domain, the device is joined directory to the AAD tenant. It is the new way of setting up work devices for work (e.g. Windows 10 laptop) and using Azure AD as your online directory directly. When configured accordingly, it is possible to disallow Azure AD join to any user, allow it for specific people/groups or allow it for every user (self-service). When configured accordingly the device can also enrol into either Intune or the MDM solution that has been configured in Azure AD. The device is managed through the applicable MDM solution.

In AAD the status of the device is:

  • DeviceTrustType = Azure AD Joined”
  • “DeviceTrustLevel = Compliant” (only when fulfilling compliancy requirements, otherwise it is managed)

Due to the trust level “Compliant”, the device would be able to access resources configured with conditional access. You should only use this if you are migrating from your on-premises AD to Azure AD or if you do not have or want to have an on-premises AD

image

Figure 1: The Link To The Azure AD Join Option

image

Figure 2: Azure AD Join For Work Related Devices

[C] “Workplace Join” (Windows 7/8.1) or “Add Work or School Account” (Windows 10) or a.k.a. just “Device Registration”

This the way to register personal devices with Azure AD to be able to access work related resources. The user will then be able to leverage SSO for work resources through apps and browser (Edge and IE). When configured accordingly, it is possible to either disallow device registration or allow device registration for every user (self-service). When configured accordingly the device can also enrol into either Intune or the MDM solution that has been configured in Azure AD. The device is managed through the applicable MDM solution.

In AAD the status of the device is:

  • “DeviceTrustType = Workplace Joined”
  • “DeviceTrustLevel = Compliant” (only when fulfilling compliancy requirements, otherwise it is managed)

Due to the trust level “Compliant”, the device would be able to access resources configured with conditional access. When enabling this it applies to every user with an AAD account. It is however possible to limit the number of registered devices per user. If MDM is used, it is also possible to configure for which users MDM i mandatory, being “None”, “Specific Groups” or “All”. You should use this if you allow people to register their personal devices.

image

Figure 3: “Add Work Or School Account” (Windows 10) Or A.K.A. Just “Device Registration” For Personal Devices

In addition

  • Registered = device is known to Azure AD (a registered device can be managed or non-managed)
  • Managed = Registered + managed by MDM solution (a managed device can be compliant or non-compliant)
  • Compliant = Managed + full fills all compliancy rules

With regards to auto Azure AD joining computers to Azure you can read the following documentation:

….and if you also want to go all crazy about all kinds of details, you must definitely read Jairo’s blog posts about Azure AD join and related matters. These are:

Cheers,
Jorge
———————————————————————————————
* This posting is provided "AS IS" with no warranties and confers no rights!
* Always evaluate/test yourself before using/implementing this!
* DISCLAIMER:
https://jorgequestforknowledge.wordpress.com/disclaimer/
———————————————————————————————
############### Jorge’s Quest For Knowledge #############
#########
http://JorgeQuestForKnowledge.wordpress.com/ ########
———————————————————————————————

Posted in Azure AD Join, Windows Azure Active Directory | 2 Comments »

(2016-12-16) Automatic Azure AD Join With ADFS v3.0 And Higher And Conditional Access – What You Really Need In Detail

Posted by Jorge on 2016-12-16


With regards to auto Azure AD joining computers to Azure you can read the following documentation:

…and if you also want to go all crazy about all kinds of details, you must definitely read Jairo’s blog posts about Azure AD join and related matters. These are:

So WHY should you read this (my) blog post?

If you keep to the defaults that Microsoft provides in the documentation above, you are good to go!. However, and here comes the answer to the “WHY?”, if you want or need to deviate from the default you might not be able to get auto Azure AD joining working!

So, let’s start by going at it piece by piece!

Synchronize Computer Accounts Azure AD Join Or Auto Azure AD Join:

With Azure AD multiple join definitions exist. The definition I’m focusing on this blog is joining your Windows 7/8.1/10 PCs, that already joined to the on-premises AD, to Azure AD. There are two ways to achieve that goal, although with some conditions.

With Windows 7/8.1/10, if you want to have your AD domain joined PCs automatically and instantly joined to Azure AD, then you should continue to read remainder of this blog.With Windows 7/8.1/10 the computer is automatically register in Azure AD as soon as it starts and all conditions are met or in place.

With Windows 7/8.1 registration is done at user logon or when unlocking the PC and is done under the user context. The registration is done as user @ device. Therefore in Azure AD you may find multiple device registrations for the same Windows 7/8.1 PC and the reason for that is that multiple users are using the same PC. Remember that the scheduled tasks that triggers the registration has or may have a delay configured. So if you log on and nothing happens immediately, then think about the delay configured in the scheduled task. Windows 7 @ user logon delay is 5 min., Windows 7 @ workstation unlock there is no delay, Windows 8.1 @ user logon delay is 5 min.. Something else to be aware is that a non-admin user can unregister and register his own Windows 7/8.1 PC. Every a registration occurs for a specific PC initially or after an unregistration a new device object is created. Therefore, it might see may device objects in Azure AD for Windows 7/8.1 PCs and that is caused by multiple users using the PC or 1 single user that has reregistered his PC multiple times

With Windows 10 registration is done at user logon and is done under the computer context. The registration is really done as a device. For every Windows 10 PC you should only find one corresponding device object. Remember that the scheduled tasks that triggers the registration has or may have a delay configured. So if you log on and nothing happens immediately, then think about the delay configured in the scheduled task. Windows 10 @ user logon delay is 1 min.. Oh, and if a device object already exists that corresponds to the registering PC, because it was created by Azure AD Connect, then that device object is used. Compared to Windows 7/8.1, in Windows 10 non-admin users cannot unregister and register the WIndows 10 PC as it is the PC itself that must do this.

The part above is about automatically and instantly registering devices in Azure AD, or in other words provisioning. How about deprovisioning? When you unregister a device in Windows 7/8.1 the user @ device object is not cleaned automatically. You must have an out-of-band process to clean those. When you unregister a device in Windows 10 the device object is cleaned automatically and there is no need clean it up yourself. So what happens then if you just throw away the computer account in AD? Well, with Windows 7/8.1 nothing will happen in Azure AD. Again you will have to clean that yourself. With Windows 10 however, it depends on your Azure AD Connect configuration, so let’s talk about that!

With Azure AD Connect, you can select the OUs containing your Windows 10 PCs and bring those into the scope of synchronization. When you do that you achieve two goals. The first goal is that you will be able to provision device objects in Azure AD for those PCs that have not registered (yet) against Azure AD automatically. So if you do not use auto Azure AD joining for Windows 10 PCs, then Azure AD Connect will do it for you, although in a delayed manner due to the synchronization interval of Azure AD Connect. If a PC has auto registered itself, then Azure AD Connect will match the device object to the computer account in AD automatically next time Azure AD Connect runs. In either case, with or without auto Azure AD joining, Azure AD Connect will delete the device object as soon as the computer account has been deleted in AD or has been removed from the synchronization scope of Azure AD. Management of device objects in Azure AD (provisioning and deprovisioning) by Azure AD Connect is only possible for Windows 10 PCs as those are really registered as device objects representing the PC. It is does not support Windows 7/8.1 PCs are those are registered as device objects representing the user on the PC.

Therefore:

  • 1 Windows 7/8.1 PC can have multiple device objects in Azure AD. How many device objects, depends on the number of users using that Windows 7/8.1PC
  • 1 Windows 10 PC will have 1 device object in Azure AD, regardless the amount of users using that Windows 10 PC

Workplace Join Software And Triggering Registration:

Windows 8.1 and 10 do not require any additional software. All the required software is already integrated in Windows. Windows 7, however, does not have the required software. The required software must be installed manually or through some distribution system. Be aware that there are 2 versions of this software!

One version is available through Microsoft Connect. You can access it through this link. The other most recent version is available through Microsoft Download. You can access it through this link. One noticeable difference between the 2 versions is that the Microsoft Connect version does not use the SCP, even if it is in place. This version will always use the suffix of the UPN to determine the FQDN of the corresponding federated domain in Azure AD. If your UPN is non-internet routable, then you have a problem. The Microsoft Download version will also always use the suffix of the UPN to determine the FQDN of the corresponding federated domain in Azure AD, if the SCP is not in place in AD. If the SCP is in place, then it will use that information instead. If your UPN is non-internet routable, then this will work for you!

My suggestion for you is to use the Microsoft Download version!

Windows 7 will register as soon as all conditions are met. The same applies for Windows 8.1 and 10, but in addition to trigger the registration you must have a GPO with the correct setting enabled targeting the Windows 8.1/10 PCs in AD.

  • GPO Setting to trigger device registration in Azure AD for Windows 8.1/10:
    • From W2K12R12/Win81 machine –> Computer Configuration > Policies > Administrative Templates > Windows Components > Workplace Join > Automatically workplace join client computers = Enabled
    • From W2K16/Win10 machine –> Computer Configuration/Policies/Administrative Templates/Windows Components/Device Registration > Automatically workplace join client computers = Enabled

DNS Records For Device Registration:

If an operating system does not use the SCP, but rather uses the suffix of the UPN, then you need to create the correct DNS records for every suffix that you must support. If an operating system does use the SCP, then you need to create the correct DNS records for every FQDN that is listed in any SCP. You can only have one SCP for Azure AD per AD. If you have multiple ADs, you may also need an SCP for every AD. More information below. Check the documentation for the exact information about the required DNS records.

I have found out that this also works WITHOUT the “enterprise.<your federated domain FQDN>” DNS CNAME record when using the SCP. I do not know what would happen if it uses the suffix of the UPN. I would assume the same behavior

Service Connection Point (SCP):

For your Windows clients (Windows 7, 8.1, 10 and probably higher) to be able to register against your Azure AD tenant, those clients need to find the  registration service endpoint. For that to succeed, you need to create a SCP through a PowerShell CMDlet in Azure AD Connect. Check the documentation for the exact syntax of the command and the information about the object in AD. After running the command, the “keywords” attribute contains the Azure AD Tenant ID and the FQDN of one of the federated domains if you have any. If you have multiple federated domains, the command will just choose one. It does not really matter which one, at least if all federated domains in Azure AD point to the same on-premises federation system. If you have multiple federated domains and those point to different on-premises federation systems, then you need to tweak the SCP manually by specifying the correct FQDN. Remember that any given AD forest can only have one SCP with Azure AD Tenant information. If you have multiple AD forests being served by the same federation system, then you need to create an SCP in every AD forest where you want to support auto Azure AD join. For the latter scenario, you can perform an LDIFDE export of the object where it already exists, adjust the information as needed and perform an LDIFDE import in the other AD forest. Remember that for every FQDN that you use, you must have the correct DNS records in place as mentioned earlier!

As LDIFDE is sooooooooooooooo before 2005, you can also use PowerShell to create the SCP in other AD forest. The only thing you need to know is the FQDN of a federated domain in AAD and the AAD tenant ID. Knowing that you can use the following script:

$verifiedDomain = "<Replace this with the FQDN of any of your verified domain names in Azure AD>"
$tenantID = "<Replace this with you tenant ID>"

$thisADForest = [DirectoryServices.ActiveDirectory.Forest]::GetCurrentForest()
$configNC = $($thisADForest.schema.name).Substring($($thisADForest.schema.name).IndexOf(",") + 1)

$directoryEntry = New-Object System.DirectoryServices.DirectoryEntry
$directoryEntry.Path = "LDAP://CN=Services," + $configNC

$deviceRegContainer = $directoryEntry.Children.Add("CN=Device Registration Configuration", "container")
$deviceRegContainer.CommitChanges()

$serviceConnectionPoint = $deviceRegContainer.Children.Add("CN=62a0ff2e-97b9-4513-943f-0d221bd30080", "serviceConnectionPoint")
$serviceConnectionPoint.Properties["keywords"].Add("azureADName:" + $verifiedDomain)
$serviceConnectionPoint.Properties["keywords"].Add("azureADId:" + $tenantID)

$serviceConnectionPoint.CommitChanges()

image

Figure 1: SCP Object In AD

Authentication:

With auto Azure AD join you are joining PCs to Azure AD that are already joined to AD. Auto Azure AD join always occurs within the corporate network and leverages Windows authentication with no interaction. Therefore, within ADFS you must have “Windows Integrated Authentication (WIA)” as the first authentication mechanism. You CANNOT use anything like Forms Based Authentication (FBA) or Certificate Based Authentication (CBA).

Home Realm Discovery:

With auto Azure AD join you cannot have any interaction. With that in mind you must therefore sure the Home Realm Discovery (HRD) screen in ADFS does not interact. If you only have one claims provider/identity provider trust (i.e “Active Directory”), then you are good to go! However, if you have multiple claims provider/identity provider trusts, you must make sure that only the “Active Directory” CP trust is allowed to be used. Within ADFS v3.0 and higher, every RP trust has a property called “ClaimsProviderName” and you need to make sure that only “Active Directory” is listed in that property. When that is the case, ADFS will always assume that everyone needs to be authenticated by the local Active Directory or any other 2-way forest trust connected Active Directory.

image

Figure 2: RP Trust For Azure AD Configured For Only The CP Trust Active Directory

Authentication Class References:

By default the RP trust for Azure AD is not configured with any authentication class reference. For Windows 7/8.1/10 you must configure the RP trust for Azure AD to have “wiaormultiauthn” as an allowed authentication class reference. See the documentation for how to configure this.

image

Figure 3: Required Authentication Class Reference

image

Figure 4: Sending Authentication Class Reference In Claims

The yellow marked claim rule (rule 11):

@RuleName = "AuthN Claims – Methods References"
c:[Type == "
http://schemas.microsoft.com/claims/authnmethodsreferences"%5D
=> issue(claim = c);

If you do not configure this, you will see a error (event ID 364) in the ADFS logs exactly the same or similar to

Encountered error during federation passive request.

Additional Data

Protocol Name:
wsfed

Relying Party:
urn:federation:MicrosoftOnline

Exception details:
Microsoft.IdentityServer.RequestFailedException: The requested authentication method ‘wiaormultiauthn’ is not valid for relying party trust ‘Microsoft Azure Active Directory (Custom Config)’.
   at Microsoft.IdentityServer.Web.Authentication.AuthenticationPolicyEvaluator.ValidateRpAllowsAuthClassReference(String rpIdentifier, String authClassReferenceId)
   at Microsoft.IdentityServer.Web.Authentication.AuthenticationPolicyEvaluator.VerifyTargetRPsSupportAuthClassReference(String authClassReferenceId)
   at Microsoft.IdentityServer.Web.Authentication.AuthenticationPolicyEvaluator.EvaluatePolicy(Boolean& isLastStage, AuthenticationStage& currentStage, Boolean& strongAuthRequried)
   at Microsoft.IdentityServer.Web.PassiveProtocolListener.GetAuthMethodsFromAuthPolicyRules(PassiveProtocolHandler protocolHandler, ProtocolContext protocolContext)
   at Microsoft.IdentityServer.Web.PassiveProtocolListener.GetAuthenticationMethods(PassiveProtocolHandler protocolHandler, ProtocolContext protocolContext)
   at Microsoft.IdentityServer.Web.PassiveProtocolListener.OnGetContext(WrappedHttpListenerContext context)

ADFS Endpoints:

Windows 10 and Windows Server 2016 and higher will authenticate by using Windows Integrated Authentication to an active WS-Trust endpoint hosted by ADFS. It is therefore very important that this endpoint is enabled. Check the documentation for the correct endpoint and how to enable that endpoint if not already enabled. This is not needed for Windows 7/8.1.

However, ADFS provides 2 ADFS endpoint that support this requirement. By default, the endpoint “/adfs/services/trust/2005/windowstransport” is enabled by default for ADFS and the WAP (Proxy) and by default the endpoint “/adfs/services/trust/13/windowstransport” is disabled by default for ADFS and WAP. The documentation will tell you to enable “/adfs/services/trust/13/windowstransport”. However, if you already have “/adfs/services/trust/2005/windowstransport” enabled for ADFS you may not need to enable “/adfs/services/trust/13/windowstransport” for ADFS.

Some documentation, like Windows 10 Sign on – enabling device authentication with AD FS will tell you to enable both, but that is not really needed.

ClientCredentialType : Windows
Enabled              : True
FullUrl              :
https://<FQDN Federation Service Farm>/adfs/services/trust/2005/windowstransport
Proxy                : True
Protocol             : WS-Trust
SecurityMode         : Transport
AddressPath          : /adfs/services/trust/2005/windowstransport
Version              : wstrust2005

ClientCredentialType : Windows
Enabled              : False
FullUrl              :
https://<FQDN Federation Service Farm>/adfs/services/trust/13/windowstransport
Proxy                : False
Protocol             : WS-Trust
SecurityMode         : Transport
AddressPath          : /adfs/services/trust/13/windowstransport
Version              : wstrust13

If you do not have a WS-trust endpoint enabled, you will see a error (event ID 305) in the ADFS logs exactly the same or similar to:

Automatic registration failed at authentication phase.  Unable to acquire access token.  Exit code: Unspecified error. Server error: AdalMessage: ADALUseWindowsAuthenticationTenant failed,  unable to preform integrated auth
AdalError: authentication_failed
AdalErrorCode: 0x2ee6
AdalCorrelationId: {18691F25-1E05-4D4E-BD43-28BD34D879E9}
AdalLog:  HRESULT: 0x2ee6
AdalLog:  HRESULT: 0x2ee6
AdalLog:  HRESULT: 0x2ee6
AdalLog: AggregatedTokenRequest::UseWindowsIntegratedAuth- received realm info ; HRESULT: 0x0
AdalLog:  HRESULT: 0x4aa90010
AdalLog: AggregatedTokenRequest::UseWindowsIntegratedAuth w Tenant ; HRESULT: 0x0
AdalLog: AggregatedTokenRequest::AcquireToken- returns false ; HRESULT: 0x0
AdalLog: AggregatedTokenRequest::AcquireToken- refresh token is not available ; HRESULT: 0x0
AdalLog: AggregatedTokenRequest::AcquireToken get refresh token info ; HRESULT: 0x0
AdalLog: Authority validation is completed ; HRESULT: 0x0
AdalLog: Authority validation is enabled ; HRESULT: 0x0
AdalLog: Token is not available in the cache ; HRESULT: 0x0
. Tenant Type: XXXXX.XXX

If you do not have a WS-trust endpoint enabled, you will see a error (event ID 304) in the ADFS logs exactly the same or similar to:

Automatic registration failed at join phase.  Exit code: Unknown HResult Error code: 0xcaa1000e. Server error: empty. Debug Output:\r\n joinMode: Join
drsInstance: azure
registrationType: fed
tenantType: fed
tenantId: 550d46cf-0819-4a9b-a03c-2f0fd431ce1f
configLocation: undefined
errorPhase: auth
adalCorrelationId: {18691F25-1E05-4D4E-BD43-28BD34D879E9}
adalLog: AdalLog:  HRESULT: 0xcaa1000e
AdalLog:  HRESULT: 0x2ee6
AdalLog:  HRESULT: 0x2ee6
AdalLog:  HRESULT: 0x2ee6
AdalLog: AggregatedTokenRequest::UseWindowsIntegratedAuth- received realm info ; HRESULT: 0x0
AdalLog:  HRESULT: 0x4aa90010
AdalLog: AggregatedTokenRequest::UseWindowsIntegratedAuth w Tenant ; HRESULT: 0x0
AdalLog: AggregatedTokenRequest::AcquireToken- returns false ; HRESULT: 0x0
AdalLog: AggregatedTokenRequest::AcquireToken- refresh token is not available ; HRESULT: 0x0
AdalLog: AggregatedTokenRequest::AcquireToken get refresh token info ; HRESULT: 0x0
AdalLog: Authority validation is completed ; HRESULT: 0x0
AdalLog: Authority validation is enabled ; HRESULT: 0x0
AdalLog: Token is not available in the cache ; HRESULT: 0x0

adalLog: AdalLog:  HRESULT: 0xcaa1000e
AdalLog:  HRESULT: 0x2ee6
AdalLog:  HRESULT: 0x2ee6
AdalLog:  HRESULT: 0x2ee6
AdalLog: AggregatedTokenRequest::UseWindowsIntegratedAuth- received realm info ; HRESULT: 0x0
AdalLog:  HRESULT: 0x4aa90010
AdalLog: AggregatedTokenRequest::UseWindowsIntegratedAuth w Tenant ; HRESULT: 0x0
AdalLog: AggregatedTokenRequest::AcquireToken- returns false ; HRESULT: 0x0
AdalLog: AggregatedTokenRequest::AcquireToken- refresh token is not available ; HRESULT: 0x0
AdalLog: AggregatedTokenRequest::AcquireToken get refresh token info ; HRESULT: 0x0
AdalLog: Authority validation is completed ; HRESULT: 0x0
AdalLog: Authority validation is enabled ; HRESULT: 0x0
AdalLog: Token is not available in the cache ; HRESULT: 0x0

adalResponseCode: 0xcaa1000e

To enable the "/adfs/services/trust/13/windowstransport" endpoint for ADFS, execute on the (primary) ADFS server:

Enable-AdfsEndpoint -TargetAddressPath "/adfs/services/trust/13/windowstransport"

To enable the "/adfs/services/trust/2005/windowstransport" endpoint for ADFS, execute on the (primary) ADFS server:

Enable-AdfsEndpoint -TargetAddressPath "/adfs/services/trust/2005/windowstransport"

Claims Rules For The RP Trust For Azure AD (User Authentication/Access):

For a user to successfully authenticate against Azure AD you must configure a number of claims rules. The claims rules are listed below and I will explain them one by one. By the way, the claims rules you see are the claims rules I have for MY environment. Your claims rules should be either exactly the same of similar to what you see below. For this part of this blog post it is also important that you also read the following blog posts to have the complete picture:

Azure AD Connect – Identifying Objects In AD And In Azure AD

image

Figure 5: Claims Rules For User Authentication Against Azure AD On the Azure AD RP Trust

The yellow marked claim rule (rule 1):

@RuleName = "Identity Claims – upn To UPN"
c:[Type == "
http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn"%5D
=> issue(Type = "http://schemas.xmlsoap.org/claims/UPN&quot;, Issuer = c.Issuer, OriginalIssuer = c.OriginalIssuer, Value = c.Value, ValueType = c.ValueType);

EXPLANATION: For the user to successfully authenticate against Azure AD, the value of the AD attribute that you chose during the installation of Azure AD Connect as the source for the User Principal Name in Azure AD must be send in a claim type to Azure AD. By default, that is the AD attribute “userPrincipalName”. You may have chosen something else, e.g. mail, if your AD attribute “userPrincipalName” contains values with non-internet routable suffixes. Also see (2016-05-07) Azure AD Connect – Identifying Objects In AD And In Azure AD (Part 1) .

The yellow marked claim rule (rule 2):

@RuleTemplate = "MapClaims"
@RuleName = "Identity Claims – iamTECImmutableID To ImmutableID"
c:[Type == "
http://temp.org/identity/claims/iamTECImmutableID"%5D
=> issue(Type = "http://schemas.microsoft.com/LiveID/Federation/2008/05/ImmutableID&quot;, Issuer = c.Issuer, OriginalIssuer = c.OriginalIssuer, Value = c.Value, ValueType = c.ValueType);

EXPLANATION: For the user to successfully authenticate against Azure AD, an additional immutable identifier must be send to Azure AD in a claim type. Now why is this, you may think, if the previous claim rule already sends identification to Azure AD. See this claim type as an addition security measure that really links the user in Azure AD to the user in your AD, and not to somebody else’s AD that is using the same UPN suffix (e.g. hacker). This immutable ID is a unique value that nobody can guess easily. The value of the AD attribute that you chose for users during the installation of Azure AD Connect as the source for the Source Anchor in Azure AD must be send in a claim type to Azure AD. By default, that is the AD attribute “objectGUID”. If you have read the blog post (2016-05-07) Azure AD Connect – Identifying Objects In AD And In Azure AD (Part 1) and the reasons mentioned there apply to you (even if they do not, I really suggest you follow that guidance to give yourself room in the future if you need it!), you have chosen another AD attribute to be the source of the Source Anchor. As you can see above I’m using a special claim type “http://temp.org/identity/claims/iamTECImmutableID” that contains my immutable ID value for Azure AD. That value is put into the claim type “http://schemas.microsoft.com/LiveID/Federation/2008/05/ImmutableID” that Azure AD wants to receive. I will explain below how I get my value for “http://temp.org/identity/claims/iamTECImmutableID

The yellow marked claim rule (rule 3):

@RuleTemplate = "MapClaims"
@RuleName = "Identity Claims – iamTECImmutableID To NameID"
c:[Type == "
http://temp.org/identity/claims/iamTECImmutableID"%5D
=> issue(Type = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier&quot;, Issuer = c.Issuer, OriginalIssuer = c.OriginalIssuer, Value = c.Value, ValueType = c.ValueType, Properties["http://schemas.xmlsoap.org/ws/2005/05/identity/claimproperties/format"%5D = "urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified");

EXPLANATION: The exact value you send as the immutable ID to “http://schemas.microsoft.com/LiveID/Federation/2008/05/ImmutableID” must also be send to “http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier” and in addition using the format specified in the claim rule for the name identifier. Again, the value of the AD attribute that you chose for users during the installation of Azure AD Connect as the source for the Source Anchor in Azure AD must be send in a claim type to Azure AD. By default, that is the AD attribute “objectGUID”. If you have read the blog post (2016-05-07) Azure AD Connect – Identifying Objects In AD And In Azure AD (Part 1) and the reasons mentioned there apply to you (even if they do not, I really suggest you follow that guidance to give yourself room in the future if you need it!), you have chosen another AD attribute to be the source of the Source Anchor. As you can see above I’m using a special claim type “http://temp.org/identity/claims/iamTECImmutableID” that contains my immutable ID value for Azure AD. That value is put into the claim type “http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier” that Azure AD wants to receive. I will explain below how I get my value for “http://temp.org/identity/claims/iamTECImmutableID”.

The yellow marked claim rule (rule 4):

@RuleName = "Identity Claims – Issuer Identifier"
c1:[Type == "
http://schemas.xmlsoap.org/claims/UPN&quot;, Value =~ "(?i)@(xxxxxx|yyyyyy).nl$"]
&& c2:[Type == "
http://temp.org/identity/claims/primaryGroupID&quot;, Value =~ "^513$"]
=> issue(Type = "
http://schemas.microsoft.com/ws/2008/06/identity/claims/issuerid&quot;, Value = regexreplace(c1.Value, ".+@(?<domain>.+)", "<Federation Service Identifier>:AAD:${domain}"));

EXPLANATION: This claims rule is NOT required if you only have 1 federated domain in Azure AD. If you have multiple federated domains in Azure AD, then a claims rule similar to this one is required. That claims rule is configured automatically when using the “SupportMultipleDomain” option as explained here. The reason for this is that every federated domain in Azure AD must have a unique identifier. If multiple federated domains point to the same federation system on-premises, the identifier will be the same across multiple federated domains, and Azure AD does not allow that. That’s why, if you have multiple federated domains, you have to send an additional claim type that contains a custom unique issuer ID.

I my case I only to apply this to users, hence the use of the “http://temp.org/identity/claims/primaryGroupID” claim type with value “513” (I will explain below how I get this value). This basically says the following:

If a UPN value is present that ends in “@xxxxxx.nl” or “@yyyyyy.nl” and a primaryGroupID value of “513” exist, then issue the claim type “http://schemas.microsoft.com/ws/2008/06/identity/claims/issuerid” with a value of “<Federation Service Identifier>:AAD:#######” where “#######” is replaced by either “xxxxxx.nl” or “yyyyyy.nl”. The value for <Federation Service Identifier> is in my case exactly the same as the identifier of my ADFS farm. For this to work, the value “<Federation Service Identifier>:AAD:xxxxxx.nl” must exist as an issueURI on the domain “XXXXXX.NL” in Azure AD and the value “<Federation Service Identifier>:AAD:yyyyyy.nl” must exist as an issueURI on the domain “YYYYYY.NL” in Azure AD.

In the Microsoft documentation, or after running the PowerShell CMDlet with the “SupportMultipleDomain” option you will not find the value "<Federation Service Identifier>:AAD:${domain}", but rather you will find “http://${domain}/adfs/services/trust/”. Whatever value you use, it does not really matter. The only rule that applies is: whatever you send in the issuer ID claim type, it must match the issuer =URI of the targeted federated domain in Azure AD. If you need to support sub-domains of federated domains, than also look here.

Claims Rules For The RP Trust For Azure AD (Computer Authentication/Access):

For a Windows 10 computer to successfully authenticate against Azure AD you must configure a number of claims rules. The claims rules are listed below and I will explain them one by one. By the way, the claims rules you see are the claims rules I have for MY environment. Your claims rules should be either exactly the same of similar to what you see below.

image

Figure 6: Claims Rules For Computer Authentication Against Azure AD On the Azure AD RP Trust

The yellow marked claim rule (rule 5):

@RuleName = "Machine Claims – ObjectGUID To ImmutableID"
c1:[Type == "
http://temp.org/identity/claims/primaryGroupID&quot;, Value =~ "^515$"]
&& c2:[Type == "
http://temp.org/identity/claims/adObjectGuidBase64org"%5D
=> issue(Type = "http://schemas.microsoft.com/LiveID/Federation/2008/05/ImmutableID&quot;, Issuer = c2.Issuer, OriginalIssuer = c2.OriginalIssuer, Value = c2.Value, ValueType = c2.ValueType);

EXPLANATION: For the computer to successfully authenticate against Azure AD, an additional immutable identifier must be send to Azure AD in a claim type. The value of the AD attribute that you chose for users during the installation of Azure AD Connect as the source for the Source Anchor in Azure AD is NOT relevant for computers. Although it is possible to change this, for computers by default, the value of the AD attribute “objectGUID” is used as the immutable ID to identify the computer. As you can see above I’m using a special claim type “http://temp.org/identity/claims/adObjectGuidBase64org” that contains my immutable ID value for Azure AD. That value is put into the claim type “http://schemas.microsoft.com/LiveID/Federation/2008/05/ImmutableID” that Azure AD wants to receive. I will explain below how I get my value for “http://temp.org/identity/claims/adObjectGuidBase64org”. As you have seen before I’m now explicitly filtering for primaryGroupID being equal to 515 and that means that it will only apply for computers. I will explain below how I get the value for “http://temp.org/identity/claims/adObjectGuidBase64org” and “http://temp.org/identity/claims/primaryGroupID”.

The yellow marked claim rule (rule 6):

@RuleName = "Machine Claims – ObjectGUID To OnPremObjectGUID"
c1:[Type == "
http://temp.org/identity/claims/primaryGroupID&quot;, Value =~ "^515$"]
&& c2:[Type == "
http://temp.org/identity/claims/adObjectGuidBase64org"%5D
=> issue(Type = "http://schemas.microsoft.com/identity/claims/onpremobjectguid&quot;, Value = c2.Value);

EXPLANATION: The exact value you send as the immutable ID to “http://schemas.microsoft.com/LiveID/Federation/2008/05/ImmutableID” must also be send to “http://schemas.microsoft.com/identity/claims/onpremobjectguid”. Again, the value of the AD attribute that you chose for users during the installation of Azure AD Connect as the source for the Source Anchor in Azure AD is NOT relevant for computers. Although it is possible to change this, for computers by default, the value of the AD attribute “objectGUID” is used as the immutable ID to identify the computer. As you can see above I’m using a special claim type “http://temp.org/identity/claims/adObjectGuidBase64org” that contains the immutable ID value for computers in Azure AD. That value is put into the claim type “http://schemas.microsoft.com/identity/claims/onpremobjectguid” that Azure AD wants to receive. I will explain below how I get my value for “http://temp.org/identity/claims/adObjectGuidBase64org”. As you have seen before I’m now explicitly filtering for primaryGroupID being equal to 515 and that means that it will only apply for computers. I will explain below how I get the value for “http://temp.org/identity/claims/adObjectGuidBase64org” and “http://temp.org/identity/claims/primaryGroupID”.

The yellow marked claim rule (rule 7):

@RuleName = "Machine Claims – PrimarySid"
c1:[Type == "http://temp.org/identity/claims/primaryGroupID&quot;, Value =~ "^515$"]
&& c2:[Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/primarysid"%5D
=> issue(claim = c2);

EXPLANATION: For computers only, hence the additional filter/condition using the “http://temp.org/identity/claims/primaryGroupID” claim type containing the value “515”, the objectSID must be send to Azure AD. Therefore if a claim type “http://schemas.microsoft.com/ws/2008/06/identity/claims/primarysid” exist for computers with a value, then that claim type and value must be send to Azure AD. I will explain below how I get the value for “http://temp.org/identity/claims/primaryGroupID”.

The yellow marked claim rule (rule 8):

@RuleName = "Machine Claims – Account Type"
c:[Type == "
http://temp.org/identity/claims/primaryGroupID&quot;, Value =~ "^515$"]
=> issue(Type = "
http://schemas.microsoft.com/ws/2012/01/accounttype&quot;, Value = "DJ");

EXPLANATION: For computers only, hence the additional filter/condition using the “http://temp.org/identity/claims/primaryGroupID” claim type containing the value “515”, a special claim type “http://schemas.microsoft.com/ws/2012/01/accounttype” with a value of DJ must be send to Azure AD. This is telling Azure AD that the computer in question is already domain joined in AD. I will explain below how I get the value for “http://temp.org/identity/claims/primaryGroupID”.

The yellow marked claim rule (rule 9):

@RuleName = "Machine Claims – Issuer Identifier"
c:[Type == "
http://temp.org/identity/claims/primaryGroupID&quot;, Value =~ "^515$"]
=> issue(Type = "
http://schemas.microsoft.com/ws/2008/06/identity/claims/issuerid&quot;, Value = "<Federation Service Identifier>:AAD:XXXXXX.NL");

EXPLANATION: This claims rule is NOT required if you only have 1 federated domain in Azure AD. If you have multiple federated domains in Azure AD, then a claims rule similar to this one is required. As for users, when having multiple federated domains in Azure AD, for computers you must also send the “http://schemas.microsoft.com/ws/2008/06/identity/claims/issuerid” claim type with a specific value. However for computers only, hence the additional filter/condition using the “http://temp.org/identity/claims/primaryGroupID” claim type containing the value “515”, the value does not matter. As long as the value matches the issuerURI of one of the federated domains in Azure AD, then that’s OK. Which one to choose? Does not matter, just pick your favorite! I will explain below how I get the value for “http://temp.org/identity/claims/primaryGroupID”.

Claims Rules For The CP Trust For AD:

For a user and a computer to successfully authenticate against ADFS and have the required claim types and values for Azure AD you must configure a number of claims rules. The claims rules are listed below as the bare minimum to extract the required information from AD and I will explain them one by one. By the way, the claims rules you see are the claims rules I have for MY environment. Your claims rules should be either exactly the same of similar to what you see below. For this part of this blog post it is also important that you also read the following blog posts to have the complete picture:

Azure AD Connect – Identifying Objects In AD And In Azure AD

REMARK: The claims rules below DO NOT take anything else into account other than just Azure AD. Therefore DO NOT use these claims rules and replace those you already have. You will need to integrate with what you already have!

REMARK: Many people rely on the groupSID claim, which is OK. There is one caviat though!. If you have many groups in AD that users are a member of, then using the groupSID may give you problems with either ADFS and/or applications. With regards to ADFS, the problem relies with the browser that is not able to put the large amount of claim types and values in the security token (cookie!). The cookie size is limited and from what I know it cannot be adjusted/increased. With regards to application the header size might be to big for the application to understand. A solution is to increase the header size of the Windows server the application is running on, but the upper limit is fixed, if you know what I mean

image

Figure 6: Claims Rules For User/Computer Authentication Against ADFS And Azure AD On the AD CP Trust

The yellow marked claim rule (rule 1):

@RuleTemplate = "PassThroughClaims"
@RuleName = "Identity Claims – Primary SID"
c:[Type == "
http://schemas.microsoft.com/ws/2008/06/identity/claims/primarysid"%5D
=> issue(claim = c);

EXPLANATION: The claim type “http://schemas.microsoft.com/ws/2008/06/identity/claims/primarysid” is required as the Windows 10 computer needs to send this to Azure AD.

The yellow marked claim rule (rule 2):

@RuleTemplate = "PassThroughClaims"
@RuleName = "Identity Claims – Windows Account Name"
c:[Type == "
http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname"%5D
=> issue(claim = c);

EXPLANATION: The claim type “http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname” is the anchor claim type required by ADFS and is also required by rule 4 to query for additional information from AD.

The yellow marked claim rule (rule 3)

@RuleTemplate = "PassThroughClaims"
@RuleName = "Identity Claims – upn"
c:[Type == "
http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn"%5D
=> issue(claim = c);

EXPLANATION: The claim type “http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn” is required as the user needs to send this to Azure AD.

The yellow marked claim rule (rule 4):

@RuleName = "Identity Claims – Extra Identity Claims/Attributes"
c:[Type == "
http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname"%5D
=> issue(store = "Active Directory", types = ("http://temp.org/identity/claims/adObjectGuidBase64org&quot;, "http://temp.org/identity/claims/iamTECImmutableID", "http://temp.org/identity/claims/primaryGroupID&quot;), query = ";objectGUID,iamTECImmutableID,primaryGroupID;{0}", param = c.Value);

EXPLANATION: Based upon the “http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname”, additional claim types will be sourced from AD. The following will occur:

  • User object:
  • Computer object:
    • “objectGUID” attribute value in base64 format will go into the claim type “http://temp.org/identity/claims/adObjectGuidBase64org"
    • “iamTECImmutableID” attribute value is empty for computers
    • “primaryGroupID” attribute value (for computers this is 515) will go into the claim type “http://temp.org/identity/claims/primaryGroupID

REMARK: the AD attribute “iamTECImmutableID” does not exist in AD by default. For this the AD schema was extended!

Now, looking at all the claim rules displayed above, how will the transport of the values look like? Well, look at the table below!

FOR USERS

AD Attribute With Example Value Claim Types In Security Token For ADFS Claim Types In Security Token For Azure AD
“ObjectSID” (S-1-5-21-963889158-2862062032-2620964440-2076) http://schemas.microsoft.com/ws/2008/06/identity/claims/primarysid” (same value) N.A.
“msDS-PrincipalName” (XXXXXX\SOMEUSER) http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname” (same value)
“userPrincipalName” (SOMEUSER@XXXXXX.NL) http://schemas.xmlsoap.org/claims/UPN” (same value)
http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn” (same value) http://schemas.microsoft.com/ws/2008/06/identity/claims/issuerid” (urn:federation:fs.xxxxxx.nl:AAD:XXXXXX.NL)
“ObjectGUID” (Base 64) (NQUKyhbeN0yLsrQ/1b6a3w==) http://temp.org/identity/claims/adObjectGuidBase64org” (same value) N.A.
“iamTECImmutableID” (NQUKyhbeN0yLsrQ/1b6a3w==) "http://temp.org/identity/claims/iamTECImmutableID" (same value) http://schemas.microsoft.com/LiveID/Federation/2008/05/ImmutableID” (same value)
"http://temp.org/identity/claims/iamTECImmutableID" (same value) “http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier" (same value)
“primaryGroupID” (513) http://temp.org/identity/claims/primaryGroupID” (same value) N.A.

FOR COMPUTERS

AD Attribute With Example Value Claim Types In Security Token For ADFS Claim Types In Security Token For Azure AD
“ObjectSID” (S-1-5-21-963889158-2862062032-2620964440-3333) http://schemas.microsoft.com/ws/2008/06/identity/claims/primarysid” (same value) http://schemas.microsoft.com/ws/2008/06/identity/claims/primarysid” (same value)
“msDS-PrincipalName” (XXXXXX\COMPUTER$) http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname” (same value) N.A.
“userPrincipalName” (Empty, N.A.) N.A. N.A.
“ObjectGUID” (Base 64) (Kx3CDrz7HkaTOjRLzQfKNw==) http://temp.org/identity/claims/adObjectGuidBase64org” (same value) http://schemas.microsoft.com/LiveID/Federation/2008/05/ImmutableID” (same value)
http://temp.org/identity/claims/adObjectGuidBase64org” (same value) http://schemas.microsoft.com/identity/claims/onpremobjectguid” (same value)
“iamTECImmutableID” (Empty, N.A.) N.A. N.A.
“primaryGroupID” (515) http://temp.org/identity/claims/primaryGroupID” (same value) N.A.
http://schemas.microsoft.com/ws/2012/01/accounttype” (DJ)
http://schemas.microsoft.com/ws/2008/06/identity/claims/issuerid” (urn:federation:fs.xxxxxx.nl:AAD:XXXXXX.NL)

Any questions or comments on this? Use the contact page to contact me or use the comments section below!

Enjoy and have fun!

Cheers,
Jorge
———————————————————————————————
* This posting is provided "AS IS" with no warranties and confers no rights!
* Always evaluate/test yourself before using/implementing this!
* DISCLAIMER:
https://jorgequestforknowledge.wordpress.com/disclaimer/
———————————————————————————————
############### Jorge’s Quest For Knowledge #############
#########
http://JorgeQuestForKnowledge.wordpress.com/ ########
———————————————————————————————

Posted in Azure AD Join, Windows Azure Active Directory | 8 Comments »

 
%d bloggers like this: