Skip to content

Authentication

The mock ships a working OAuth2 server so the commercetools SDK’s token flows succeed. By default authentication is relaxed — tokens are issued but not required or verified — which is what most tests want. You can tighten it with two options.

OptionDefaultEffect
enableAuthenticationfalseWhen true, API routes require the request to be checked for a bearer token. When false, API requests need no Authorization header at all.
validateCredentialsfalseWhen true and enableAuthentication is on, a bearer token that was actually issued by the mock is required. When false, tokens are optional and never verified.
enableAuthenticationvalidateCredentialsBehaviour
false (default)(any)No auth enforced. No Authorization header needed on API requests.
truefalseToken optional and unverified. If a recognised token is sent, the associated clientId is recorded on createdBy/lastModifiedBy.
truetrueA bearer token issued by the mock is required. Missing or unknown token → 401 invalid_token.

The OAuth2 server is mounted under /oauth and exposes:

EndpointGrant typesPurpose
POST /oauth/tokenclient_credentials, refresh_tokenStandard client and refresh tokens.
POST /oauth/{projectKey}/customers/tokenpasswordCustomer (password) sign-in token.
POST /oauth/{projectKey}/in-store/key={storeKey}/customers/tokenpasswordIn-store customer token.
POST /oauth/{projectKey}/anonymous/tokenclient_credentialsAnonymous session token.

All of these require an HTTP Basic Authorization header carrying the client id/secret — but see the gotcha: the id/secret values are not validated, any non-empty pair is accepted.

{
"access_token": "<random base64>",
"token_type": "Bearer",
"expires_in": 172800,
"scope": "<requested scope, or \"todo\" if none>",
"refresh_token": "my-project-<random>"
}

Tokens are held in memory and are accessible from your test through ctMock.authStore().

With the default options this “just works” — the SDK requests a token, the mock issues one, and API requests succeed without any bearer check. To require valid tokens:

const ctMock = new CommercetoolsMock({
defaultProjectKey: 'my-project',
enableAuthentication: true,
validateCredentials: true,
})

Now every API request must carry a bearer token that the mock issued (i.e. the SDK must have completed a token request first). Requests without one get 401 invalid_token.

The customer token endpoint validates the supplied username/password against the customers that exist in the project. Create the customer first through the API:

await apiRoot
.customers()
.post({ body: { email: 'jane@example.com', password: 's3cret' } })
.execute()

A matching customer yields a token whose scope carries customer_id:<id>; no match returns 400 invalid_customer_account_credentials.

POST /oauth/{projectKey}/anonymous/token issues a token with an anonymous_id:<uuid> appended to the scope — useful for testing anonymous cart flows.

These differ from real commercetools and are worth knowing when writing tests:

  • Client id/secret are never verified. Any non-empty Basic credentials are accepted by the token endpoints. Use validateCredentials if you want to assert that a token was obtained before API calls.
  • enableAuthentication does not protect the token endpoints — they always require a Basic header regardless.
  • expires_in is always 172800 (48h) and is never enforced. Token expiry cannot be simulated; validateCredentials only checks that a token exists.
  • Scope defaults to the literal "todo" for client tokens when none is requested.
  • /me endpoints do not consume the token’s customer_id scope. Customer identity for /me routes comes from the request payload (e.g. login), not from the bearer token. Per-customer data isolation on /me is therefore not enforced based on the token.

See also: API coverage & limitations.