ddtcorex

10 Oct 2026 · 5 min read

Integration tokens, OAuth, and the admin token you should not use

Compare admin, customer, and integration tokens, rotate secrets safely, and stop using the admin token for integrations

Part 7 of the API Platform series — pick the smallest token that can do the job.

The token you should stop using

Almost every Magento team has one: an admin token minted with POST /V1/integration/admin/token, pasted into an ERP connector, a cron script, or a .env file, and never rotated. It works, so it survives. It is also the most dangerous credential in the integration landscape. That token carries the full permissions of the admin user who created it, never expires on its own, and cannot be scoped down. Whoever holds it can do anything that admin can do. This finale sorts out the three token types Magento offers and shows the rotation habit that replaces the shared admin token.

The three token types

Magento issues three kinds of bearer tokens, each for a different caller.

Admin tokens come from POST /V1/integration/admin/token with a username and password. They represent a backend user with that user's full role. They are meant for short-lived administrative scripting and manual testing, not for system-to-system traffic. Their scope follows the admin role, which almost always exceeds what one integration needs.

Customer tokens come from POST /V1/integration/customer/token with customer credentials. They carry the self scope: the caller can touch only their own cart, orders, and profile. Use them for storefront and mobile-app sessions where the acting party is the shopper. They expire according to the customer session lifetime and cannot reach other customers' data.

Integration tokens belong to integrations created under System > Extensions > Integrations. An integration declares exactly which ACL resources it needs, such as Vendor_Credit::balance_view from the previous post. Magento issues a consumer key, consumer secret, access token, and access token secret for it. These are the credentials for servers talking to servers: ERP, OMS, warehouse, and middleware. Their scope is the narrow resource list approved at activation, nothing more.

The rule is simple. A human shopper gets a customer token. A backend system gets an integration with the smallest resource set it needs. The admin token is for neither.

Why the admin token is a liability

Three properties make the shared admin token risky. First, it inherits the admin role, so a read-only sync job silently holds write and delete powers across catalog, customers, and sales. Second, it is tied to a person: when that admin leaves or changes role, the integration breaks or keeps running under a stale identity nobody owns. Third, it has no rotation story. There is no expiry forcing renewal, so the same secret spreads across scripts, vendors, and chat logs for years.

A leaked integration token with one narrow resource exposes one capability. A leaked admin token exposes the store. The fix is not a longer password on the admin account. It is removing the admin token from every automated path.

Setting up an integration the right way

Create the integration in the admin under System > Extensions > Integrations, grant only the resources the consumer needs, and activate it to receive the four OAuth values. For REST calls with token-based auth, exchange them for a bearer access token the same way other OAuth-backed integrations do, then call the API with Authorization: Bearer <token>.

For OAuth 1.0a flows, sign each request with the consumer key and secret plus the access token and secret. Most HTTP clients and middleware platforms support this natively. Prefer the bearer form where the integration supports it, because it keeps signing complexity out of every call site.

Name each integration after its consumer and purpose, for example erp-stock-sync-prod or wms-shipment-read. One integration per consumer. Shared integrations force shared scopes, and shared scopes drift toward the union of everything, which recreates the admin-token problem under a different name.

Rotation without downtime

Rotation fails when it is a surprise. Make it routine. Keep two active credential sets per integration during the window: the current set and the incoming set. Deploy the incoming set to the consumer, verify traffic on it, then revoke the old set. No flag day, no midnight deploy.

Concretely: generate the new token pair, store both in the secret manager under versioned keys such as erp-stock/token-a and erp-stock/token-b, point the consumer at the new key, watch API logs for 200s on the new credential and zero traffic on the old one, then revoke the old set in the admin. Log who performed each step. The whole procedure should fit on one runbook page.

Set a calendar interval even though Magento does not force one. Ninety days is a practical default for server-to-server credentials. Customer and admin session tokens already expire; integrations need the operational equivalent. Each rotation is also a scope review: if the integration no longer needs a resource granted a year ago, remove it before issuing the new credentials.

Store secrets where systems expect them: a vault or secret manager, injected as environment variables at runtime, never in git, never in chat, never in a ticket. If a token ever appears in a log or a screenshot, treat it as compromised and rotate immediately.

Least privilege across the series

This finale closes a loop the series opened in part one. Part 5 showed cart mutations scoped by masked quote id and customer token. Part 6 built a custom endpoint guarded by a narrow ACL resource. This post gives each caller the smallest token that reaches those guards. A storefront holds a customer token that can touch one cart. A sync job holds an integration token with one or two resources. Nothing holds an all-powerful admin token except a human doing temporary admin work.

When a new integration request arrives, answer three questions before issuing anything: who is the caller, what is the narrowest resource list, and when does this credential rotate. If any answer is vague, the integration is not ready. Precision here is cheaper than incident response later.

Closing the series

The API Platform arc moved from reading data to changing it safely: querying with GraphQL, mutating carts end to end, exposing custom REST endpoints behind service contracts and ACL, and authenticating every caller with least-privilege tokens. The throughline is contracts plus scope. Contracts keep payloads stable across upgrades. Scope keeps every credential, masked id, and ACL resource as small as the job allows.

Audit one integration this week. Find the shared admin token, replace it with a named integration carrying only the resources it needs, and put rotation on the calendar. That single swap applies everything this series argued for.

This was the final post in the API Platform series.

magento2apisecurity