Skip to main content

Jamf announced in January that the Jamf Pro Classic API will no longer support basic authentication in a future release. Classic API scripts can still run—administrators just need to make a simple change in how they authenticate.


Let’s look at why this change is coming and how to convert Classic API scripts to use bearer tokens for authentication instead of usernames and passwords. The token obtained during this workflow will allow authentication to either the Classic API or the more modern Jamf Pro API. We’ll cover:



  • How bearer tokens improve security

  • Request the first token

  • Parse the token

  • Use the token to send an API command

  • Expire the token

  • Renew the token


How bearer tokens improve security


This change to move away from supplying usernames and passwords as credentials for authenticating to Jamf Pro is a good thing.


Bearer tokens improve security by reducing the number of times credentials are sent to the server. Instead of sending them with every request, a token is sent instead, which expires automatically after 30 minutes. And they’re ephemeral—not stored on disk like credentials in a database, but rather kept only in memory.


They also mean nothing to anyone other than the Jamf Pro server that generates them. Unlike usernames and passwords, which might be used to also access other network resources, bearer tokens are just meaningless strings of characters to anyone who might intercept them.


Keep in mind a script still needs to transmit a username and password to first acquire a bearer token, but all following requests are done using a short-lived token instead.


Request the first token


Consider using a scripting application like CodeRunner to see how the following snippets work.


If your Classic API script hasn’t yet been updated to use bearer tokens, it’s using “basic” authentication. The username and password it’s sending is still secure during transit to the server because its SSL certificate is providing encryption along the way.


Here’s what the start of the old script may look like. It may assign a username, password, and Jamf Pro server URL to some variables at the beginning to let us specify them once.


 


 


 


#!/bin/zsh

# server and credential information
jamfProURL=https://talkingmoose.jamfcloud.com
username="jamfadmin"
password="P@55w0rd"

 


 


 


We’ll keep this.


What we need to do next is use our credentials to request a token from the Jamf Pro server. Paste this after the server and credential information above:


 


 


 


# request auth token
authToken=$( /usr/bin/curl \\
--request POST \\
--silent \\
--url "$jamfProURL/api/v1/auth/token" \\
--user "$username:$password" )

echo "$authToken"

 


 


 


When we run this in CodeRunner with an echo at the end to print our results, it displays the token information returned from the server.



 


Parse the token


Notice the token information we received contains two pieces of information—“token” and “expires”. Only the token is important if we know the script will run very quickly (less than 30 minutes). Doing something like updating device asset tags from a spreadsheet could take longer than 30 minutes, so we’ll want to make sure we renew the token before it expires. We’ll talk about renewing the token a little later.


For now, we need to separate what we’ve received into useable pieces of information. Let’s put the token information into a “token” variable. Let’s put the “expires” information into a “tokenExpiration” variable. And let’s put a converted form of the expiration information into a “localTokenExpirationEpoch” variable. Paste this next:


 


 


 


# parse auth token
token=$( /usr/bin/plutil \\
-extract token raw - <<< "$authToken" )

tokenExpiration=$( /usr/bin/plutil \\
-extract expires raw - <<< "$authToken" )

localTokenExpirationEpoch=$( TZ=GMT /bin/date -j \\
-f "%Y-%m-%dT%T" "$tokenExpiration" \\
+"%s" 2> /dev/null )

echo Token: "$token"
echo Expiration: "$tokenExpiration"
echo Expiration epoch: "$localTokenExpirationEpoch"

 


 


 


The last three lines echo the results of what we parsed.



 


First, we get “Token” by itself.


Second, we get the “Expiration” by itself (2022-09-09T19:17:36.34Z). This is an expiration date for when the token will no longer be valid and it’s always 30 minutes into the future.


Finally, we convert the “Expiration” information into something called an epoch date. A Unix epoch date is literally the number of seconds since January 1, 1970. The “Expiration epoch” date is “1662751056”. When we have a straightforward number like this, we can do math calculations very easily.


Note the “TZ=UTC” item in front of the date command for the localTokenExpirationEpoch variable. This is a time zone environment variable and it’s defining the date as Universal Coordinated Time (+0000). It’s the same as the GMT+0 prime meridian that defines the starting point for time zones in the world.


The server is responding with an expiration date in the UTC time zone, not our local time zone. But the expiration date doesn’t say that. By providing the environment variable, we’re telling the date command the originating time zone and it’ll automatically convert to our local time zone when giving us the epoch date.


We can confirm this in Terminal by running /bin/date -r 1662751056. It converts the epoch date back to a date we can read: Fri Sep  9 14:17:36 CDT 2022. This shows a corrected time that is five hours different from the UTC time the server sent. Without this correction, our calculations could be up to 12 hours off. And it works regardless of whether Daylight Saving Time is in effect.


Use the token to send an API command


With basic authentication, the username and password are sent each time to the server when we use the curl command to request or change information. Here’s an example of what might come next in an unconverted Classic API script where we want to get a list of computer groups. Go ahead and paste this next:


 


 


 


# get list of static groups
computerGroupXML=$( /usr/bin/curl \\
--header "Accept: text/xml" \\
--request GET \\
--silent \\
--url "$jamfProURL/JSSResource/computergroups" \\
--user "$username":"$password" )

echo "$computerGroupXML"

 


 


 


If we run the entire script so far, we should get a string of XML that denotes several computer groups.



 


Now, let’s convert the command to use the bearer token instead of basic authentication. It’s simple to do. We’ll replace:


     --user "$username":"$password"


with


     --header "Authorization: Bearer $token"


and run the script again to test. We should get the same thing.



 


That’s it! That’s the basic change we need to make. We’re keeping our username, password, and server information that we had originally. But we used it instead to ask for a token and then simply replaced our credentials with the token when sending the API command. All we need to do is update all our other scripts to do the same thing.


We’re not done yet, though.


Expire the token


Remember, the token is valid for 30 minutes. If all we’re going to do is make a one-time Classic API call that takes just a few seconds to run and finish, we don’t need the token anymore. A good practice is to expire the token at the end of the script. Paste this near the end of your script where no further API calls will be made:


 


 


 


# expire auth token
/usr/bin/curl \\
--header "Authorization: Bearer $token" \\
--request POST \\
--silent \\
--url "$jamfProURL/api/v1/auth/invalidate-token"

 


 


 


We don’t see anything change when we run the script again. But we also don’t see any errors.



 


Did it work?


Normally, we can rely on this working, but just to test this one time (or if you’d like to always test), we can add a command to verify whether the token is still valid. Paste this after the command expiring the token:


 


 


 


# verify auth token is valid
checkToken=$( /usr/bin/curl \\
--header "Authorization: Bearer $token" \\
--silent \\
--url "$jamfProURL/api/v1/auth" \\
--write-out "%{http_code}" )

tokenStatus=${checkToken: -3}
echo Token status: "$tokenStatus"

 


 


 


This runs one more API command, which attempts to authenticate with the bearer token. At the end, it includes a --write-out argument. Every command we’ve sent to the server has returned an HTTP status code. Here’s a list of some that we might receive:


 


 


 


200 Request successful
201 Request to create or update object successful
400 Bad request
401 Authentication failed
403 Invalid permissions
404 Object/resource not found
409 Conflict
500 Internal server error

 


 


 


The --write-out argument instructs the curl command to show us the code returned from our API call. When we run the script with the additional code to check our token status, we see the result on the last line.



 


A 401 code lets us know “Authentication failed” or that our bearer token is expired and no longer works.


Renew the token


What if our script is still running after 30 minutes? Won’t the token expire?


Yes, it will, and the script will stop working. This is where getting the expiration date of the token and the converted epoch date is useful. What we need to do is add something that’s tracking the time and will renew the token just before it expires. We can do that with an “if” statement and a function.


First, we need to include in our script everything above that we’ve added: requesting and parsing the token, using it to make a Classic API command, and then expiring it. Now, we’ll add some more code to check for the pending expiration and renew the token.


The reason a script may take longer than 30 minutes to complete is that it’s probably looping through something in Jamf Pro. Let’s assume it’s looping through devices without an asset tag and updating each device with an asset tag from a spreadsheet. That part of the script may look something like this:


 


 


 


while IFS= read aDevice
do
# run Classic API commands here
# to update a device
# and keep looping
done <<< "$listOfDevices"

 


 


 


The commands to update the device aren’t important here—just their location within the while loop.


What we need to do with each iteration of the loop is verify whether the token is close to expiring. Instead of waiting until the last minute, though, we need to renew it with a little time to spare. Let’s choose 5 minutes before it expires. Paste this above the while loop:


 


 


 


# subtract five minutes (300 seconds) from localTokenExpirationEpoch
renewalTime=$(( $localTokenExpirationEpoch - 300 ))

 


 


 


We’ll renew the token around 25 minutes instead of 30. Calculating the renewal time is as simple as subtracting 300 (5 minutes) from the epoch date.


How many times will we need to renew the token? Once? A few times? We don’t know. So, something like this is best handled as a function in our script that we can call any time we need it. Let’s name that function “renewToken” and add it inside the while loop with some additional code. Here’s what we’ll have so far.


 


 


 


# subtract five minutes (300 seconds) from localTokenExpirationEpoch
renewalTime=$(( $localTokenExpirationEpoch - 300 ))

while IFS= read aDevice
do
now=$( /bin/date +"%s" )

if nE "$renewalTime" -lt "$now" ]]; then
renewToken
fi

# run Classic API commands here
# to update a device
# and keep looping
done <<< "$listOfDevices"

 


 


 


As the script loops through our list of devices to update their asset tags, the first thing it’ll do is verify whether the token’s renewal time is less than the time right now. That won’t happen for about 25 minutes, so the loop will carry on updating the device’s asset tag.


After 25 minutes of updating asset tags, the renewal time arrives! That’s when the script calls the “renewToken” function that we’ll add next. A function is like a mini script within the script. With just one word, we can call that mini script any time we’d like.


Here’s the function; paste it anywhere in the script so long as it’s somewhere before the while loop.


 


 


 


renewToken() {

# renew auth token
authToken=$( /usr/bin/curl \\
--header "Accept: application/json" \\
--header "Authorization: Bearer $token" \\
--request POST \\
--silent \\
--url "$jamfProURL/api/v1/auth/keep-alive" )

# parse auth token
token=$( /usr/bin/plutil \\
-extract token raw - <<< "$authToken" )

tokenExpiration=$( /usr/bin/plutil \\
-extract expires raw - <<< "$authToken" )

localTokenExpirationEpoch=$( TZ=GMT /bin/date -j \\
-f "%Y-%m-%dT%T" "$tokenExpiration" \\
+"%s" 2> /dev/null )

# update the renewal time for another 25 minutes
renewalTime=$(( $localTokenExpirationEpoch - 300 ))

}

 


 


 


It looks like a lot of the same code we’ve already been using. And it is for the most part.


The biggest difference is the command at the top for renewing the auth token. It’s using the old token to request a new one! That means the script has still only ever sent the username and password credentials to the server just one time.


The rest of the function parses for the token and new expiration date, generates the expiration epoch date, and updates the renewal time for another 25 minutes.


Although renewing the Classic API token is really for scripts that could take longer than 30 minutes to complete, you can still add the code for it to your shorter existing scripts. It’ll make your scripts longer and more complex; however, sometimes having just one “template” script to maintain can be easier than trying to determine when you need just some or all the code. As you gain experience with the Classic API and scripting, you’ll know when to omit unnecessary code.


Some closing thoughts


Because of how some websites format their content, copying snippets and pasting them into scripts or script editors may not always work. Verify that single and double dashes like the ones in front -f or --header haven’t been automatically converted to other characters like long em dashes. Retype them if you need. Also, quotes should be straight " not curly “”. And wherever you see a backslash at the end of a line in the examples above, that just means the command has been split onto multiple lines to make it easier to write here.


Something like this:


/usr/bin/plutil \\


-extract expires raw - <<< "$authToken"


is the same as:


/usr/bin/plutil -extract expires raw - <<< "$authToken"


You might say, “I’m not a scripter. I just use what I find online.” That’s OK, but what you find may be an outdated script that’s still using basic authentication. In the future, that script won’t work—only because it can’t authenticate correctly with your Jamf Pro server. Updating it to use bearer token authentication isn’t difficult and should be mostly copy/paste from what’s presented here.


If you don’t like showing username and password credentials in your scripts, you can use base64 to obfuscate them. This isn’t encryption. Anyone can still reverse the encoding and see the credentials. But it may give you a little extra piece of mind.


Once you’ve converted all your scripts to use bearer tokens for authentication, do one more thing to improve security. In Jamf Pro, go to the Settings cog > System Settings > Jamf Pro User Accounts & Groups > Password Policy. Disable the option to allow basic authentication for your Classic API scripts.


In the future, Jamf will remove this option altogether. For more information about this change, see the Classic API Authentication Changes page in the Jamf Developer Portal.

I can't thank you enough! Excellent article, very detailed and extremely helpful.


How do I use encoded credentials with bearer authentication?


This was very helpful. Reading this and trying out all of the steps helped me learn how to use the API in scripts. Today, I created a new script that uses the API to assign Macs to sites. This has been a big issue for us since we have several Jamf admins who can only access their assigned site. We had a lot of Macs assigned to the wrong site or not assigned to any. I was able to automate the assignments using the script.


@talkingmoose 


I'm looking at trying to do the same thing but for a powershellscript, have you had any success doing that?


 


the intent is to populate our DHCP with approved access policies for mdm bound Mac addresses, so that we can curb user wifi enrolment of non bound devices, which are also generating multiple IP reservations in our DHCP, due to the changing Mac addresses, where the device causing it is unmanaged.


Hi all,


I have a shell script that will take all app IDs I have listed and add them to a category ID I have listed. I just can't seem to incorporate this into @talkingmoose method of using bearer token.

Can anyone point me in the right direction?


 


 


#!/bin/sh
TARGET=(29 58 64 65 87 88 133 157 158 169 190 205 236 267 271 278 279 284 290 315 318 337 343 371 379 381 389 395 406 411 415 434 444 449 479 489 512 513 535 563 567 572 574 576 579 590 591 595 597 598 599 605 630 642 654 657 660 680 688 694 738 740 751 752)
CATEGORY=24

cat $TARGET | while read APP; do
curl -sk -u @username:@password -H "Content-Type: text/xml" -d "<?xml version="1.0" encoding="ISO-8859-1"?><mobile_device_application><general><category><id>$CATEGORY</id></category></general></mobile_device_application>" https://$jamfProURL/JSSResource/mobiledeviceapplications/id/$APP -X PUT

done

 


 


so far I got 


#!/bin/zsh

# server and credential information
jamfProURL=https://www.myjamfurl.com:8443/
username="username"
password="password"

renewToken() {

# renew auth token
authToken=$( /usr/bin/curl \\
--header "Accept: application/json" \\
--header "Authorization: Bearer $token" \\
--request POST \\
--silent \\
--url "$jamfProURL/api/v1/auth/keep-alive" )

# parse auth token
token=$( /usr/bin/plutil \\
-extract token raw - <<< "$authToken" )

tokenExpiration=$( /usr/bin/plutil \\
-extract expires raw - <<< "$authToken" )

localTokenExpirationEpoch=$( TZ=GMT /bin/date -j \\
-f "%Y-%m-%dT%T" "$tokenExpiration" \\
+"%s" 2> /dev/null )

# update the renewal time for another 25 minutes
renewalTime=$(( $localTokenExpirationEpoch - 300 ))

}

# request auth token
authToken=$( /usr/bin/curl \\
--request POST \\
--silent \\
--url "$jamfProURL/api/v1/auth/token" \\
--user "$username:$password" )

echo "$authToken"

# parse auth token
token=$( /usr/bin/plutil \\
-extract token raw - <<< "$authToken" )

tokenExpiration=$( /usr/bin/plutil \\
-extract expires raw - <<< "$authToken" )

localTokenExpirationEpoch=$( TZ=GMT /bin/date -j \\
-f "%Y-%m-%dT%T" "$tokenExpiration" \\
+"%s" 2> /dev/null )

echo Token: "$token"
echo Expiration: "$tokenExpiration"
echo Expiration epoch: "$localTokenExpirationEpoch"

# subtract five minutes (300 seconds) from localTokenExpirationEpoch
renewalTime=$(( $localTokenExpirationEpoch - 300 ))

while IFS= read aDevice
do
now=$( /bin/date +"%s" )

if [[ "$renewalTime" -lt "$now" ]]; then
renewToken
fi

# change app categorys
TARGET=(29 58 64 65 87 88 133 157 158 169 190 205 236 267 271 278 279 284 290 315 318 337 343 371 379 381 389 395 406 411 415 434 444 449 479 489 512 513 535 563 567 572 574 576 579 590 591 595 597 598 599 605 630 642 654 657 660 680 688 694 738 740 751 752)
CATEGORY=24
APP="<mobile_device_application><general><category><id>$CATEGORY</id></category></general></mobile_device_application>"
$appcategory=$( /usr/bin/curl \\
--header "Accept: text/xml" \\
--request PUT \\
--silent \\
--url "$jamfProURL/JSSResource/mobiledeviceapplications/id/$APP" \\
--header "Authorization: Bearer $token" )

done <<< "$appcategory"


# expire auth token
/usr/bin/curl \\
--header "Authorization: Bearer $token" \\
--request POST \\
--silent \\
--url "$jamfProURL/api/v1/auth/invalidate-token"

# verify auth token is valid
checkToken=$( /usr/bin/curl \\
--header "Authorization: Bearer $token" \\
--silent \\
--url "$jamfProURL/api/v1/auth" \\
--write-out "%{http_code}" )

tokenStatus=${checkToken: -3}
echo Token status: "$tokenStatus"



yet I'm getting a 


Token: <stdin>: Could not extract value, error: No value at that key path or invalid key path: token


Expiration: <stdin>: Could not extract value, error: No value at that key path or invalid key path: expires


Expiration epoch:


Untitled.sh: line 78: =: command not found


Token status: 000
error.


@HenryOzsoy 


I am going to be inclined to say its the put command.


How I am reading it is:


$appcategory=$( /usr/bin/curl \\


--header "Accept: text/xml" \\


--request PUT \\


--silent \\


--url "$jamfProURL/JSSResource/mobiledeviceapplications/id/<mobile_device_application><general><category><id>$CATEGORY</id></category></general></mobile_device_application>"


 


I think firstly you want:


--url "$jamfProURL/JSSResource/mobiledeviceapplications/id/$TARGET”


not


--url "$jamfProURL/JSSResource/mobiledeviceapplications/id/$APP”



This is some example code that uses PUT that will insert a variable into the Purchasing_Contact field of a device.


so I think your xml section needs to be similar...


I will try and re-write your section there in the way I think it should be written in a follow up post... But I would advise to test it against a single Target first.


echo "<?xml version=\\"1.0\\" encoding=\\"UTF-8\\"?>
<xsl:stylesheet version=\\"1.0\\" xmlns:xsl=\\"http://www.w3.org/1999/XSL/Transform\\">
<xsl:output method=\\"text\\"/>
<xsl:template match=\\"/\\">
<xsl:value-of select=\\"id\\"/>
</xsl:template>
</xsl:stylesheet>" > /private/var/tmp/stylesheet.xslt

curl -s -k \\
-H "Authorization: Bearer $jamfProApiToken" \\
-H "Content-type: application/xml" \\
-X PUT \\
-d "<computer><purchasing><purchasing_contact>$updatedmdmdeviceName</purchasing_contact></purchasing></computer>" \\
"${jamfProURL}/JSSResource/computers/id/$computerID"
echo "name change applied $updatedmdmdeviceName"

 


Thanks, @Malcolm . To follow up on your comment, I modified the script. I'm not getting any errors now, yet no change has occurred in the app category post-script.


#!/bin/sh

# server and credential information
jamfProURL=https://www.myjamfurl.com:8443
username="username"
password="password"

renewToken() {

# renew auth token
authToken=$( /usr/bin/curl \\
--header "Accept: application/json" \\
--header "Authorization: Bearer $token" \\
--request POST \\
--silent \\
--url "$jamfProURL/api/v1/auth/keep-alive" )

# parse auth token
token=$( /usr/bin/plutil \\
-extract token raw - <<< "$authToken" )

tokenExpiration=$( /usr/bin/plutil \\
-extract expires raw - <<< "$authToken" )

localTokenExpirationEpoch=$( TZ=GMT /bin/date -j \\
-f "%Y-%m-%dT%T" "$tokenExpiration" \\
+"%s" 2> /dev/null )

# update the renewal time for another 25 minutes
renewalTime=$(( $localTokenExpirationEpoch - 300 ))

}

# request auth token
authToken=$( /usr/bin/curl \\
--request POST \\
--silent \\
--url "$jamfProURL/api/v1/auth/token" \\
--user "$username:$password" )

echo "$authToken"

# parse auth token
token=$( /usr/bin/plutil \\
-extract token raw - <<< "$authToken" )

tokenExpiration=$( /usr/bin/plutil \\
-extract expires raw - <<< "$authToken" )

localTokenExpirationEpoch=$( TZ=GMT /bin/date -j \\
-f "%Y-%m-%dT%T" "$tokenExpiration" \\
+"%s" 2> /dev/null )

echo Token: "$token"
echo Expiration: "$tokenExpiration"
echo Expiration epoch: "$localTokenExpirationEpoch"

# subtract five minutes (300 seconds) from localTokenExpirationEpoch
renewalTime=$(( $localTokenExpirationEpoch - 300 ))

while IFS= read aDevice
do
now=$( /bin/date +"%s" )

if [[ "$renewalTime" -lt "$now" ]]; then
renewToken
fi

# change app categorys
TARGET=29
CATEGORY=24

appcategory=$( /usr/bin/curl \\
--header "Accept: text/xml" \\
--request PUT \\
--silent \\
--url "$jamfProURL/JSSResource/mobiledeviceapplications/id/$TARGET/<mobile_device_application><general><category><id>$CATEGORY</id><name>Applications</name></category></general><mobile_device_application>" \\
--header "Authorization: Bearer $token" )

done <<< "$changeappcategorys"

echo "$appcategory"

# expire auth token
/usr/bin/curl \\
--header "Authorization: Bearer $token" \\
--request POST \\
--silent \\
--url "$jamfProURL/api/v1/auth/invalidate-token"

# verify auth token is valid
checkToken=$( /usr/bin/curl \\
--header "Authorization: Bearer $token" \\
--silent \\
--url "$jamfProURL/api/v1/auth" \\
--write-out "%{http_code}" )

tokenStatus=${checkToken: -3}
echo Token status: "$tokenStatus"

@HenryOzsoy 


try this:


 


echo "<?xml version=\\"1.0\\" encoding=\\"UTF-8\\"?>
<xsl:stylesheet version=\\"1.0\\" xmlns:xsl=\\"http://www.w3.org/1999/XSL/Transform\\">
<xsl:output method=\\"text\\"/>
<xsl:template match=\\"/\\">
<xsl:value-of select=\\"id\\"/>
</xsl:template>
</xsl:stylesheet>" > /private/var/tmp/stylesheet.xslt

curl -s -k \\
-H "Authorization: Bearer $token" \\
-H "Content-type: application/xml" \\
-X PUT \\
-d "<mobile_device_application><general><category><id>$CATEGORY</id></category></general></mobile_device_application>" \\
"${jamfProURL}/JSSResource/mobiledeviceapplications/id/$TARGET"
echo "Category change Category $CATEGORY to application $TARGET"

 


 


But I would suggest trying this first against just one of your targets:


 


echo "<?xml version=\\"1.0\\" encoding=\\"UTF-8\\"?>
<xsl:stylesheet version=\\"1.0\\" xmlns:xsl=\\"http://www.w3.org/1999/XSL/Transform\\">
<xsl:output method=\\"text\\"/>
<xsl:template match=\\"/\\">
<xsl:value-of select=\\"id\\"/>
</xsl:template>
</xsl:stylesheet>" > /private/var/tmp/stylesheet.xslt

curl -s -k \\
-H "Authorization: Bearer $token" \\
-H "Content-type: application/xml" \\
-X PUT \\
-d "<mobile_device_application><general><category><id>24</id></category></general></mobile_device_application>" \\
"${jamfProURL}/JSSResource/mobiledeviceapplications/id/29"
echo "Category change category 24 on app 29"

 


 


Thanks, @Malcolm works great.


@HenryOzsoy 


Happy to have helped, it took me a long time to work out the put command the right way, I had an old script for forcing old assets to unmanaged a Jamf employee helped me with because I wanted to retain the information of the previously managed devices, such as the activation lock and FileVault key.


I later ended up needing to do it for a different purpose, and had to dissect their code to work it out.


I use it to auto name devices, using assigned users and prefix information I append to the device, set via a prestage enrolment group, the trouble I had was I had a lot of devices, in presages where the data wasn;t accurate as moving a device from one prestage to another would leave the old prestage information on the device record, so I had to query the presages for the device id, then collect the correct prestage prefix info I would store in the prestage purchasing section of the prestage info, then I would update that data back to the device record, and then use that data with the assigned user to name the device.


I then later on used it to also bind devices that were shared devices, by using a purchasing field for the string AD, which then in the same naming script, would also domain bind the device.


Reply