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

Adobe Developer Console "Add an API" dialog with the Edge Delivery Services card selected and the Next button in the lower right.

  1. Sign in to the Adobe Developer Console: https://developer.adobe.com/console/

  2. Click Create new project, then Add API and choose Edge Delivery Services.

  3. Select OAuth Server-to-Server as the authentication type, give your credential a name and save.

  4. On the credential page, click to open your new OAuth Server-to-Server credential.

  5. Save the following into your password/secret manager:

    1. Client ID
    2. Client Secret (keep it secret)
    3. Scopes: you should see openid, AdobeID, additional_info.projectedProductContext, aem.frontend.all, and read_organizations
    4. Technical account email (…@techacct.adobe.com)

Generate a token (valid for 24 hours)

  1. Set CLIENT_ID and CLIENT_SECRET in 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)

  1. Open https://tools.aem.live/tools/user-admin/index.html
  2. Input your Organization and Site, then click Fetch Users. In my case I had 0 users for my test site.
  3. First, make sure your own email has the Admin role, so you don't lock yourself out.
  4. Add the technical-account email with the Publish role, which includes preview. Changes can take a minute or two to apply.

Edge Delivery User Admin tool's "Add Users" dialog with two entries: a personal Adobe email with the Admin role selected, and a techacct.adobe.com email with the Publish role selected.

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   |

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:

EMA chat where the user asks to upload the page to DA and the agent replies that Document Authoring refused the request because the "Allow LLM to use my Adobe credentials" setting is off. The site preview is visible on the right.

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:

EMA chat after the setting is enabled: the agent confirms access works, uploads the home page to Document Authoring, and lists what changed. The preview shows the updated heading "BRUCE IS TESTING".

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/