Giving EMA its own least-privilege token
In my last post I described how I let the Experience Modernization Agent (EMA) use my Adobe credentials so it can upload to DA, preview, and publish on its own. Doing so made it a very effective collaborator, but it also handed the agent every permission my account has. A technical account token gives your agent the same desired agency while shrinking the blast radius to only what you grant it access to. Here's how to set one up.
Create the credential
-
Sign in to the Adobe Developer Console: https://developer.adobe.com/console/
-
Click Create new project, then Add API and choose Edge Delivery Services.
-
Select OAuth Server-to-Server as the authentication type, give your credential a name and save.
-
On the credential page, click to open your new OAuth Server-to-Server credential.
-
Save the following into your password/secret manager:
- Client ID
- Client Secret (keep it secret)
- Scopes: you should see
openid,AdobeID,additional_info.projectedProductContext,aem.frontend.all, andread_organizations - Technical account email (
…@techacct.adobe.com)
Generate a token (valid for 24 hours)
- Set
CLIENT_IDandCLIENT_SECRETin your shell, then run:
TOKEN=$(curl -s -X POST https://ims-na1.adobelogin.com/ims/token/v3 \
-d grant_type=client_credentials \
-d client_id="$CLIENT_ID" -d client_secret="$CLIENT_SECRET" \
-d scope="openid,AdobeID,read_organizations,additional_info.projectedProductContext,aem.frontend.all" \
| jq -r .access_token)
Confirm the email that Edge Delivery sees
curl -s -H "Authorization: Bearer $TOKEN" https://admin.hlx.page/profile | jq .profile.email
Should return an <id>@techacct.adobe.com email address which matches that of your credential.
You'll use this email in the next two steps.
Edge Delivery permissions (for preview/publish)
- Open https://tools.aem.live/tools/user-admin/index.html
- Input your Organization and Site, then click Fetch Users. In my case I had 0 users for my test site.
- First, make sure your own email has the Admin role, so you don't lock yourself out.
- Add the technical-account email with the Publish role, which includes preview. Changes can take a minute or two to apply.
DA permissions (for upload and write)
In the permissions sheet at https://da.live/config#/<org>/, add:
| path | groups | actions |
| ----------- | ------------------------------ | ------- |
| /<site>/+** | <your email>, <techacct email> | write |
readis enough for preview/publish, but uploading needswrite.- If the sheet was empty, adding a row restricts the whole org, so add rows for your org's other users too.
Click Save.
Use the token
This serves as a quick sanity check. First a preview request and then a publish:
H=(-H "Authorization: Bearer $TOKEN" -H "x-content-source-authorization: Bearer $TOKEN")
curl -X POST "${H[@]}" https://admin.hlx.page/preview/<org>/<site>/main/<path>
curl -X POST "${H[@]}" https://admin.hlx.page/live/<org>/<site>/main/<path>
And finally from EMA. In the first image below, this shows what you'll see before you enable "Allow LLM to use my Adobe credentials for admin.hlx.page, Document Authoring, and repositories hosted outside GitHub". The agent will not be able to upload to DA, preview, or publish on your behalf:
Open the Settings in EMA, enable Allow LLM to use my Adobe credentials for admin.hlx.page... and provide the technical account access token you generated above as Custom IMS Token (optional).
Then prompt the agent to take an action with DA/Edge, such as uploading or previewing content:
Security note
Anyone with access to this token can upload, preview and publish on the site for 24 hours, and the Client Secret can generate new tokens indefinitely. Keep both out of chats and repos, and rotate the secret in Developer Console if it leaks.
---
So, is this more effort than flipping a toggle in Settings? Yes. Pasting a fresh token into EMA every 24 hours is also a small chore. But I take comfort knowing that if anything goes sideways the impact is limited to only what the technical account can access, as opposed to everything that my Adobe ID can reach.
If you've been hesitant to enable that setting in your EMA project, this could serve as a good middle ground. Try it today 👉 https://aemcoder.adobe.io/