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:

    FieldDescription
    idUnique identifier of the OAuth 2.0 client that is used to obtain an access token.
    nameUser-defined name.
    scopeUser-defined set of scopes available to the API Client. When using Stores, you can add them as scopes.
    secretSecret that is used to obtain an access token.
    lastUsedAtDate of the last day the API Client was used to obtain an access token.
    deleteAtIf set, the API Client is automatically deleted after the specified date and time.
    accessTokenValiditySecondsExpiration time in seconds for each access token obtained by the API Client.
    refreshTokenValiditySecondsInactivity expiration time in seconds for each refresh token obtained by the API Client.
    createdAtDate 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 credentialsPassword and anonymous
    Expected scopesGeneral (non-me)Me
    Token consumed byServerClient or server
    Session managementYou 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 typeGeneral 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).

    If you choose to use the client credentials flow, you are responsible for guaranteeing that the user's session can only access their own data and not that of others. To make this possible, Composable Commerce APIs support creating and retrieving resources that belong to a specific 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.

    1. The frontend application makes a request to the backend server, such as a Backend for Frontend (BFF).
    2. The backend server requests an access token from the authentication server using the client credentials (client_id and client_secret).
    3. The authentication server validates the client credentials and sends back the access_token, token_type, expires_in, and scope.
    4. The backend server uses the access_token to access the commercetools API.
    5. The commercetools API returns the data to the backend server.
    6. 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:

    POST requestcURL
    https://{auth_host}/oauth/token -X POST \
    --basic --user "{clientId}:{clientSecret}" \
    -d "grant_type=client_credentials&scope=manage_products:furniture_shop_au_prod
    manage_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:

    POST responsecURL
    {
    "access_token": "RydkYXkgbWF0ZSwgYWNjZXNzIHRva2Vu",
    "token_type": "Bearer",
    "expires_in": 172800,
    "scope": "manage_products:furniture_shop_au_prod
    manage_customers:furniture_shop_au_prod
    view_products:furniture_shop_au_prod
    view_customers:furniture_shop_au_prod"
    }
    • access_token: the token to access resources through the commercetools API
    • token_type: the type of the token
    • expires_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

    1. The client-side application requests an access token from the authentication server using the user-provided credentials (username and password).
    2. The authentication server validates the credentials and sends back the access_token, token_type, refresh_token, expires_in, and scope.
    3. The client-side application uses the access_token to access the commercetools API.
    4. 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

    1. The client-side application sends the user-provided credentials (username and password) to the backend server.

    2. The backend server requests an access token from the authentication server using the user’s credentials.

    3. The authentication server validates these credentials and sends back the access_token, token_type, refresh_token, expires_in, and scope.

    4. The backend server uses the access_token to access the commercetools API.

    5. The commercetools API returns the data to the backend server.

    6. 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 codeError meaningSuggested handling
    401Credentials are invalid or the API Client doesn't existSend the error to your logging system. Have your logging system send alerts for this critical error (for production).
    400, 404Bad requestSend the error to your logging system. Have your logging system send alerts for this critical error (for production).

    API server errors

    Error codeToken typeError meaningSuggested handling
    401Client credentialsToken expired or the API Client doesn't existProgrammatically 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, 404Client credentials, Anonymous, PasswordBad requestSend the error to your logging system.
    401Anonymous, PasswordToken expired or the API Client doesn't existProgrammatically 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.
    • Anonymous: you can try generating a new anonymous token. If a new token is granted, then the session can continue; otherwise, there could be a problem with the API Client. Remember that the new anonymous token will not automatically migrate any resources (Carts, Quotes, etc.)
    • Password: attempting the password grant flow again would require you to store the Customer's password, which is not advised. Instead, test whether you can create a new anonymous token, which will indicate if the API Client is valid (or not).
    503AnyService UnavailableThe 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:

    1. Clear the user's session: if the user is not linked to the session they must re-authenticate with their credentials.
    2. Revoke the token: you can revoke the anonymous or password token by using the token revocation endpoint.

    Test your knowledge