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