How to offline add a domain user to a mac

tjosey
New Contributor III

I'm working through some remote support issues for macs, and stuck on this one. Mac is remote, and has to use a VPN to connect to the domain. Normally, after the machine joins the domain (no problem - I connect with the VPN and join) I log off as the local user then login as the domain user. Then I create a mobile account and all's well.

However, because the connection to the VPN drops once the local user is logged out, you can not login as a domain user because it can't look it up on the domain.

With Windows, we get around this issue by using "Change User" which doesn't actually log off the local user and doesn't break the VPN connection to the domain. I don't see how to accomplish this on a Mac, and because we support remote users with Macs, we need to be able to set them up on the domain.

One thing I tried was to create a local account using the domain ID/password, then login with it, connect to the VPN/domain, then tick "mobile account" but for that type of account it does not give a mobile option.

I also tried turning on Fast Switching (users) and selecting 'other user' and trying to log in then, but it won't allow it - apparently that breaks the VPN connection too (or perhaps Fast Switching requires an established account).

Thoughts? We just us OS Catalina

51 REPLIES 51

rwinfie
Contributor

Assuming the device has a valid connection while on VPN. Have the user open a terminal prompt and use the login command. It will prompt for user name and password. Once that login has been confirmed. Use this command to create a mobile account

sudo /System/Library/CoreServices/ManagedClient.app/Contents/Resources/createmobileaccount -n username

Rebind option worked and was able to add the users.. thank you so much for your help.

tjosey
New Contributor III

When I try to put in the username it tells me its incorrect. I am already on the Domain and connected to a vpn on the local admin account. Any Ideas? I am trying to login as as a new domain user.

AdamCraig
Contributor III

Despite my trying in a ton of different ways I was never able to script this. I had to type it in to terminal on the computer.

sudo /System/Library/CoreServices/ManagedClient.app/Contents/Resources/createmobileaccount -a $adminUsername -U $adminPassword -n $USERNAME
That will put the user account on the computer

dscacheutil -q user -a name $USERNAME
that will cache the users password so you can log in with them.

Jons
New Contributor

Should this work for none AD syncs? I am performing authentication using an LDAP sync to google. I need mobile or even local accounts created at sign-in to allow my MDM policies to take effect. Should I be able to just copy and paste your TERM line or do I need to make edits?  

rwinfie
Contributor

When you log into the system while on VPN in the terminal window use the command "id $USERNAME" if the command comes back no such user , then the device has lost its domain join. Run your bind policy again on the device then try to login.

tjosey
New Contributor III

@strayer unfortunately the first line keeps asking for the user's password which I am positive is correct. It returns with "Sorry please try again"

@rwinfie I ran that command and its seems to come back with a bunch of information such as Admin information Staff information etc. I tried a user name that I know is not on our domain but it returned with the same information as above.

AdamCraig
Contributor III

@tjosey The password it's asking for is the admin users password because it is a sudo command.

The process I use never requires you to enter the user account you are adding's password into terminal

EDIT: You also may want to rebind the computer to the domain if it's having trouble finding the user.

tjosey
New Contributor III

@strayer For example the I tried adding myself as Tjosey. I have made a test account on the domain I am typing in the following on Terminal:

sudo /System/Library/CoreServices/ManagedClient.app/Contents/Resources/createmobileaccount -a $Administartor(Local Admin Account) -U $(Password for local administrator) -n $tjosey
It then ask me for a password in which I put in the local admin account and returns with the following error

* error: "-n username" is a required argument

Any ideas on what I am doing wrong. Really appreciate the help on this.
Also rejoined bind it to the domain

rwinfie
Contributor

@strayer remove the $

tjosey
New Contributor III

@rwinfie i removed the entire command and got the error "

*user name "tjosey" was not found: 0 ((null))

the VPN connection I have is stable and I am able to access different resources not normally available outside the network. When I enet the username do I have to put in the domain as well?

rwinfie
Contributor

Ok , lets try this , please send the output of the command id tjosey

AdamCraig
Contributor III

@tjosey the $ was there to indicate a variable and should not be included. sorry about that.

Not sure what your vpn setup is like, but our company has a limited always on VPN and a full access VPN that requires authentication. For us this only works on the Full access vpn because the limited VPN does not have access to AD, only a small set of very commonly used internal resources.

Before I put in the answer I ran these commands on my computer and it was successful in putting the account on my machine. I agree with @rwinfie to try id tjosey and maybe unbind and rebind the computer before proceeding further.

I also tried on limited VPN first and failed then i switched to full VPN then it gave me an error on the full VPN as well. I started a new terminal session and then it succeeded. So maybe after you verify your VPN connection and AD bind is good quit and relaunch terminal.

tjosey
New Contributor III

@strayer I think we made some progress. I am able to Id Tjosey. Pulls the domain that I am a part of as well. Did a test for another Domain user with the same results. When I tried a none domain user its says "user not found" so thats progress! However, when I enetr the below command it says the * admin authentication failed. Any Idea? The command I typed is below

sudo /System/Library/CoreServices/ManagedClient.app/Contents/Resources/createmobileaccount -a Administartor(Local Admin Account) -U (Password for local administrator) -n tjosey

Can you confirm which password its asking for when I run this command? Right now I am putting the local admin password which is returning the error.

AdamCraig
Contributor III

@tjosey That is the admin password you should be entering. Doing some testing on my machine I get the "Admin authentication failed" error when the admin password is not entered correctly.
if the user is not an admin or does not exist it gives an error.

tjosey
New Contributor III

@strayer Is it the local admin to the machine or a domain admin that I need to log in with?

AdamCraig
Contributor III

@tjosey it is a local admin on the machine.

tjosey
New Contributor III

@strayer what credentials am I using for -a $adminUsername -U $adminPassword? Is it also the local admin or a varified domain user?

AdamCraig
Contributor III

@tjosey That is the login i was referring to and is also a local admin on the machine. When we do a remote setup we have a local non-domain admin. We are logged into that user and enter the command using that -a localadminusername -U localadminpassword -n accountweareadding

if the computer is already bound to AD you never need domain admin credentials to do any of this.

hansjoerg_watzl
Contributor II

Thanks everyone for this interesting thread! I always wanted to have the option to add a domain user offline but never found a working solution.
I just tried the following steps:
- Configured and tested VPN connection -> OK
- Manually bound device to our domain -> OK
- Run id myDomainUser and got a bunch of data as result -> OK
- Added my domain user as a mobile user account with: sudo /System/Library/CoreServices/ManagedClient.app/Contents/Resources/createmobileaccount -a myLocalAdminAccount -U 'myLocalAdminPassword' -n myDomainUser -> OK (btw, the SINGLE quotes are important, when the password contains special characters!)
- Cached local password with: dscacheutil -q user -a name myDomainUser -> OK (at least no error)

I see the new domain user in Users & Groups as "mobile". But when I want to login with this account (offline of course), nothing happens. The new domain user will be shown on the login screen and I can enter the password, but then nothing happens and after this I can't re-enter the password anymore. (The password does not shake, so it's not denied, it just does not work.)

So, it seems, I only have to fix this last step. But without this I can't use this scenario, as I need to login with a cached password.
I'm using 10.15.3 on my test device. Does the dscacheutil really fetch the password from the domain and save it in the local cache? I was never prompted for the domain user password.

P.S.: @strayer How did you color format some of your commands??

tjosey
New Contributor III

@hansjoerg.watzl Ran across the exact same issue but I managed to get around it Yesterday! Will post a detailed thread later. However, after you run the command "dscacheutil -q user -a name myDomainUser" switch the user in terminal using the SU myDomainUser command. This will prompt you to put the password in for that user. Once that is done you should be able to log off the current account and login as that user!

Also, Thank you so much for mentioning quotes are needed for passwords with special characters! It was driving me crazy why my original local admin password was failing so I created another local test account with a simple password to get around it!. I'll try it with my original local admin password with the quotes you mentioned.

hansjoerg_watzl
Contributor II

Wow! Thanks for this! Now it works....the first time I could configure a BYOD Mac to a domain bound Mac with domain user added from outside the corporate network (only VPN).
I'm wondering, if the dscacheutil command is really needed or if just the su command alone did the trick....

AdamCraig
Contributor III

@hansjoerg.watzl @tjosey Options other than su you can also do login and login as that username and password. or do /usr/bin/dscl /Search -authonly adUsername adPassword

I have done this with just the dscacheutil command and the advantage of that is that you don't need to know the users password. Which may not be an issue for you guys, but is an important part of the process that I am using it for.

hansjoerg_watzl
Contributor II

@strayer But when you just use dscacheutil, how is then the user be able to login (offline)? Or do you provide him the instructions, how to do the login command in terminal?
I still don't know, what dscacheutil really does? Regarding the man page, dscacheutil -q user -a name jdoe just does a lookup. Does this lookup fetch and store the password locally or just show the user? Or does it prepare the cache, so AFTER the next authentication the password is cached locally?
btw dscacheutil -cachedump brings me only Unable to get details from the cache node

(Would still be thankful if you could tell me how you format the color text in your messages ;-) )

AdamCraig
Contributor III

I format color in my messages by using backticks `

We put a Setup account on the computer, do the dscacheutil instruction and we have fast user switching enabled with a config profile and the user does fast user switching over to their user account.

this used to be an emergency remote setup measure, but now with the current pandemic and over 90% of my company working from home we are having to use this method more.

AdamCraig
Contributor III

@tjosey @hansjoerg.watzl I put together a script that got this working in Self Service.

our first test with a user we are shipping a computer to is tomorrow, but it's been working over VPN on my computer in repeated tests.

It prompts the user for the username and password of the account to be added to the computer.
the local admin account username and password need to be passed to the script as variables 4 and 5
it also adds the user to Filevault using the same admin credentials, but you can delete that part from the end if you don't need that.

We also use fast user switching so I kill the menu bar process after the user account is created so the User gets added to Fast User switching.

I referenced https://github.com/rtrouton/rtrouton_scripts/blob/master/rtrouton_scripts/migrate_local_user_to_AD_d...
for some of the commands.

#!bin/bash

adminUser="$4"
adminPass="$5"

osvers=$(sw_vers -productVersion | awk -F. '{print $2}')
check4AD=`/usr/bin/dscl localhost -list . | grep "Active Directory"`

## verify that adminuser and pass variables are both passed to the user
if [[ -z "$adminUser" ]] || [[ -z "$adminPass" ]] ; then
    dialog="either Admin User or Password is missing"
    echo "$dialog"
    cmd="Tell app "System Events" to display dialog "$dialog""
    /usr/bin/osascript -e "$cmd"
    exit 1
fi

## check the admin password
adminCheck=$(/usr/bin/dscl /Local/Default -authonly "$adminUser" "$adminPass")
if [[ -z "$adminCheck" ]] ; then
    echo "Admin password is verified"
else
    echo "Admin Password not working"
    exit 1
fi

# If the machine is not bound to AD, then there's no purpose going any further. 
if [ "${check4AD}" != "Active Directory" ]; then
    dialog="This machine is not bound to Active Directory.
Please bind to AD first. "
    echo "$dialog"
    cmd="Tell app "System Events" to display dialog "$dialog""
    /usr/bin/osascript -e "$cmd"
    exit 1
fi

## Prompt for Username
userToAdd=$(/usr/bin/osascript<<END
tell application "System Events"
activate
set the answer to text returned of (display dialog "Enter the username to add to this computer" default answer "" buttons {"Continue"} default button 1)
end tell
END
)

## Prompt for Password
userPass=$(/usr/bin/osascript<<END
tell application "System Events"
activate
set the answer to text returned of (display dialog "Please enter the user's account Password:" default answer "" with hidden answer buttons {"Continue"} default button 1)
end tell
END
)

loopCount=0
while [ "$loopCount" -lt 3 ]; do
    # Refresh Directory Services
    if [[ ${osvers} -ge 7 ]]; then
        /usr/bin/killall opendirectoryd
    else
        /usr/bin/killall DirectoryService
    fi
    sleep 15

    ## try to auth the user in advance. this seems to increase the success of the ID command.
    /usr/bin/dscl /Search -authonly "$userToAdd" "$userPass"

    adCheck=`id $userToAdd`
    echo "AD Check is: $adCheck"
    if [[ -z "$adCheck" ]] ; then
        ((loopCount++))
    else
        echo "AD Check successful"
        break
    fi
done 


if [[ -z "$adCheck" ]] ; then
    dialog="AD User Not found. Verify Good Full VPN connection and Rebind to Domain if needed."
    echo "$dialog"
    cmd="Tell app "System Events" to display dialog "$dialog""
    /usr/bin/osascript -e "$cmd"
    exit 1
fi


sleep 2

## hit AD create the user
/System/Library/CoreServices/ManagedClient.app/Contents/Resources/createmobileaccount -a "$adminUser" -U "$adminPass" -n "$userToAdd"

sleep 2

## check to see if the user account was added
userCheck=$(dscl . list /Users | grep "$userToAdd")

if [[ -z "$userCheck" ]] ; then
    dialog="AD User failed to add."
    echo "dialog"
    cmd="Tell app "System Events" to display dialog "$dialog""
    /usr/bin/osascript -e "$cmd"
    exit 1
fi

## this should query AD to cache the user including the password
dscacheutil -q user -a name "$userToAdd"

## this will auth the user to AD and should also cache their password locally
/usr/bin/dscl /Search -authonly "$userToAdd" "$userPass"

## this kills the menubar so that the fast user switching list refreshes
killall -KILL SystemUIServer

## NOW that we've verified the user exists let's add the user to FileVault

# create the plist file:
echo '<?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>Username</key>
<string>'$adminUser'</string>
<key>Password</key>
<string>'$adminPass'</string>
<key>AdditionalUsers</key>
<array>
    <dict>
        <key>Username</key>
        <string>'$userToAdd'</string>
        <key>Password</key>
        <string>'$userPass'</string>
    </dict>
</array>
</dict>
</plist>' > /tmp/fvenable.plist  ### you can place this file anywhere just adjust the fdesetup line below

# now enable FileVault
fdesetup add -i < /tmp/fvenable.plist

rm -r /tmp/fvenable.plist

fdeList=`fdesetup list | grep $userToAdd`

if [[ "$fdeList" == *"$userToAdd"* ]] ; then
    dialog="$userToAdd account created, and added to Filevault Successfully"
    echo "$dialog"
    cmd="Tell app "System Events" to display dialog "$dialog""
    /usr/bin/osascript -e "$cmd"
    exit 0
else    
    dialog="$userToAdd account created, please run the 'Update Filevault Password' policy in Self Service"
    echo "$dialog"
    cmd="Tell app "System Events" to display dialog "$dialog""
    /usr/bin/osascript -e "$cmd"
    exit 0
fi

markopolo
New Contributor III

@strayer Thank you for posting your script! I'm currently getting "either Admin User or Password is missing" even though I've plugged them in as such:

adminUser="localadmin"
adminPass="<password>"

Any ideas?

Update: Changed double quotes to single and now it's passing creds. However, now I'm getting "AD User Not found. Verify Good Full VPN connection and Rebind to Domain if needed". I'm fairly confident in both VPN and AD binding, though. Anything else I should check?

Update2: Removed the "adCheck" portion of the script and it appears to be working now! W00t!! You rock dude!!!

AdamCraig
Contributor III

@mcantwell I was trying to use this with a remote user today and it was failing for me at that same section. It seems like a good idea to check connection with AD, but when we ran the terminal commands they worked. So I think I may do some revising to that section of the script. I'll post an update here. Glad you got it working!

markopolo
New Contributor III

@strayer Have you had any issue with it caching the user password? I had to do a separate Terminal login as the user before it would let them login from the macOS security screen.

markopolo
New Contributor III
I had to do a separate Terminal login as the user before it would let them login from the macOS security screen.

As an update, I got this to work by also passing the user password when creating the account:
createmobileaccount -a "$adminUser" -U "$adminPass" -n "$userToAdd" -p "$userPass"

PADPower
New Contributor

Thank you @strayer ,@tjosey @hansjoerg.watzl and @mcantwell for your collaboration on this. I'd been beating my head on my desk trying to get some new macs setup for new hires remotely. I'd found online and tried the @rtrouton script and Patrick Gallagher scripts unsuccessfully and I found this just a little late, but know I will be needing it again soon!

kuzama
New Contributor

@strayer I'm a complete and total rookie when it comes to Mac - That being said, I don't know two big things (well, I don't know a lot more but that's a different story) One, I need to know which items I'm editing in the script that you so kindly provided, Example $localAdminUser am I modifying anything that has a $ preceding it? Sorry, I do not want to mess this up as I bound the Mac to the domain and I have a cmd line we use to fix FileVault issues and I used pieces of that to get my user directory created for my mobile account but never cached it and in reading was probably because I didn't have the single quotes around my complex password. So, super long story short, I have a local account that I need to migrate to mobile/AD and your script should work for me. I just don't know what I need to modify. Two, how am I saving this script and running it? what is the language as when I attempt to save it, it's asking me what the language is and I have no idea? I thought Shell Script but it doesn't allow me to add the .command extension so I'm obviously doing it wrong. I know it's been months since you posted but this could ultimately save our first response team some serious time in getting new devices to remote users. I appreciate any help from anyone and I thank whoever it may be in advance, truly.

AdamCraig
Contributor III

@kuzama since posting it here I set up my github and this is the version of the script that I'm using in Production. The production version does expect filevault encryption to be turned on. (it will also call a policy with the sudo jamf policy -trigger catalina_fv if FV is not turned on.)
it also expects the computer to be bound and runs a policy with sudo jamf policy -trigger rebind to rebind the computer if it is not bound.

https://github.com/theadamcraig/jamf-scripts/blob/master/remote_AD_user_creation.sh

either version of the script only expects the local admin's username and password to be passed as variables $4 and $5 in Jamf (see screenshot). You don't need to edit anything in the script itself (unless you aren't using filevault)

468d3051db034d788c56c2c45ec3e715

You want to save it with the .sh command. .command files are a different thing that I've only used once or twice and not very well, but Jamf policies will be using it as a shell script.

in shell scripting language the $ just indicates that something is a variable. So at the top of the script when it says

adminUser="$4" adminPass="$5"

it is defining those variables from the jamf policy screenshot.

Hope that is a good explanation.

rnoureddine
New Contributor III

@mcantwell Thanks for the update. I was able to create an account with a standard one word password, however if an account has a password with spaces, say the password is "Football is my #1 Sport" it always comes back with authentication failed error. using the example above, can you please let me know what the command would be?

Update: I had the account added before seeing your post, so once I removed the account then added it again with the password, it worked like a charm.

Thanks
Thanks in advance

llitz123
Contributor II

Hi
I'm trying to work through the script without filevault.
I copy and pasted the one from @strayer's github and created a self service policy.
I got this error when running the script:

An error occurred while running the policy "Add Remote AD User" on the computer "HLC1471". Actions from policy log: [STEP 1 of 5] Executing Policy Add Remote AD User [STEP 2 of 5] Running script Local AD User Creation... Script exit code: 1 Script result: admin user is not SecureToken enabled. admin user is not SecureToken enabled. Checking for policies triggered by "rebind" for user "support"... No policies were found for the "rebind" trigger. * admin user is not SecureToken enabled. AD User failed to add. Verify GlobalProtect is Connected. Recommend restarting the computer and trying this install again. If issues continue run 'Rebind to Domain' from Self Service and then try install again. button returned:OK

I did some searching and am really confused about SecureToken and how it pertains to this process if I don't want filevault.
Thanks for any assistance.

Nix4Life
Valued Contributor

@llitz123 What i found from having to do this for the first time this week is that the following:

-a username : opt SecureToken enabled admin user name
-U password : opt SecureToken enabled admin user password.
-D : don't prompt for SecureToken enabled admin information

So it seems like you may need to replace both -a -U with just -D if the local admin is not a secure tokenholder

bcbackes
Contributor II

@strayer First, thanks for all the work you've done on this. It's fantastic. Second, I'm trying to follow along and want to make sure I understand what is happening and what needs to be done by IT prior to giving this to an end user.

What information is needed about the user in order to use your script? I assume the username is needed. What I don't understand is if your script is creating a temp password for the user, or, if it's going to AD and pulling the users current password and caching it on the Mac? This isn't creating a user account in AD is it?

If you can explain that part, that would be helpful. My company will not allow us to ask the user for their password - nor would I want to for security reasons. However, I haven't been able to find a way to create a mobile account for them without them being present to login to the device first.

Thank you.

bcbackes
Contributor II

I've tried taking another look at this and I'm still running into issues trying to get it to work. I'm getting an error saying to verify GlobalProtect. I even tried to do the manual process of running the following commands in terminal:

sudo /System/Library/CoreServices/ManagedClient.app/Contents/Resources/createmobileaccount -a $adminUsername -U $adminPassword -n $USERNAME

and

dscacheutil -q user -a name $USERNAME

It created the mobile account on the computer, however, the second command didn't appear to pull down the password for that AD account to the device since I couldn't login with the password for that account. Not sure what I'm missing here.

efil4xiN
Contributor

@bcbackes

We are using a version of the above script by strayer. The quick difference I see is that we are using the AD user's Credentials instead of the admin credentials. I can confirm this has been working for the past 3 months. we hardcode the admin creds in $4 and $5. We run this over VPN after AD Binding

#!/bin/sh

adminUser="$4"
adminPass="$5"
DATE=`date`


echo "Running cache AD User  Account"



ADuser=$(osascript -e 'set T to text returned of (display dialog "Enter AD User Name:" buttons {"Cancel", "OK"} default button "OK" default answer "")')

#Prompts User for Password
#-----------------------------------#
read -r -d '' applescriptCode <<'EOF'
    set dialogText to text returned of (display dialog "Enter your Current AD password to continue" default answer "" with icon stop buttons {"OK"} default button 1 with hidden answer)
    return dialogText
EOF

ADuserPWD=$(osascript -e "$applescriptCode");

echo "$ADuser"


#Do not use verbose mode as it shows users password in log
/System/Library/CoreServices/ManagedClient.app/Contents/Resources/createmobileaccount  -D  -n $ADuser -p $ADuserPWD 


## this should query AD to cache the user including the password
dscacheutil -q user -a name "$ADuser"


#Lets Set an encrypted on date as a back up to cache account

sudo -H -u $ADuser  touch /Users/$ADuser/Documents/image.txt
sudo -H -u $ADuser  echo "This Mac was Filevaulted on $DATE" > /Users/$ADuser/Documents/image.txt


# create the plist file:
/bin/echo '<?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>Username</key>
<string>'$adminUser'</string>
<key>Password</key>
<string>'$adminPass'</string>
<key>AdditionalUsers</key>
<array>
    <dict>
        <key>Username</key>
        <string>'$ADuser'</string>
        <key>Password</key>
        <string>'$ADuserPWD'</string>
    </dict>
</array>
<key>UseRecoveryKey</key>
<true/>
<key>ShowRecoveryKey</key>
<false/>
</dict>
</plist>' > /tmp/fvenable.plist  ### you can place this file anywhere just adjust the fdesetup line below

#now enable FileVault
/usr/bin/sudo fdesetup enable -inputplist < /tmp/fvenable.plist

rm -rf /tmp/fvenable.plist



diskutil apfs updatePreboot  /


/usr/bin/dscl .  -change /Users/onetimeuselocaluseraccountnamehere UserShell /bin/zsh /sbin/nologin

 dialog="$ADuser account has been added to Filevault, Please reboot to enable Filevault"
    echo "$dialog"
    cmd="Tell app "System Events" to display dialog "$dialog""
    /usr/bin/osascript -e "$cmd"