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 ‘Claims’ Category

(2018-11-01) Transform Rules In ADFS – Send E-Mail Address Value For E-mail, Otherwise Send UPN Value For E-Mail

Posted by Jorge on 2018-11-01


A few days ago I got the following question:

  • Some accounts have a mailbox, some do not;
  • For accounts that do have a mailbox I need to send the e-mail address value as the claim value in the e-mail address claim type;
  • For accounts that do not have a mailbox I need to send the upn value as the claim value in the e-mail address claim type;

How can I achieve that through the claims rule language in ADFS?

It is not that difficult. See below for an example as the answer to the question above:

RULENAME1: User Identity Claims – Windows Account Name
COMMENT1: if the windows account name claim exists and has a value send it through

c:[Type == "
http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname"]
=> issue(claim = c);

RULENAME2: User Identity Claims – upn
COMMENT2: if the UPN claim exists and has a value send it through

c:[Type == "
http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn"]
=> issue(claim = c);

RULENAME3: User Identity Claims – E-Mail Address
COMMENT3: get mail from AD and put it in claim

c:[Type == "
http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname"]
=> issue(store = "Active Directory", types = ("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress"), query = ";mail;{0}", param = c.Value);

RULENAME4: System Claims – Check E-Mail Address Existence
COMMENT4: check if the mail address claim exist or not

NOT EXISTS([Type == "
http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress"])
=> add(Type = "http://temp.org/system/claims/eMailAddressExistance", Value = "False");

RULENAME5: User Identity Claims – upn To E-Mail Address (When E-Mail Address DOES NOT Exist)
COMMENT5: send the UPN value into mail address claim if no mail claim address exists

c1:[Type == "
http://temp.org/system/claims/eMailAddressExistance", Value == "False"] &&
c2:[Type == "
http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn"]
=> issue(Type = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress", Value = c2.Value);

Make sure to test this first in a TEST 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 Federation Services (ADFS), Claims, Claims Rule Language | Leave a Comment »

(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", 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", "http://schemas.microsoft.com/LiveID/Federation/2008/05/ImmutableID"), 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 »

(2017-06-12) Changing The Identity Type Displayed On The MFA Page In ADFS

Posted by Jorge on 2017-06-12


By default when you hit the MFA page in ADFS 2012 R2, the identity type displayed is similar to DOMAIN\SAMACCOUNTNAME as you can see in figure 1 below. The MFA page in ADFS 2012 R2 by default uses the value from the name claim type (“http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name”) to display that same value in the MFA page in ADFS 2012 R2.

The name claim type is configured by default in an Acceptance Transform Rule on the “Active Directory” CP trust, and it is most likely read from the “msDS-PrincipalName” attribute in AD.

The Acceptance Transform Rule on the “Active Directory” CP trust for the name claim type may be similar to

@RuleTemplate = "PassThroughClaims"
@RuleName = "Pass through all Name claims"
c:[Type == "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name&quot;, Issuer =~ "^(AD AUTHORITY|SELF AUTHORITY|LOCAL AUTHORITY)$"] => issue(claim = c);

image

Figure 1: MFA Page In ADFS 2012 R2 With The Default Value For The Name Claim Type

However, with all the cloud development going on and everything focusing on the mail address of a user instead, you may want to display the mail address of the user instead as displayed in figure 2 below.

To make this change you need to delete the default Acceptance Transform Rule on the “Active Directory” CP trust for the name claim type and create a new rule where you will flow the value of the mail claim value (MAIL@ADDRESS.COM) into the name claim type. The new Acceptance Transform Rule on the “Active Directory” CP trust would look like:

@RuleTemplate = "MapClaims"
@RuleName = "E-mail Address To Name"
c:[Type == "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress"%5D
=> issue(Type = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name&quot;, Issuer = c.Issuer, OriginalIssuer = c.OriginalIssuer, Value = c.Value, ValueType = c.ValueType);

image

Figure 2: MFA Page In ADFS 2012 R2 With The Custom Value For The Name Claim Type

Is there a catch to this? Yes there is, or better yes there are!

[Catch 1]

By default the e-mail address is NOT extracted from AD by ADFS! Because of that you need to create your own Acceptance Transform Rule where you do that. The Acceptance Transform Rule you need at least is or looks similar to:

@RuleTemplate = "LdapClaims"
@RuleName = "E-mail Address"
c:[Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname&quot;, Issuer == "AD AUTHORITY"]
=> issue(store = "Active Directory", types = ("
http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress&quot;), query = ";mail;{0}", param = c.Value);

Because the name claim type depends on this Acceptance Transform Rule, this Acceptance Transform Rule for the mail claim type must be processed before the Acceptance Transform Rule for the name claim type

[Catch 2]

Some applications connected to ADFS may expect to receive a name claim value that looks like DOMAIN\SAMACCOUNTNAME instead of MAIL@ADDRESS.COM. By implementing the new Acceptance Transform Rule for the name claim type you will impact those applications.

To mitigate that impact before making those changes, you would need reconfigure the RP trust of the application that needs the name claim value. If RP trust has an Issuance Transform Rule that is similar to or looks like:

@RuleTemplate = "PassThroughClaims"
@RuleName = "Pass through all Name claims"
c:[Type == "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name"%5D => issue(claim = c);

….you would need to delete that Issuance Transform Rule and replace it with:

@RuleTemplate = "MapClaims"
@RuleName = "Windows Account Name To Name"
c:[Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname"%5D
=> issue(Type = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name&quot;, Issuer = c.Issuer, OriginalIssuer = c.OriginalIssuer, Value = c.Value, ValueType = c.ValueType);

[Catch 3]

By default when you hit the MFA page in ADFS 2016, the identity type displayed is similar to UPN@ADDRESS.COM as you can see in figure 1 below. The MFA page in ADFS 2016 by default uses the value from the upn claim type (“http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn”) to display that same value in the MFA page in ADFS 2016. However, if there is no value for the upn claim, it will fall back to the value of the name claim. Unless you have removed it, by default ADFS has an Acceptance Transform Rule on the “Active Directory” CP trust for the upn claim type. And if you look carefully, the text also changed (compare figure 1 and figure 3).

As you can see in figure 3, it now really shows my upn (jorge@iamtec.net) whereas mail e-mail address uses a different suffix (jorge@iamtec.nl). With the use of Azure AD, the federated/managed domain in AAD is iamtec.nl and not iamtec.net.

image

Figure 3: MFA Page In ADFS 2016 With The Default Value For The UPN Claim Type

To be able to logon with the mail address I have 2 options, either update the userPrincipalName value to match the mail address value in AD or keep it as is and use the alternate logon ID feature in ADFS to target the mail address field in AD. If you choose the first option the value in the MFA page is also updated automatically and you do not need to update Acceptance Transform Rules. If you choose the second option you may need to delete the default Acceptance Transform Rule for the upn claim type and replace it with the following Acceptance Transform Rule:

@RuleTemplate = "MapClaims"
@RuleName = "E-Mail Address To UPN"

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

This new Acceptance Transform Rule for the upn claim type would result in the following for on the MFA page in ADFS 2016

image

Figure 4: MFA Page In ADFS 2016 With The Custom Value For The UPN Claim Type

Is there a catch to the catch? Unfortunately there is! As mentioned earlier for the name claim type, the same would apply to the upn clam type. Some applications connected to ADFS may expect to receive a upn claim value that looks like UPN@ADDRESS.COM instead of MAIL@ADDRESS.COM. By implementing a new Acceptance Transform Rule for the upn claim type you will impact those applications.

To mitigate that impact before making those changes, you would need reconfigure the “Active Directory” CP trust and implement an Acceptance Transform Rule that is similar to or looks like:

@RuleTemplate = "MapClaims"
@RuleName = "Original UPN To Custom UPN Claim"
c:[Type == "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn"%5D
=> issue(Type = "
http://temp.org/identity/claims/orgUPN&quot;, Issuer = c.Issuer, OriginalIssuer = c.OriginalIssuer, Value = c.Value, ValueType = c.ValueType);

…and you would need reconfigure the RP trust of the application that needs the original upn claim value. If RP trust has an Issuance Transform Rule that is similar to or looks like:

c:[Type == "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn"%5D
=> issue(claim = c);

….you would need to delete that Issuance Transform Rule and replace it with:

@RuleTemplate = "MapClaims"
@RuleName = "Custom UPN Claim To Original UPN"
c:[Type == "http://temp.org/identity/claims/orgUPN""http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname"%5D
=> issue(Type = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn&quot;, Issuer = c.Issuer, OriginalIssuer = c.OriginalIssuer, Value = c.Value, ValueType = c.ValueType);

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 MFA Adapter, Claim Types, Claims, Claims Rule Language, Federation Trusts | Leave a Comment »

(2015-07-10) HTTP Error 400 Bad Request – Error When Accessing Claims Based Website

Posted by Jorge on 2015-07-10


Do you have a claims based website and do you get the following error when accessing the website?

image

Figure 1: HTTP Error 400 – Bad Request

Does the problem go away if you remove a large number of claims rules that issue a large number of claims? If yes, the issues is most likely that the "Request header too long", although it is not mentioned. When that happens, in this case, the user is not necessarily a member of too many groups. In this too many claims having generated and presented to the application. The solution is to increase the default HTTP header or packet size. See the first article on the list of articles below to understand how to solve it. However, Instead of increasing the HTTP header or packet size, see if you can optimize the claims rules to process/issue less claims!

After configuring this, reboot the server!!

Additional Information:

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 Active Directory Federation Services (ADFS), Claims, Claims Based Apps, Security Tokens, Troubleshooting | 1 Comment »

(2015-07-04) Displaying The Issued Claims In A Security Token (On Screen)

Posted by Jorge on 2015-07-04


When accessing a federated application, from a troubleshooting perspective, it can be very interesting in knowing/seeing which claims are being send to the application. ADFS itself logs that information in the Security Event Log, assuming auditing has been enabled. However, to know about all the claims send to an application you might need to go through multiple event IDs.

For more information about enabling the auditing of issued claims see in ADFS:

If you have a farm consisting of multiple ADFS STS servers, you need to understand first which of the ADFS STS servers in the farm serviced the issuance of the security token. In summary, it can be quite a pain to get the required information when needed. Now, wouldn’t it great to have a claims-based application that shows the claims from the security token that was issued by the (last) federation system? Yes it would!

So how would you display the issued claims for a specific claims-based application on another claims-based application? That’s easy!

Let’s say that the "Display The Issued Claims" claims-based application is the application that display all the claims from a security token.

Let’s say that the "Collaboration" claims-based (SharePoint) application is the application for which you want to see the issued claims.

Configure the exact same issuance transform rules in ADFS from the RP trust representing the "Collaboration" claims-based (SharePoint) application on the RP trust representing the "Display The Issued Claims" claims-based application. Now tell the user to navigate to the "Display The Issued Claims" claims-based application and ask the user to e-mail the contents of the website by pressing [CTRL]+[A], followed by [CTRL]+[C] and followed by [CTRL]+[V] in an e-mail to the service desk.

In this blog post, the "Ask PFE Platform" guys explains how to setup the website I’m talking about. However, it requires different manual steps to implement it. I used the exact same website and created a brand new deployment script that helps you setup the website in IIS and the RP trust in ADFS. So, let’s get started and see how you can deploy this.

You can download my version of this from here and unpack it on the Windows Server 2012 (R2) where you want to deploy it.

Before running the script, make sure the following is clear:

After unpacking the ZIP file on the server where you want to deploy website, AND taking care of all the points above, execute the script ‘Deploying-Claims-Based-Application.ps1’ that is also available in the unpacked folder. The script will guide you step by step in deploying the website and creating the RP trust in ADFS. The script always specifies what the next step will be before executing it.

After pressing any key, the script will install all required roles and features…

image

Figure 1: Current Step: Initial Screen Warming About Prerequisites – Next Step: Installing Roles And Features

After pressing any key, the script will check if ‘FedUtil.exe’ is available on the local server. If it is not available, the script will abort. ‘FedUtil.exe’ is required to generate the federation metadata of the application, so that a RP trust can be created by using the federation metadata URL of the application.
image

Figure 2: Current Step: Installing Roles And Features – Next Step: Checking Availability Of ‘FedUtil.exe’

After pressing any key, the script will check if ‘New-SelfSignedCertificateCustom.ps1’ is available on the local server. If it is not available, the script will abort. ‘New-SelfSignedCertificateCustom.ps1’ is required to generate a self-signed certificate as the Token Encryption Certificate for the application.

image

Figure 3: Current Step: Checking Availability Of ‘FedUtil.exe’ – Next Step: Checking Availability Of ‘New-SelfSignedCertificateCustom.ps1’

After pressing any key, the script will create a new application pool or use an existing one, depending on what you specify. When the choice is made to create a new application pool, a name and credentials need to be provided for the new application pool.

image

Figure 4: Current Step: Checking Availability Of ‘New-SelfSignedCertificateCustom.ps1’ – Next Step: Creating The Web Application Pool

After pressing any key, the script will create a new website or you can use an existing website and create a subfolder, depending on what you specify. When the choice is made to create a new website, HTTP binding information needs to be specified. When the choice is made to use an existing website, the virtual folder an its path need to be specified. In both cases the HTTPS URL to access the application, including the custom port if applicable, needs to be specified.

image

Figure 5: Current Step: Creating The Web Application Pool – Next Step: Creating The WebSite

After pressing any key, the script will check if SSL is enabled and enforced. If not, HTTPS binding information needs to be specified, including a certificate for SSL.

image

Figure 6: Current Step: Creating The WebSite – Next Step: Enabling SSL

After pressing any key, the script will retrieve ADFS related information (i.e. identifier, token signing certificate and endpoints) to configure the WEB.CONFIG of the application with.

image

Figure 7: Current Step: Enabling SSL – Next Step: Getting ADFS Information

After pressing any key, the script will use ‘New-SelfSignedCertificateCustom.ps1’ to generate a self-signed certificate with the subject you specify. Additional characteristics of the certificate are:

  • EnhancedKeyUsage "Server Authentication"
  • KeyUsage "KeyEncipherment","DigitalSignature"
  • StoreLocation "LocalMachine"
  • ProviderName "Microsoft Enhanced Cryptographic Provider v1.0"
  • AlgorithmName RSA
  • KeyLength 2048
  • SignatureAlgorithm SHA256
  • NotBefore $([datetime]::now.AddDays(-1))
  • NotAfter $([datetime]::now.AddDays(3650))
  • FriendlyName "Show My Claims ASPNET TOKEN" -exportable

image

Figure 8: Current Step: Getting ADFS Information – Next Step: Generating The Self-Signed Certificate

After pressing any key, the script will assign the account used in the application pool Allow:Read permissions in the private key of the certificate.

image

Figure 9: Current Step: Generating The Self-Signed Certificate – Next Step: Assigning The Application Pool Account Permissions On The Private Key Of The Self-Signed Certificate

After pressing any key, the script will copy the website from the specified source folder to the specified target folder of the website of the virtual folder.

image

Figure 10: Current Step: Assigning The Application Pool Account Permissions On The Private Key Of The Self-Signed Certificate – Next Step: Copy The Website Files To The Target Folder

After pressing any key, the script will configure the WEB.CONFIG of the application with the gathered information.

image

Figure 11: Current Step: Copy The Website Files To The Target Folder – Next Step: Confguring The Web.Config Of The Application

After pressing any key, the script will generate the federation metadata for the application based upon the WEB.CONFIG.

image

Figure 12: Current Step: Confguring The Web.Config Of The Application – Next Step: Generate The Federation Metadata For The Application

After pressing any key, the script will try to create the RP trust within ADFS using the federation metadata URL of the application. The issuance authorization rules will allow access for everyone (permit all). The issuance transform rules will send the userPrincipalName (UPN) as nameIdentifier to the application including any other issued claim.

image

Figure 13: Current Step: Generate The Federation Metadata For The Application – Next Step: Create The Relying Party Trust Within ADFS

The script will display all the RP trusts in ADFS and you need to decide if the name you specified for the RP trust is now included in the list of RP trusts. If it is in the list you are done and can specify Y or Yes. If it is not in the list you may need to solve why it did not create the RP trust by checking for example the Event Logs and fix what needs to be fixed. Then you can retry the creation by specifying N or No.

image

Figure 14: Current Step: Create The Relying Party Trust Within ADFS – Next Step: Confirm Creating Of The Relying Party Trust Within ADFS

Assuming you specified Y or Yes, the script ends and displays both the application URL as the federation metadata URL of the application. You can copy the that into a browser and try the application.

image

Figure 15: Script Finished Succesfully

If the federation metadata URL was specified in the browser you would see something similar.

image

Figure 16: Federation Metadata Of The Application

If the application URL was specified in the browser, the application should redirect you to ADFS and possibly ask you to perform Home Realm Discovery (HRD) by telling ADFS from which IdP you are coming from.

image

Figure 17: Home Realm Discovery Within ADFS v3.0 and Higher

Assuming WIA is enabled, the logged on credentials will be used. To configure and support WIA for different browsers, see:

The application now display the issued claims from the security token send to the application (begin of the list)

image

Figure 18: The List Of Issued Claims Within The Security Token

The application now display the issued claims from the security token send to the application (end of the list)

image

Figure 19: The List Of Issued Claims Within The Security Token

Enjoy!

PS: Mylo from the Access Onion has written a blog post about SimpleSAMLphp which is the similar PHP version of an application like this

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 Active Directory Federation Services (ADFS), Claims, Claims Based Apps, Security Tokens | 1 Comment »