The importance of the secure token
I’ve already talked about my struggles and findings around the Secure Token in a previous article. The gist of it is that I manage an environment where all computers are shared, and none of the users have a local account (we are still AD-bound).
In this situation, managing macOS updates is very tricky. Since I work for a school system, I cannot rely on users (who might be students) to update the computers, nor can I remotely push macOS updates during the day since machines might be in use for classes. Even DDM (Declarative Device Management) commands are unsatisfactory, as I cannot reliably ensure the computer will update outside of class hours.
Ever since I’ve started building my Jamf instance, the only reliable and controllable way I have found to update macOS has been to deploy the full installer, and use the startosinstall command.
However, with Apple Silicon Macs, this requires to have an account that holds a Secure Token. Active Directory accounts never recieve a Secure Token.
In the past, I found a trick that allowed an admin account (created via PreStage Enrollment) to grant itself the Secure Token. But since macOS Tahoe, this no longer works.
Right now, as of writing this post, the only way an account can obtain a Secure Token is if three conditions are met:
- The Bootstrap token has been escrowed to the MDM server
- The account is a local account (or a mobile account, which is functionally local)
- A login has been initiated from the login window
Since macOS Tahoe, the first conditions is automatic, there is not longer a need to manually escrow the Bootstrap Token.
For my admin account, the second condition is met.
However, the third condition is a pain. My admin account is a technical account and should never log in to the computer. I am not going to travel around my area to manually log into the 2500 Macs I manage!
Autologin to the rescue
The solution is to set up an automatic login for our admin account. However that comes with a few technicalities.
Setting up the autologin
As part of our deployment setup I’ve added a script that configures autologin for our technical account. Normally running the native command should work, but I’ve found that it is not always reliable:
/usr/sbin/sysadminctl -autologin set -userName "${technical_account}" -password - 2>&1
Because of this, I rely on a fallback system that uses third-party Python tools to enable autologin and create the /etc/kcpassword file. My script will therefore download the two tools and use them to enable autologin to my technical account:
/usr/bin/curl --silent --output "$BIN_DIR"/enable_autologin https://raw.githubusercontent.com/xfreebird/kcpassword/refs/heads/master/enable_autologin
/usr/bin/curl --silent --output "$BIN_DIR"/kcpassword https://raw.githubusercontent.com/xfreebird/kcpassword/refs/heads/master/kcpassword
xattr -c "$BIN_DIR"/enable_autologin
xattr -c "$BIN_DIR"/kcpassword
chmod a+x "$BIN_DIR"/kcpassword
chmod a+x "$BIN_DIR"/enable_autologin
"$BIN_DIR"/enable_autologin ${technical_account} ${technical_password}
Taking all of this into account, along with some extra checks, here is what my script looks like:
#!/bin/bash
#
# Add autologin to technical account
# Get JAMF parameters
technical_account="$4"
technical_password="$5"
# Set autologin
AUTOLOGIN_OUTPUT="$(printf '%s' "${technical_password}" | /usr/sbin/sysadminctl -autologin set -userName "${technical_account}" -password - 2>&1)"
if [[ -n "$AUTOLOGIN_OUTPUT" ]]; then
echo "An error occured : $AUTOLOGIN_OUTPUT"
echo "Fallback to another system"
BIN_DIR="/usr/local/bin/"
if [ ! -e "$BIN_DIR/python3" ]; then
echo "Python3 is not installed, fallback will not work"
exit 1
fi
/usr/bin/curl --silent --output "$BIN_DIR"/enable_autologin https://raw.githubusercontent.com/xfreebird/kcpassword/refs/heads/master/enable_autologin
/usr/bin/curl --silent --output "$BIN_DIR"/kcpassword https://raw.githubusercontent.com/xfreebird/kcpassword/refs/heads/master/kcpassword
xattr -c "$BIN_DIR"/enable_autologin
xattr -c "$BIN_DIR"/kcpassword
chmod a+x "$BIN_DIR"/kcpassword
chmod a+x "$BIN_DIR"/enable_autologin
if ! "$BIN_DIR"/enable_autologin ${technical_account} ${technical_password}; then
echo "Fallback system did not work."
exit 2
fi
fi
# Verification if autologin is on
if /usr/sbin/sysadminctl -autologin status | grep OFF; then
echo "Unable to activate autologin"
exit 3
fiRemove autologin
After the technical account logs in for the first time, we obviously do not want autologin to remain active. The mechanism should therefore be disabled immediately after that initial session starts.
This requires a script to be executed at login. There are several ways this can be done: with a LaunchAgent, with Jamf’s login trigger or with Outset. In our case I chose Outset since we already use it for other scripts.
The script will perform three tasks: deactivate the autologin, remove itself so that it does not run for the other users (not that it will do any harm, it is just that is becomes unnecessary) and finally log out or restart the computer to go back to the login window.
This will look like this (I’ve added some logging for debugging purposes):
#!/bin/bash
#
# Run jamf script to grant secure token to technical account
technical_account="my_admin_account"
OUTSET_DIR="/usr/local/outset/login-privileged-every"
SCRIPT_NAME="checkSecureToken.sh"
echo "$(date "+%d.%m.%G - %T") - Login user $CURRENT_USER"
if [[ "$CURRENT_USER" != "$technical_account" ]]; then
# Do not run if logged in user is not the technical account
# (this should not happen)
echo "$(date "+%d.%m.%G - %T") - User is not $technical_account"
exit 0
fi
# Check the secure token status
check="$(/usr/sbin/sysadminctl -secureTokenStatus "$technical_account" 2>&1)"
if echo "$check" | grep -c ENABLED; then
echo "$(date "+%d.%m.%G - %T") - Token granted to technical account"
else
echo "$(date "+%d.%m.%G - %T") - Token NOT granted to technical account"
fi
sysadminctl -autologin off
rm -f /etc/kcpassword >>/etc/sem/checkSecureToken.out 2>&1
mv "$OUTSET_DIR/$SCRIPT_NAME" /tmp/ >>/etc/sem/checkSecureToken.out 2>&1
shutdown -r nowSecure token is a strange beast
For reasons that are totally unknown and baffling to me, timing is critical.
If this autologin workflow is executed right after setting up the Mac, it works very reliably.
However, if any other login occurs before the technical account’s autologin completes, the secure token will not be granted, even if the account that logged in is a network account that does not receive a Secure Token aynway !
What’s even more surprising, is that when that happens, the technical account can still get the Secure Token but only through a manual login at the login window. This means macOS handles manual logins and autologins differently under the hood when establishing cryptographic chains.
Conclusion
Granting the secure token to a technical account can be done by setting up autologin, However, this will only work on a computer that has been reinstalled and before any other user logs in.
Once the technical account successfully receives its Secure Token, it will retain it across future major macOS upgrades.