SecureToken for Admin Accounts

markc0
New Contributor III

Hi, I have quite a few macs with admin accounts on 10.13.6 that dont have a secure token (viewed by running sysadminctl command).
I want to add the secure token silently without involving the user via ssh or someother tool, as i have seen the users of the machines have this secure token.
I have tried sysadminctl -secureTokenOn "admin account" -password "password" but get Operation is not permitted without secure token unlock.
i know that sysadminctl -adminUser user -adminPassword “password” -secureTokenOn "admin account" -password “password” Will probably do it but i cant go asking for the user password

Does anyone know of another way?

36 REPLIES 36

jrb
New Contributor III

Following...
Just went through this and couldn't come up with a solution that worked.
Had to wipe and re-install macOS

m_donovan
Contributor III

Have you verified that the "admin" account has a secureToken?

sysadminctl -secureTokenStatus <username>

My (very limited) understanding is that only a secureToken enabled account can give a secureToken to another user.

markc0
New Contributor III

m.donovan yes, i ran the sysadminctl command to verify this.

alexjdale
Valued Contributor III

The sad fact is that you need two passwords to give someone a Secure Token: their own password, and the password of an admin account with a Secure Token. It is totally scriptable but the user has to participate.

You can easily get yourself into a situation where nobody knows a usable local admin password and the system cannot be encrypted. You need to start over. Apple is touting this as making the OS very secure, which it does, but at a huge cost. It's bad design for enterprises.

jrb
New Contributor III

Apple's enterprise support suggested re-running the first boot AppleSetup and creating a new admin account (which should have created a secure token for that account), but it didn't.

HASysOps
New Contributor

SecureToken is garbage. We've had to wipe and redeploy our devices where SecureToken has broken for all users.

crbeck
Contributor

Are your users Administrators on their Macs? Because they would need to be to grant another user account a SecureToken, even if you had their password.

This isn't really helpful post-deployment, but this is what I have planned for my deployment:
I'm using a script to activate FileVault as my admin user (with EncryptedStrings for the password) which so far has reliably given the admin user the SecureToken as long it is run before a user signs in (my DEP process has the Account Settings configured to skip account creation, just creates the management account and my admin user). So i'm taking over the login window for a few seconds before they sign in.

fdesetup enable -user "Admin" -password "password"

The user has to sign in around a tech so they get the SecureToken prompt and can be given a SecureToken to unlock their own machine. Local techs have their own local admin accounts on the Mac so I'll use

sysadminctl -adminUser "Admin" -adminPassword “password” -secureTokenOn "localAdmin" -password “password”

So that local techs can grant SecureToken without my Admin account.

easyedc
Valued Contributor II

Had a similar issue earlier this year (see my post) where Apple came back and basically said the only option would be to erase and reinstall to get an account which could enable secure token (i.e. one created at initial setup). A few weeks ago someone mentioned that @rtrouton had some insight into 10.13.5+ getting a token after the fact, but I haven't tried that yet.

yadin
Contributor

The admin account created by JAMF on first boot during DEP enrollment in MDM is not created with securetoken. Because no account has a token, you can't add a token. This catch22 should not be possible, which is Apple's fault, and the account made by JAMF should have a token which I want to say is JAMF's fault, unless Apple is once again not giving sauce to the product they indicate we should be using.... Either way, until this is fixed all our new hardware is half bricked, has service limits, and can't dual boot. Or, we ditch JAMF and do entirely manual deployments to get full operation. Lose lose.

TTG
Contributor
Contributor

@ebonweaver sorry but your claims are just not accurate. please have a look at my reply here: Secure Tokens

yadin
Contributor

Sorry to say, my statements are very much accurate. I'm aware you can script your way out of the problem, we're looking for the product to not require this or force a change of workflow to compensate.

TTG
Contributor
Contributor

I am not scripting anything Sir. See other topic.

rblaas
Contributor II

I want to chip in.. :)

I to have this weird problem. But....
My local admin DOES have a secure Token. but still I am unable to add the secure TOken to a (mobile) user account who has no Secure Token

 sysadminctl interactive -secureTokenStatus admin
2019-04-18 07:47:12.246 sysadminctl[1612:42740] Secure token is ENABLED for user Admin
sysadminctl interactive -secureTokenStatus jdoe
2019-04-18 07:44:30.937 sysadminctl[1610:42422] Secure token is DISABLED for user John Doe
sysadminctl -interactive -secureTokenOn jdoe -
2019-04-17 16:32:51.718 sysadminctl[1536:36268] Operation is not permitted without secure token unlock.

if anyone have any ideas??!!

TTG
Contributor
Contributor

@rblaas

You need to provide token holder and password to “unlock”:

sysadminctl -adminUser admin -adminPassword addAdminUserPasswordHere -secureTokenOn jdoe -password addjdoePasswordHere

And then “diskutil apfs updatePreboot /“ to allow that user to unlock FV at boot

rblaas
Contributor II

@frederick.abeloos Tried, same result....

TTG
Contributor
Contributor

@rblaas diskutil apfs listcryptousers /

Is the UUID you see in the list the same as the UUID of your admin user?

If “admin” is really an admin, and if he really has a token, your admin user UUID should be listed in the reply of thatiscryptousers command

rblaas
Contributor II

@frederick.abeloos

Yep UUID's are the same and Admin = real admin

so I am very confused!

TTG
Contributor
Contributor

@rblaas tried with sudo?

rblaas
Contributor II

ClassicII
Contributor III

@rblaas

What is the error output from the command @frederick.abeloos gave you ?

rblaas
Contributor II

I found my problem... I was using quotes (double quotes) and there was no need to use quotes.

This fixed my problem

bsuggett
Contributor II

Additionally,

The sysadminctl command doesn't output proper return codes. So even if the command fails with the standard "Operation is not permitted without secure token unlock.", the exit code is still 0 and always is 0 which is bad. (At least in 10.13)

Eskobar
Contributor

@bsuggett  am having the same issue, did you find a solution?

 

johntgeck
Contributor

Still running into the dreaded "Operation is not permitted without secure token unlock."
Secure token is enabled for the admin acct called in the script. Syntax is as below, admin user & password are defined as parameters 4 & 5, respectively.

#!/bin/bash

currentUser=$(who | grep "console" | cut -d" " -f1)

userPwd=$(osascript << EOF
text returned of (display dialog "Please enter password for $currentUser to allow FileVault encryption" default answer "xxxxxxxxx" buttons {"OK"} default button 1 with hidden answer)
EOF
)

echo "Enabling secure token for $currentUser"
sysadminctl -adminUser $4 -adminPassword $5 -secureTokenOn $currentUser -password $userPwd

 

mlarsen21
New Contributor II

@johntgeck I just tried your script and got the same error.

Then ran my iteration here and it does work.. just prompts for an additional pop up from sysadminctl 

#!/bin/bash


#get logged in user
currentuser=$(/bin/ls -la /dev/console | /usr/bin/cut -d ' ' -f 4)

user_entry=""

#prompt user for their password
while  [ "$user_entry" = "" ] ; do
	
	user_entry=$(osascript -e '
tell application "Finder"
	activate
	try
		display dialog "Please enter local password" with title "Assign SecureToken" default answer ""
		set user_entry to the (text returned of the result)
	on error number -128
		set user_entry to ""
	end try
	return user_entry
end tell')
	
done
echo $user_entry

#pass info into terminal to grant token from admin user

sudo /usr/sbin/sysadminctl -secureTokenOn $currentuser -password $user_entry interactive || -adminUser $4 -adminPassword $5

exit 0

 

pcampos9
New Contributor II

Thank you for this! 
This worked for me.

I created another user (admin1) and when I created that user, it had SecureToken Enabled. 

I logged into the original Admin account that didn't have it enabled and ran this script from Terminal. 
From there, I typed in the password for original admin account, and when the box came up for credentials, I used the newly created admin1 credentials. It enabled SecureToken for my original admin and then I deleted the other admin account that I created. 

Saved me the trouble of having to wipe/re-install OS.

Yep, this is the solution we've been using in limited scope, but it doesn't help the other 200 or so computers that have been deployed that are in a similar situation. I'm not walking around and touching them all.

mlarsen21
New Contributor II

I have managed to get this pretty streamlined where all the user has to do is setup a quick 5 minute zoom meeting, then run a policy from Self Service, and then once it asks to change system settings, we get take control of the screen and enter the IT admin account. 
Then they are now secure token enabled and good to go. 

Glad to share more if you want to know more. 

mlarsen21
New Contributor II

We have been able to resolve about 150 of these issues will minimal effort so our users can now update on their own and don't have the secure token issues. 

My problem is most of the computers suffering this issue are unattended (lab or classroom computers), but I'm taking all of these suggestions to heart to find the most streamlined solution.

mlarsen21
New Contributor II

do they all have the same admin account password? 

They do, yes.

GabeShack
Valued Contributor III

my problem is laps totally screwed this up.  Our original admin password doesnt always work for this, where yes it recognizes the admin password as correct and shows the admin with the token and volume ownership, but its not working to allow an update (almost like laps broke the actual record of the admin password for volume ownership).  So im not sure how to proceed since I cant get any of the above methods to work.  Only one I didnt try was to create another admin user and see if it gets a token.

Gabe Shackney
Princeton Public Schools

The jamf documentation outlines that it changes the password but doesnt change the cryptographic encryption password. So expected behaviour and it will vary from machine to machine based on other variables... 

Its a bit of a dogs breakfast to get consistant across a fleet of macs...

 

Which is why, despite the obvious security advantages of LAPS, we still maintain a separate local admin that does not have a rotating password. 

We use the LAPS password in the event that a user needs to perform an unexpected admin task in the field.

GabeShack
Valued Contributor III

So I have come up with a script to change the laps passwords on a specified smart group back manually to a specific password.  This is helping us undo some of the issues we have seen on Apple Silicon with volume ownership.  Obviously for security reasons I would run this only locally on a machine and not upload this script to the jamf cloud distribution point without some encryption of passwords.

 

#!/bin/bash

# API USER
user="YOUR_API_USERNAME_HERE"
# API PASSWORD
pass="YOUR_API_USER_PASSWORD_HERE"
# URL (https://yourjamfserver.jamfcloud.com)
jurl="https://YOUR_JAMF_URL_HERE"
# Smart group or static group ID to get computer IDs from
groupID="YOUR_SMARTGROUP_ID_HERE"
# Define the admin user name
adminname="YOUR_ADMIN_USERNAME_HERE"
# New LAPS password to set
newPassword="YOUR_PASSWORD_HERE"  


# Get Bearer token for API calls
getBearerToken() {
    response=$(curl -s -u "$user:$pass" "$jurl/api/v1/auth/token" -X POST)
    token=$(echo "$response" | plutil -extract token raw -)
    tokenExpiration=$(echo "$response" | plutil -extract expires raw - | awk -F . '{print $1}')
    tokenExpirationEpoch=$(date -j -f "%Y-%m-%dT%T" "$tokenExpiration" +"%s")
    echo "Token acquired."
}

# Invalidate the token once done
invalidateToken() {
    curl -w "%{http_code}" -H "Authorization: Bearer $token" "$jurl/api/v1/auth/invalidate-token" -X POST -s -o /dev/null
    echo "Token invalidated."
}

# Check token expiration and get a new one if necessary
checkTokenExpiration() {
    nowEpochUTC=$(date -j -f "%Y-%m-%dT%T" "$(date -u +"%Y-%m-%dT%T")" +"%s")
    if [[ tokenExpirationEpoch -gt nowEpochUTC ]]; then
        echo "Token is valid."
    else
        echo "Token expired, fetching new token."
        getBearerToken
    fi
}

# Run the function to get the token
getBearerToken

# Grab all computer IDs from the smart group (ID 802)
echo "Fetching computer IDs from group ID: $groupID"
computerids=($(curl -s $jurl/JSSResource/computergroups/id/$groupID \
-H 'accept: application/xml' \
-H "Authorization: Bearer $token" | xmllint --xpath '/computer_group/computers/computer/id/text()' -))

echo "Found Computer IDs: ${computerids[@]}"

# Loop through all computer IDs to look up the managementId and reset the LAPS password
for id in "${computerids[@]}"; do
    checkTokenExpiration
    
    # Get computer details to retrieve the managementId
    computerInfo=$(curl -s "$jurl/api/v1/computers-inventory/$id?section=GENERAL" \
        -H 'accept: application/json' \
        -H "Authorization: Bearer $token")

    # Extract the managementId using jq
    managementId=$(echo "$computerInfo" | jq -r '.general.managementId')

    if [[ -z "$managementId" || "$managementId" == "null" ]]; then
        echo "No management ID found for computer $id, skipping..."
        continue
    fi

    echo "Found Management ID: $managementId for computer $id"

    # Reset the LAPS password for the macadmin user using the correct API endpoint
    curl -s -X PUT "$jurl/api/v2/local-admin-password/$managementId/set-password" \
        -H "accept: application/json" \
        -H "Authorization: Bearer $token" \
        -H "Content-Type: application/json" \
        -d "{\"lapsUserPasswordList\": [{\"username\": \"$adminname\", \"password\": \"$newPassword\"}]}" || echo "Failed to reset LAPS password for computer $id with Management ID: $managementId"

done

# Invalidate the token when done
invalidateToken

exit 0

 

 

Gabe Shackney
Princeton Public Schools