Authentication and authorization
An important aspect of any Composable Commerce project is Identity and Access Management (IAM), which relies on the concepts of authentication and authorization.
After completing this page, you should be able to:
- Explain the processes an API Client uses to grant access tokens to resources.
Authentication is the process of verifying an identity, while authorization is the process of verifying what that identity has permissions to do. While often mistaken as a single concept, they are actually two distinct processes that work together.
You have two options to manage these processes with Composable Commerce:
Use Composable Commerce’s OAuth 2.0 server, which uses the OAuth 2.0 Authorization Framework.
Use an external OAuth 2.0 server.
If you choose to use an external OAuth 2.0 server, you are responsible for the uptime and reliability of the service. For example, the introspection endpoint must return a result within
500 ms
to the Authorization API, otherwise the request would fail. This time limit includes any network latency that may occur.
API Clients
To access the Composable Commerce APIs you need to create an API Client inside your Project. Each Project can have multiple API Clients, each used for a specific application.
API Clients grant tokens from https://auth.{region}.commercetools.com
, which are then used to access resources on https://api.{region}.commercetools.com
.
An API Client consists of the following:
Field | Description |
---|---|
id | Unique identifier of the OAuth 2.0 client that is used to obtain an access token. |
name | User-defined name. |
scope | User-defined set of scopes available to the API Client. When using Stores, you can add them as scopes. |
secret | Secret that is used to obtain an access token. |
lastUsedAt | Date of the last day the API Client was used to obtain an access token. |
deleteAt | If set, the API Client is automatically deleted after the specified date and time. |
accessTokenValiditySeconds | Expiration time in seconds for each access token obtained by the API Client. |
refreshTokenValiditySeconds | Inactivity expiration time in seconds for each refresh token obtained by the API Client. |
createdAt | Date and time the API Client was initially created at. |
The first API Client in a Project must be created using the Merchant Center. After that, you can use either the Merchant Center or the Authorization API to create additional API Clients, depending on your specific requirements.
The Create API Client endpoint on the Authorization API is helpful in these common scenarios:
- When you use an infrastructure as code service (such as Terraform) or a configuration management solution.
- When you need to define when the API Client's access expires.
Temporary access
API Clients remain valid until they are deleted in the Merchant Center or through the Delete API Client endpoint, unless a deleteDaysAfterCreation
value is set during creation. The system automatically deletes the API Client once the date calculated in deleteDaysAfterCreation
has passed.
The validity period of the tokens generated by the API Client is determined by the values assigned to the accessTokenValiditySeconds
and refreshTokenValiditySeconds
properties on the API Client. If these properties are not set at the creation of the API Client, the default validity is used.
If you need to provide temporary access, for example, to a third party such as a contract developer or systems integrator, you can provide them with their own API Client. In this case, you can set a value for deleteDaysAfterCreation
through the Create API Client endpoint. This ensures that access is automatically revoked at the end of the contract period. In addition, you can track changes made by the API Client with Audit Log Premium.
Application-specific usage
We recommend that you create an API Client for each application that you have.
Let's imagine that your Project contains the following application integrations:
- A commerce website using a composable frontend.
- A product information management (PIM) system integration using an off-the-shelf connector.
- A custom-built integration to sync new Orders to the enterprise resource planning (ERP) system.
In this case, you should create three API Clients, each with its own distinct scopes that are limited to only what is absolutely necessary for that application. In the event of a security breach that exposes the API Client or token(s) of a single application, the potential impact will be limited. This is also the reason that we advise against creating a general-purpose API Client with permissive scopes.
Grant types and usage
Grant types are the methods available to an application to generate an access token that grants access to the resources of your Composable Commerce Project. An API Client can use different grant types based on the configured scopes.
The following grant types are used in Composable Commerce:
- Client credentials
- Password and anonymous (often used together)
Grant types are paired with a commerce application, and the grant flow is done client side or server side.
The following table describes how each grant type is commonly used:
Client credentials | Password and anonymous | |
---|---|---|
Expected scopes | General (non-me) | Me |
Token consumed by | Server | Client or server |
Session management | You are responsible for tracking the user's state (for example, logged-in status) across multiple requests. | Provided. Unique tokens are granted to each user. |
Integrations using this token type | General commerce applications, product information management (PIM) systems, order management systems (OMS), enterprise resource planning (ERP) systems, data lakes, etc. | Commerce applications |
Applications that do not have a middleware but require access to resources restricted to a particular Customer can use the password or anonymous flows. This allows them to acquire an access token specifically scoped to the me endpoints. Scopes designed for the me endpoints include "my" within the scope name (for example, manage_my_carts
and manage_my_shopping_lists
). These scopes and endpoints ensure that the Customer (or anonymous user) can only view and modify their own resources.
One exception to an application using only scopes designed for the me endpoints, is when the application also grants the view_products
scope. Allowing this scope is acceptable when all Customers are permitted to view the same products.
Each me endpoint contains a subset of functionality compared to its corresponding general endpoint. For example, My Carts is derived from the full-featured Carts API general endpoint. Due to the functional differences between these endpoint types, we recommend that you only use me endpoints in the absence of a middleware layer.
Grant flows
Client credentials flow
The client credentials flow is used for general application usage and unlike the password and anonymous flows, is not scoped towards any individual Customer (or anonymous user).
This grant type uses a backend server to complete the grant flow. For security purposes, the token is stored on the server and is not shared with the client.
- The frontend application makes a request to the backend server, such as a Backend for Frontend (BFF).
- The backend server requests an access token from the authentication server using the client credentials (
client_id
andclient_secret
). - The authentication server validates the client credentials and sends back the
access_token
,token_type
,expires_in
, andscope
. - The backend server uses the
access_token
to access the commercetools API. - The commercetools API returns the data to the backend server.
- The backend server processes and returns the data to the frontend.
Validation example
Let's take a closer look at steps #2 and #3, where the authentication server validates the client credentials.
The following example is a request for an access token to the authentication server:
https://{auth_host}/oauth/token -X POST \--basic --user "{clientId}:{clientSecret}" \-d "grant_type=client_credentials&scope=manage_products:furniture_shop_au_prodmanage_customers:furniture_shop_au_prod"
If you have a Composable Commerce Project, you can create your own API Client and cURL this request using your credentials.
Specify the values that were provided to you when you created the API Client:
auth_host
: the authentication server for your Project. A list of all authentication hosts can be found here.clientId
clientSecret
scope
(optional)
A successful request will return a response similar to this:
{"access_token": "RydkYXkgbWF0ZSwgYWNjZXNzIHRva2Vu","token_type": "Bearer","expires_in": 172800,"scope": "manage_products:furniture_shop_au_prodmanage_customers:furniture_shop_au_prodview_products:furniture_shop_au_prodview_customers:furniture_shop_au_prod"}
access_token
: the token to access resources through the commercetools APItoken_type
: the type of the tokenexpires_in
: the number of seconds until token expiration (48 hours by default)scope
: the list of granted scopes
In the client credentials flow, we only requested the manage_products
and manage_customers
scopes, yet the view_products
and view_customers
scopes were also granted. This is because managing a resource inherently involves viewing it.
It is important to note that the inverse is not true: a token can be granted view-only access for a given resource.
Password flow
The password flow uses the Customer's username (email) and password to create an access token.
Client-side grant
- The client-side application requests an access token from the authentication server using the user-provided credentials (username and password).
- The authentication server validates the credentials and sends back the
access_token
,token_type
,refresh_token
,expires_in
, andscope
. - The client-side application uses the
access_token
to access the commercetools API. - The commercetools API returns the data to the client-side application.
Authentication flows that occur on the client application are susceptible to credential exposure and token misuse. For example, a malicious actor could utilize a man-in-the-middle attack to gain access to tokens granted to the user. These tokens could then be used to make direct requests to the API server. This can pose a problem when you wish to hide implementation details such as sensitive Product attributes, Cart fields, Customer fields, or any other sensitive fields of a resource that this token has access to.
Server-side grant
The client-side application sends the user-provided credentials (username and password) to the backend server.
The backend server requests an access token from the authentication server using the user’s credentials.
The authentication server validates these credentials and sends back the
access_token
,token_type
,refresh_token
,expires_in
, andscope
.The backend server uses the
access_token
to access the commercetools API.The commercetools API returns the data to the backend server.
The backend server processes the data using one of the following options:
- Option 1: Encrypts the tokens on the backend server and sends them to the client-side application as an encrypted cookie. The client-side application then stores the cookie locally and includes it with each request to the backend server.
- Option 2: The tokens are stored in a cache on the backend server and a reference to the cache is sent to the client-side application as a cookie. The client-side application then stores the cookie locally and includes it with each request to the backend server.
In this flow, the authorization happens on the backend server and ensures that the client-side application never sees the actual token values. This method reduces the risk of unauthorized access to the commercetools APIs.
Anonymous session flow
This flow creates a token for each anonymous session, which can be used, for example, in guest checkout scenarios where the user hasn't logged in.
Anonymous tokens are similar to tokens issued with the password grant flow and are intended to be used with scopes designed for the me endpoints. This token type returns a unique anonymous_id
that is used to access a user's resources. If a user with an anonymous_id
creates an account, this identifier can also be used to assign any existing resources to the newly created Customer.
It is standard practice to use the anonymous and password flows together in the same application but not the client credentials flow.
Common errors
When consuming client credentials, password, or anonymous flow tokens, different errors can be returned. You can define solutions to handle these errors and recover without needing human intervention.
Authentication server errors
Error code | Error meaning | Suggested handling |
---|---|---|
401 | Credentials are invalid or the API Client doesn't exist | Send the error to your logging system. Have your logging system send alerts for this critical error (for production). |
400, 404 | Bad request | Send the error to your logging system. Have your logging system send alerts for this critical error (for production). |
API server errors
Error code | Token type | Error meaning | Suggested handling |
---|---|---|---|
401 | Client credentials | Token expired or the API Client doesn't exist | Programmatically try to obtain a new token through the grant flow. Observe if a new token is granted or if the authentication server returns an error. Send the error to your logging system. |
400, 404 | Client credentials, Anonymous, Password | Bad request | Send the error to your logging system. |
401 | Anonymous, Password | Token expired or the API Client doesn't exist | Programmatically use the refresh token to grant a new access token. If this fails, try to get a new token through the grant flow and if that fails, there is a problem with the API Client.
|
503 | Any | Service Unavailable | The token consumer can assume that the token is still valid, and should retry the request after a reasonable delay. Try using an exponential backoff with a maximum retry limit. Send the error(s) to your logging system. In the unlikely event that you see continuous 503 errors, log a ticket with support and provide the correlation IDs and time period. |
We haven't mentioned using the token introspection endpoint when troubleshooting because it returns only the status of the token, scopes, expiration, and API Client ID. To avoid errors and reduce the need for an introspection endpoint, we recommend that you familiarize yourself with the common error scenarios and use the scope query parameter during the grant flow.
Common scenarios
Token expiration
All tokens have a set lifespan which you see when you:
- Create the token: the value of the
expires_in
field provides the number of seconds until the token expires. - Introspect the token: the value of the
exp
field provides a Unix timestamp that details when the token expires.
If a client credentials token expires, the client must reauthenticate by requesting a new token. If a password or anonymous flow token expires, use the refresh token flow instead of requesting a new set of tokens.
Logging out a Customer
To log out a Customer, do the following:
- Clear the user's session: if the user is not linked to the session they must re-authenticate with their credentials.
- Revoke the token: you can revoke the anonymous or password token by using the token revocation endpoint.