Hey all,
Recently I was troubleshooting the use of a custom attribute for the shortname of a user with Jamf Connect Menu Bar app.
To be exact, this key:
<key>ShortNameAttribute</key>
<string>attribute</string>
and Jamf Connect Menu Bar logs reporting:
"Unable to read the custom shortname attribute from OIDC"
This when trying to use a custom attribute synced from on-prem AD to Azure, or when you need to define the shortnameattribute in situations where the Kerberos Realm does not match the domain name of the UPN, and the sAMAccountName does not match the prefix of the UPN.
When all is matching defining the shortname to use should not be needed, for instance:
UPN of the user in Azure: std_user@travellingtechguy.dev
Shortname in AD: std_user
Kerberos Realm: TRAVELLINGTECHGUY.DEV
In such setups, using Kerberos via Jamf Connect Menu Bar, or Kerberos in general should be ok. When authenticating with the UPN, Kerberos should be able to fetch the shortname without much problem.
However, with different possible variations like other REALM or sAMAccountName mismatch, things break and you need to provide Kerberos with the real shortname of the account.
First of all, more feasible for testing than anything else imo, you could hardcode the shortname in the JC Menu bar plist by defining it with the following key:
<key>ShortName</key>
<string>Joel</string>
However, that would then need a profile per device, so mainly for testing only.
Nevertheless, you could replace that shortname with a JamfPro variable:
<key>ShortName</key>
<string>$USERNAME</string>
If the inventory record of the device in Jamf Pro has the variable filled in, the value would be inserted upon installation of the profile. So that works fine as well.
Now, for this to work without too much effort, you’d probably need LDAP to be integrated in Jamf Pro to fetch whatever attribute you want/need to use for the ShortName, and probably create an LDAP extension attribute.
Either use the $USERNAME variable if that is mapped to the sAMAccountName:

Or if needed create an LDAP extension attribute:

Which can then be used in Jamf Connect plist via:
<key>ShortName</key>
<string>$EXTENSIONATTRIBUTE_X</string>
Where X is the ID of the Extension Attribute in Jamf Pro:
The ID number is found in the extension attribute URL. In the example URL below, “id=2” indicates the extension attribute ID number:
https://instancename.jamfcloud.com/mobileDeviceExtensionAttributes.html?id=2&o=r
If you do have LDAP integrated, I’d say, go for this option. No additional configuration needed, and it just works.
However, there is indeed another option to achieve this, and this is by using a custom attribute via an additional claim added to the ID token in Azure.
To do this, you’ll first of all need to add the attribute from your on-prem AD as an additional claim in your ID token: https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-claims-mapping#include-the-employeeid-and-tenantcountry-as-claims-in-tokens
NOTE: update 16th FEB 2022 - depending your Azure AD Connect sync settings you may need to expose the samaccountname: https://docs.microsoft.com/en-us/azure/active-directory/app-provisioning/user-provisioning-sync-attributes-for-mapping#create-an-extension-attribute-using-azure-ad-connect or use onpremisessamaccountname https://docs.microsoft.com/en-us/answers/questions/6472/inlcude-onpemise-samaccount-in-azure-ad-claims.html
In the example MS gives here, they are adding ’employeeID’ as an additional claim, but to add the on-prem samaccountname attribute to Azure for instance, the powershell commands I used were:
Add an additional Azure AD Policy which adds the ‘samaccountname’ to the claims:
New-AzureADPolicy -Definition
>> @('{"ClaimsMappingPolicy":{"Version":1,"IncludeBasicClaimSet":"true", "ClaimsSchema":
>> [{"Source":"user","ID":"samaccountname","JwtClaimType":"samaccountname"}]}}') -DisplayName
>> "ExtraClaimSamaccountname" -Type "ClaimsMappingPolicy"
Next you’ll need to get the ObjectID of this new policy via:
Get-AzureADPolicy
As well as the ObjectID of the Jamf Connect App in Azure. The easiest way to get this is to go to the ‘Enterprise app’ blade of Azure and find the Jamf Connect App you are using. The ‘Object ID’ of the enterprise app is what you need:

With the Policy and App object ID we can can then run the command below, with the ServicePrincipal being the Enterprise App Object ID and the other ID being the object ID of the policy we created.
Add-AzureADServicePrincipalPolicy -Id <ObjectId of the ServicePrincipal> -RefObjectId <ObjectId of the Policy>
Now, once you have this configured, the only thing you’d need next is to tell Jamf Connect to use the additional claim to fetch the custom attribute for the shortname.
In my example this would be:
<key>ShortNameAttribute</key>
<string>samaccountname</string>
However, one thing I’d like to highlight here is that there is a difference between Jamf Connect Login, using OIDC, and Jamf Connect Menu Bar, using ROPG.
Hence the keys for both are different. For Jamf Connect LOGIN, the key we need on the plist is “OIDCShortName”:
<key>OIDCShortName</key>
<string>samaccountname</string>
Without sidetracking too much from the purpose of this block, let me quickly elaborate the difference of between features.
For Jamf Connect Login, the OIDCShortname key is to define the accountname of the local account which JC will create on the Mac.
When Jamf Connect Login creates a local account, it uses the pre-fix of the UPN to do so. For instance, if my accountname is std_user@travellingtechguy.dev, then JCL will create a local account with ‘std_user’ as accountname.
However, if we add the OIDCShortname key, we can tell JCL to use another attribute for the accountname, while still adding the pre-fix of the UPN as an alias. In my example below my shortname (fetched via the custom attribute OIDCShortname is ‘standarduser’, while the prefix of the UPN is ‘std_user’:

This can be handy in situation where you need to have the accountname set to a different value than the pre-fix of the UPN for any authentication needs.
Adding the additional claim to Azure and using the OIDCShortName keys totally works fine, like we can also confirm in the Jamf Connect Configuration tool. As you can see, doing an OIDC test returns the additional attribute (in my case the samaccountname) in the token:

However, if we do test ROPG, it seems that things have changed Azure-side. In the past, the additional claims were also added to ROPG flows, but it seems that this is not the case anymore. At least not via the V1 endpoints, while it does work via Azure V2 endpoints. Not sure when this changed to be honest, but more about the V2 endpoint below.
To test this, we can’t use the config tool to grab the token over ROPG (as it only returns tokens in the app for OIDC), but we can use ProxyMan to do so.
For this you need to install ProxyMan (or any other proxy tool capable of decrypting SSL/TLS) and run it while authenticating with Jamf Connect Menu Bar:

I’ll not discuss using ProxyMan too much here, but if you enable the JSON view (after enabling SSL/TLS decryption prior to connecting to Jamf Connect), you will be able to grab the id_token and decode it for instance via https://jwt.io/
This is where you’ll see a difference between the id_token you get via OIDC in the Jamf Connect Configuration tool, and the one you intercept with ROPG via ProxyMan.
The difference seems to be related to the difference in authentication flow used by OIDC and ROPG, and Azure V1 endpoints do not seem to include the custom claims in ROPG flows.
But what about that V1 and V2 endpoints? Well, Jamf Connect Menu Bar app (as per design, including version 2.5) by default uses the V1 endpoint when you configure it with Provider set to “Azure”:
<key>Provider</key>
<string>Azure</key>
So, it does not work? No panic, there is a workaround. Jamf Connect can be configured to use a variety of custom, less main stream, iDPs. For that we set the provider key to Custom and we define additional keys like the DiscoveryURL.
The trick to make Jamf Connect Menu Bar use the Azure V2 endpoint, and hence to get an id_token which has the additional claims, is to configure it in a more custom way instead of the default ‘Azure’ configuration.
Hereby an example of a configuration plist to achieve this:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IdPSettings</key>
<dict>
<key>Provider</key>
<string>Custom</string>
<key>ROPGID</key>
<string>1d884884-1111-2222-3333-71548a60aa76</string>
<key>DiscoveryURL</key>
<string>https://login.microsoftonline.com/af72a024-AAAA-BBBB-CCCC-fd66bf369fcc/v2.0/.well-known/openid-configuration</string>
</dict>
<key>Kerberos</key>
<dict>
<key>AutoRenewTickets</key>
<true/>
<key>Realm</key>
<string>DIDYOUTESTIT.COM</string>
<key>ShortNameAttribute</key>
<string>samaccountname</string>
</dict>
<key>SignIn</key>
<dict>
<key>AutoAuthenticate</key>
<true/>
<key>RequireSignIn</key>
<true/>
</dict>
</dict>
</plist>
The 2 important keys here are:
<key>Provider</key>
<string>Custom</string>
and
<key>DiscoveryURL</key>
<string>https://login.microsoftonline.com/af72a024-AAAA-BBBB-CCCC-fd66bf369fcc/v2.0/.well-known/openid-configuration</string>
This with ‘af72a024-AAAA-BBBB-CCCC-fd66bf369fcc’ set to the tenantID of your Azure tenant. Also note the v2.0 in the URL.
Furthermore I added the Kerberos config in the plist, which allows me to get Kerberos tickets, mount shares (via additional configuration profile), etc… all based on the correct shortname I need for Kerberos to work. As discussed above.
With this custom setup, forcing Jamf Connect Menu Bar to use the V2 endpoints, you do get the custom attribute in the ID Token via ROPG, just like with OIDC:
{
"..."
"unique_name": "std_user@travellingtechguy.dev",
"upn": "std_user@travellingtechguy.dev",
"..."
"samaccountname": "standarduser"
}
After successfully connecting to Jamf Connect Menu Bar with a V2 config like above, you’ll also see that the com.jamf.connect.state.plist in the preferences of the macOS User Library does contain the custom attribute:
<key>CustomShortName</key>
<string>standarduser</string>
And Kerberos ticket are retrieved correctly, based on the correct shortname.
Azure Happy, Jamf Connect Happy, Kerberos Happy, … all works!
That’s it! As always, if you liked the post, hit the like button, tell your friends about it and leave a comment down below!
Brgds,
TTG

Apple ecosystem enthusiast, geek, tech gadget freak, Belgian living in the Netherlands
Manager Technical Support | Jamf
Thank you!
Is there any kind of similar magic to be done to get this working for MFA-enabled users?
No, as per the manual using a custom attribute with the token does not work. But you can use a jamf pro variable is you have ldap enabled
Hey TTG
Love the site mate, got a few questions for you about this post
1st: are you pushing this profile as a computer or user level profile
2nd: do variables such as $EXTENSIONATTRIBUTE_X or $Email still work on computer level config profiles if LDAP is enabled
3rd: Seen as JC does not create a MDM enabled users account, how can you get over that
cheers
Hey Mark!
1: Computer level. No need for user level here and I stay away from user level profiles as much as I can.
2: Variables like $EMAIL are taken from what is populated in user and location on the inventory record. Regardless of how it has been populated. LDAP or manually.$EXTENSIONATTRIBUTE_X same, and if those are LDAP linked or even scripted link, they update with inventory update.
3: The issue is not that JC in se does not create MDM capable users. The problem is with ‘skipping account creation’ in the prestage. When you skip asscount creation, user level MDM capability is disabled in macOS as for local account only the account logged in / created when the MDM profile installs gets user level MDM capabilities. Knowing that Big Sur does not allow the Jamf Binary to enable replace the MDM profile anymore, we can not make any user MDM capable after the facts anymore. Unless you remove MDM profile and re-enroll, OR if you do NOT skip account creation, let the user create an account via setup assistant, then install Jamf Connect and at next login MIGRATE the account.
Thanks!
I had to set acceptMappedClaims to true in my JC manifest to make this work. I also had to use the policy created from https://docs.microsoft.com/en-us/answers/questions/6472/inlcude-onpemise-samaccount-in-azure-ad-claims.html. My tenant only had onpremisessamaccountname.
Note: Setting acceptMappedClaims to true may create a security risk because it skips needing a custom signing key. At least from multitenants…I think. 😉
Hi! In your blog you explain how to add a custom attribute via an additional claim to the ID token in Azure. You use powershell to configure this custom attribute.
I was wondering if powershell is necessary here. If I would manually add an additional claim in my “Jamf Pro” app in Azure, wouldn’t that have the same result? The reason I ask is because I’m planning to change our SSO Enrollment Customization with Jamf Connect and Azure setup, such that the shortname will be based on our ‘on-premise AD’ sAMAccountName attribute. At this moment I still use a shortname based on the Azure UPN. In the guide mentioned below by Sean Rabbitt it is explained how to accomplish this by adding an additional claim in the Jamf Pro Azure app. Once configured via this guide, will Jamf Connect be able to fetch the sAMAccountName attribute to use as as a custom shortname or do I still need to use your powershell instructions?
https://github.com/sean-rabbitt/Jamf-2021-Sessions/blob/main/1114%20-%20Decoding%20SAML%20-%20How%20to%20set%20up%20SSO%20quickly%20in%20Jamf%20Pro/Enrollment%20Customizations%20and%20Jamf%20Connect%20with%20Azure.pdf
Thank you!
Depends where the attribute lives. If it is already an attribute which exists in your Azure tenant, hence possible to be added in the token, you’re fine. But if it is an on-prem attribute, which is not synced by default to Azure, you need to add it to your claim via powershell.
That makes sense. Thank you!
You mention Jamf Pro offers the possibility to use internal variables like $EMAIL in config profiles. I’ve experimented with this. My goal is to use the emailaddress of the user to sync some keychain items. However, I’ve noticed that the device config profile is set sooner then a new user is added to “Users and Location” in Jamf Pro via “/usr/local/bin/jamf recon -endUsername”. I end up with a config profile that has an empty string in the profile in stead of the emailaddress of the user. Therefore I’m experimenting with the Jamf Connect Keychain Syncing function. This will use the user info stored in com.jamf.connect.state. In our case, this preference file contains the ‘displayName’ key that is equal to the upn and emailaddress of the user. I would like to use that info to sync some keychain items. However, the Jamf Connect Admin guide only mentions <> as a possible variable. I’ve tried to use <> but this didn’t work. I’ve also tried <<email>> without success.
Do you know if Jamf Connect allows other variables than shortname?
Sorry, it seems a double less-than and larger-than brackets has a special meaning WordPress. So, I was trying to say that I tried the Jamf Connect internal variable less-than, less-than bracket email larger-than, larger-than bracket. This did not work. Are there any other variables I can use in Jamf Connect than shortname?
Yeah the brackets do not parse well in WordPress comments.
Only the variable mentioned here are recognised by Jamf Connect: https://docs.jamf.com/jamf-connect/2.8.0/documentation/State_Settings_and_User_Status.html?hl=variable
And see the note at the bottom which is also related to left and right brackets.
Thank you! The fullname variable is what I needed as this is identical to the Azure emailaddress of the user in our organisation. I completely missed that part of the admin guide.
Yeah it’s not the most highlighted section in the guide indeed! Good to see it gave you what you need!
We’re trying to get jamf connect login to use the short name while creating the local account. We followed these instructions but for some reason when we add the policy to add an additional claim added to the ID token in Azure. we’re getting the error “unable to load identity provider”. are we missing some requirenment? or have things changed. without the policy in place everything works fine, we’re getting tokens just without the shortname (sAMAccountName).
Hmm that’s weird, because to load the identity provider in the login window… that is done prior to authentication so there is no token or communication done. Only loading the login webapp. Unless there is some typo in the config profile?
I should mention that we’re seeing this error in Jamf connect configuration app. it works fine without the claims mapping policy being added. We’re getting tokens and all. but as soon as we enable the policy it throws the error “unable to load identity provider”, no changes are being made in the configuration profile. Are we missing something on the azure side config?
No, only things I did was what I wrote in the post. Nothing more than those powershel commands.
Are you using the configuration app version 2.6 or above?
We’re using Jamf connect configuration 2.8.0. We got arround the error by setting the acceptMappedClaims property to true in the application Manifest in azure.
This is from the microsoft article you referenced in your article.
“Security considerations
Applications that receive tokens rely on the fact that the claim values are authoritatively issued by Azure AD and cannot be tampered with. However, when you modify the token contents through claims-mapping policies, these assumptions may no longer be correct. Applications must explicitly acknowledge that tokens have been modified by the creator of the claims-mapping policy to protect themselves from claims-mapping policies created by malicious actors. This can be done in one the following ways:
Configure a custom signing key
Or, update the application manifest to accept mapped claims.
Without this, Azure AD will return an AADSTS50146 error code.”
However we’re still not getting the samaccount name passed to jamfconnect login via the OIDCShortname key
OIDCShortName
samaccountname
I did however noticed a difference in your screenshot user info endpoint is login.microsoftonline.com and mine says graph.microsoft.com. Can that be the problem?
Oh indeed! The acceptMappedClaim is needed indeed. Sorry did not think about that but indeed part of the shared workflow.
The endpoint must be login.microsoftonline.com as well indeed!
Thank You for this info.
Can you reccomend a way to change the User Info Endpoint.
It’s getting it from the token and I assume it’s from our enterprise app settings but I can’t seem to find what it is.
The Auth and the Token endpoint are set to microsoftonline.com but the user info endpoint is not for some reason.
We Found the problem,
Our Azure AD Connect was not syncyng the additional extension attributes. We had to adjust the settings to include the sAMAccountName attribute.
see here: https://docs.microsoft.com/en-us/azure/active-directory/app-provisioning/user-provisioning-sync-attributes-for-mapping.
The other change we had to do is in the ClaimsMappingPolicy. We had to use
“onpremissessamaccountname” instead of “samaccountname”.
we found the claim named “”onpremissessamaccountname” with Microsoft graph explorer, where you can sign into see available claims. https://developer.microsoft.com/en-us/graph/graph-explorer.
Hope this helps others
Hey Goran! Funny, I just added a note on the post yesterday. If by any chance you were working with one of my colleagues in Support I may have been discussing in the back end, resulting in the additional note.
Seems I had the extension attributes synced prior to testing and writing this post. However, only difference is that I am not using the onpremissessamaccountname in the ClaimsMapping policy but really samaccountname. Still trying to figure out the reason for the difference.
In any way, thanks for the update as it will help others for sure.
Hey TTG, Yes I was working with support yesterday.
this is what we currently have in place.
New-AzureADPolicy -Definition @(‘{“ClaimsMappingPolicy”:{“Version”:1,”IncludeBasicClaimSet”:”true”, “ClaimsSchema”: [{“Source”:”user”,”ID”:”onpremisessamaccountname”,”JwtClaimType”:”samaccountname”}]}}’) -DisplayName “ExtraClaimSamaccountname2” -Type “ClaimsMappingPolicy”
it still shows as “samaccountname” in Jamf connect configuration app.
Thanks! Indeed I recognise the naming 🙂. Yes indeed the name which shows up is what you define after the JwtClaimType. I’ll try again to confirm if I just made a typo when I wrote this, or of I somehow mamaged to use samaccountname everywhere in the command.
Just to know, in Azure AD Connect, what shows up as the attribute you selected to expose? Onpremisesama
or sama?
Azure Ad connect Showed samaccountname.
Ok! Then it all matches with what I have and I only made a typo in the command + ommited the sync part 🤦♂️