ADFS 3.0 Custom attribute in SAML token - saml-2.0

I am setting up a relaying party trust (IDP) for an application a SP provides. Problem is that the SP requires a "customer ID" to be prefixed the username. E.g on-prem AD user john#company.com logges on and SP requires 001john#company.com to access the application.
How do i configure ADFS 3.0 to include the "customer id" in SAML token?
Error i receive now is: "The customer Id in the username john#company.com does not match the ones configued for the partner [001].
SP uses IBM FIM as federation solution.
Metadata is set up on both SP and IDP side.
Thanks.

You can append a string e.g.
c:[type == "http://someclaim"]
=> issue(type = "http://anotherclaim", value = "001" + c1.Value );
but there is not enough detail.
Do you always add "001" or does it vary?
Which claim do you want to alter?
Update
Have a normal LDAP rule that takes email and creates http://company.com/Temp1
(The dropdown is editable).
Then:
c:[type == "http://company.com/Temp1"]
=> issue(type = "http://company.com/Temp2", value = "001" + c.Value );
Then use a transform rule to transform http://company.com/Temp2 to NameID with a format of email.

Related

Look up user in AAD based on AADB2C attribute value

If I have a user in Aure AD B2C that was created based on an Azure AD (enterprise) identity (as described here: https://learn.microsoft.com/en-us/azure/active-directory-b2c/active-directory-b2c-setup-aad-custom), is there an attribute stored in AADB2C that will allow me to look up (using Graph API or similar) the user object in AAD? I see that among the AADB2C attributes there is userPrincipalName and issuerUserId but it's not obvious to me if either of these match any value stored in AAD.
thanks!
Martin
For an external account, the external issuer (i.e., Azure AD) and the external user identifier (i.e., the object identifier of the Azure AD user) are written to the "userIdentities" property of the user object in the Azure AD B2C directory, where the "issuerUserId" property contains the Base64-encoding of the external user identifier:
{
"userIdentities": [
{
"issuer": "contoso.com",
"issuerUserId": "Mjk2NzdlNTAtY2MwZS00MmU5LWJhNWMtZjFmMDdkZTUwMDhm"
}
]
}
To find the user object by the external account, you can invoke the following Graph API operation, where the "x/issuerUserId" value is set to the hexadecimal-encoding of the external user identifier:
GET https://graph.windows.net/myorganization/users?$filter=userIdentities/any(x:x/issuer eq 'contoso.com' and x/issuerUserId eq X'32393637376535302d636330652d343265392d626135632d663166303764653530303866')
Update:
The issuerUserId from the external identity provider should be treated as string and not decimal. In above example, when you base 64 decode "Mjk2NzdlNTAtY2MwZS00MmU5LWJhNWMtZjFmMDdkZTUwMDhm" - it returns a guid 29677e50-cc0e-42e9-ba5c-f1f07de5008f. In case of facebook, the issuerUserId will be a number, but still should be treated as string.
Next step will be to use string to hexadecimal converter and then use that value in the query.

Sending group name as claims in ADFS 3.0

I need to add a claim rule for a RP in ADFS 3.0 to issue all the group names to which the user is added as claims if the group names are, say A, B, C. How can I achieve this? As of now, I'm using LDAP attribute Token-Groups - Unqualified Names which will provide all group names which he is part of.
Filter the groups with regex.
c:[Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname", Issuer == "AD AUTHORITY"]
=> add(store = "Active Directory", types = ("http://claims/MyGroups"), query = ";tokenGroups;{0}", param = c.Value);
then something like:
c:[Type == "http://claims/MyGroups", Value =~ "^(?i)A"]
=> issue(claim = c);
and so on.

Query AD Group to get Custom Attribute on it

I am trying to get a Custom Attribute of a Group in Custom Claim rule.
The problem is no matter what i do, it always queries against User.
Here is how my Custom Claim Rule looks like:
//Rule to get all the Groups user is part of:
c:[Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname", Issuer == "AD AUTHORITY"]
=> issue(store = "Active Directory", types = ("http://schemas.xmlsoap.org/claims/Group"), query = ";tokenGroups;{0}", param = c.Value);
//Rule to fetch url attribute that is on the Group.
c:[Type == "http://schemas.xmlsoap.org/claims/Group"]
=> add(store = "Active Directory", types = ("http://temp/urlsOnGroup"), query = ";url;{0}", param = c.Value);
When this executes, i see an error in the event log on AD FS Server which states that it is trying to find User with GroupName.
How do i specify this Rule so that the last query happens against the Group Name instead of User
Error Message:
Microsoft.IdentityServer.ClaimsPolicy.Language.PolicyEvaluationException:
POLICY0018: Query ';url;{0}' to attribute store 'Active Directory' failed:
'POLICY3826: User name 'GroupName' in LDAP query ';url;GroupName' is not in the
required 'domain\user' format. POLICY3824: The LDAP query to the Active
Directory attribute store must have three parts separated by semicolons. The
first part is the LDAP query filter, the second part is a comma-separated list
of LDAP attribute names, and the third part is the user name in 'domain\user'
format.'. --->
Microsoft.IdentityServer.ClaimsPolicy.Engine.AttributeStore.AttributeStoreQueryF
ormatException: POLICY3826: User name 'GroupName' in LDAP query ';url;GroupName'
is not in the required 'domain\user' format. POLICY3824: The LDAP query to the
Active Directory attribute store must have three parts separated by semicolons.
The first part is the LDAP query filter, the second part is a comma-separated
list of LDAP attribute names, and the third part is the user name in
'domain\user' format.
I want to avoid writing Custom Attribute Store if possible. I have already did that but i am trying to find native way to query agains AD Security Groups.
The required format is e.g.
c:[Type == "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/ou"]
=> issue(store = "Active Directory", types = ("http://schemas.company.co.nz/claims/guid"), query = "(ou={0});objectGuid;domain\user", param = c.Value);
The "domain" needs to be the domain for ADFS. The "user" can be anything.
Note rule is free form so may have format errors but you get the idea!

What is the proper way to get some specific user attributes from Active Directory via LDAP C API?

I am trying to get some user attributes from Active Directry using Windows LDAP API. I am using:
Active Directory Version: The one that comes with Windows Server 2012
LDAP version: 3
Wldap32.lib version: The one that comes with Windows 10 x64
Eg:
PCHAR myAttributes[4];
myAttributes[0] = "DistinguishedName";
myAttributes[1] = "DisplayName";
myAttributes[2] = "PasswordExpired";
myAttributes[3] = "mail";
ldap_search_s(
myLdapConnection, // Ldap connection
myDomain, // DN to start search
LDAP_SCOPE_SUBTREE, // Scope
myFilter, // Filter
myAttributes, // Retrieve list of attributes
0, // Get both attributes and values
&mySearchResult // [out] Search results
);
It returns DistinguishedName, DisplayName and mail attributes, but does not reuturn the PasswordExpired attribute.
I queried with some other attributes and it looks like it does not return attributes with boolean values as well as the EmailAddress attribute.
Why does it not return PasswordExpired attribute?
What about EmailAddress ?
Is there a difference between EmailAddress and mail ?
There is no PasswordExpired LDAP attribute in Active Directory. To build your query look at this URL for attribute names in standard Active Directory schema https://msdn.microsoft.com/en-us/library/ms675090(v=vs.85).aspx. To check if password for given account is expired you'll need to check userAccountControl attribute, which is actually value storing flags of different states of user account https://msdn.microsoft.com/en-us/library/ms680832(v=vs.85).aspx. There is IADsUser interface that will translate this all for you in case you don't have to stick just to LDAP https://msdn.microsoft.com/en-us/library/aa746343(v=vs.85).aspx
You will find current primary email address in mail attribute. There is no EmailAddress LDAP attribute, unless you meant E-mail-Addresses which is CN for the same schema attribute as mail, so no difference there.
See above. In general if you do not have compelling reason to stick just to C/LDAP I'd recommend you to use .Net Framework instead. Otherwise you have a lot of work ahead of you - not just interpreting bit flags like in case of password expiration but possibly also with different authentication methods, different structures capturing time and date, accounting for timezones, UTF, chasing referrals and other stuff you might need depending on complexity of what you want to achieve. You will be productive much faster in .Net Framework. See DirectoryServices https://msdn.microsoft.com/en-us/library/mt481534(v=vs.110).aspx namespace or Security namespace https://msdn.microsoft.com/en-us/library/mt481561(v=vs.110).aspx for details.

Get users from Acctive Directory Group

I created an Active Directory domain name 'ADDOMAIN2' having a group name "CommonUsers" having 8 users. but when I do a Directory Search for users in group "CommonUsers" it returns zero result. hers is my code
DirectorySearcher searcher = new DirectorySearcher();
DirectoryEntry directoryEntry = new DirectoryEntry(string.Format("LDAP://{0}", "ADDOMAIN2"), "Administrator", "p#S$w0rd");
string dnPath = directoryEntry.Properties["distinguishedName"].Value.ToString();
// string path = string.Format("LDAP://{0}/{1}{2}", "ADDOMAIN2", "", dnPath);
string path = "LDAP://ADDOMAIN2/CN=CommonUsers,DC=ADDomain2,DC=ADDomain01,DC=WaveDomain";
directoryEntry.Path = path;
searcher.SearchRoot = directoryEntry;
searcher.Filter = "(&(objectCategory=person)(objectClass=user))";
SearchResultCollection rs = searcher.FindAll();
Any Idea what is wrong here?
Thanx
Try using some external LDAP browser (like the old and free version 2.6 of Softerra LDAP Browser) to check whether your query string is really pointing to the correct location.
DirectorySearcher is not used to find users inside a group. It's used to find objects under a base path. Since there is no user objects placed under your AD group object, you won't find anything.
In most cases, you can find the user objects in an AD group from its member attribute. Beware that AD group can contain either group or user. So, some of the entres there may be group. In some cases, the member attribute does not contain AD group nor AD user, it's containing a Foreign Security Principal. This happens if your user is coming from another forest. The primary group is also handled differently. Even "Domain User" is primary group of most of the users in AD, its member attribute doesn't contain anything at all. There are a lot other oddities that makes enumerating an AD group object really hard.
Fortunately, in .NET 3.5, Microsoft provides some useful classes in the framework to do the dirty work for you. Check out System.DirectoryServices.AccountManagement
To get some quick examples, you can check out this codeproject article
Your code should be something like this.
PrincipalContext context = new PrincipalContext(ContextType.Domain, "yourdomain.com");
GroupPrincipal groupPrincipal = GroupPrincipal.FindByIdentity(context, IdentityType.SamAccountName, "Domain Users");
foreach (Principal principal in groupPrincipal.GetMembers(false))
{
Console.Out.WriteLine(principal.DistinguishedName);
}
Console.In.ReadLine();

Resources