# HTTP API authorization Authorization methods and principles used to access the HTTP APIs. The HTTP API uses [OAuth 2.0](https://datatracker.ietf.org/doc/html/rfc6750) to authorize requests to the API. Learn more about OAuth 2.0 for API authentication in our self-paced Authorization flows and API Clients module. ## Authorization overview To authorize your application, do the following: 1. Determine the appropriate [scopes](/api/scopes.md) that the client will use. 2. Create an API Client in the [Merchant Center](/merchant-center/) or through the [API Clients API](/api/projects/api-clients.md). 3. Request an access token through the [OAuth 2.0 service](/api/authorization.md#request-an-access-token-using-the-internal-oauth-20-service), an [external OAuth server](/api/authorization.md#request-an-access-token-using-an-external-oauth-server), or both. We recommend that you use the internal OAuth 2.0 authorization flows unless your business needs require external OAuth. If you use external OAuth, you can continue to use tokens issued by the internal OAuth 2.0 service. If you received a refresh token, you can use the [refresh token flow](/api/authorization.md#refresh-token-flow) to request future tokens. ## Best practices To help keep the API Client secrets secure in your environments, follow these best practices: - **Rotate API Clients periodically.** Create new API Clients regularly and change them immediately if you detect suspicious activities. Then, update your applications to use the new API Clients and delete the old ones. This practice helps minimize potential risks if a client is ever compromised and strengthens the protection of sensitive data by preventing attackers from re-using a compromised client. - **Limit API scopes and permissions.** Follow the least privilege and need-to-know principles by restricting permissions to the minimum necessary for each application and using different API clients. This reduces the impact of a compromised API Client and the risk of unauthorized access. - **Use secure storage.** Store API Client credentials securely using encryption and access controls. Avoid hardcoding credentials directly into your application code. - **Centralize management.** Use a centralized system to manage and control API Clients. This facilitates tracking, monitoring, and revoking access when necessary. - **Implement monitoring and logging.** As part of your own logging and monitoring processes, regularly monitor the API Client activity in the environments of your applications to identify and address suspicious or unauthorized behavior. ## Request an access token using the internal OAuth 2.0 service ### Authorization URL To request an access token from the internal OAuth 2.0 service, use the authorization URL according to the [Region](/api/general-concepts.md#regions) your Project is located in: | Region | Authorization URL | | --- | --- | | North America (Google Cloud, Iowa) | `https://auth.us-central1.gcp.commercetools.com/` | | North America (AWS, Ohio) | `https://auth.us-east-2.aws.commercetools.com/` | | Europe (Google Cloud, Belgium) | `https://auth.europe-west1.gcp.commercetools.com/` | | Europe (AWS, Frankfurt) | `https://auth.eu-central-1.aws.commercetools.com/` | | Australia (Google Cloud, Sydney) | `https://auth.australia-southeast1.gcp.commercetools.com/` | The following hostnames are [deprecated](/offering/compatibility.md#deprecation), but remain accessible as aliases: - `auth.sphere.io` (Google Cloud, Belgium) - `auth.commercetools.co` (Google Cloud, Iowa) If your Project uses either of these hostnames, we recommend that you update your configuration to the current hostnames. The Authorization API provides the following authorization flows: - [Client credentials](/api/authorization.md#client-credentials-flow): creates a token for an **API Client**. - [Password flow](/api/authorization.md#password-flow): creates a token by using a **customer's login credentials**. These tokens are used with [Me endpoints](/api/me-endpoints-overview.md) for operations scoped to a specific user session. - [Anonymous session flow](/api/authorization.md#tokens-for-anonymous-sessions): creates a token for an **anonymous session**. These tokens are used with [Me endpoints](/api/me-endpoints-overview.md) for operations scoped to a specific user session or guest checkout scenario. A customer using this token might at some point log in or sign up by using the password flow. - [Refresh token flow](/api/authorization.md#refresh-token-flow): **refreshes an access token**. The [commercetools SDKs](/api/dev-tooling/) provide built-in support for obtaining and managing access tokens. ### Client credentials flow To obtain an access token through the client credentials flow, issue the following request to the auth service by providing your `client_id` and `client_secret` via [HTTP Basic Authentication](https://en.wikipedia.org/wiki/Basic_access_authentication). Here, the username is the `client_id` and the password is the `client_secret`: ```bash POST https://{auth_host}/oauth/token Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ== Content-Type: application/x-www-form-urlencoded grant_type=client_credentials&scope={scope} ``` #### Example request ```bash $curl https://{auth_host}/oauth/token -X POST --basic --user "{clientId}:{clientSecret}" -d "grant_type=client_credentials&scope=manage_project:{projectKey}" ``` #### Example response ```json { "access_token": "vkFuQ6oTwj8_Ye4eiRSsqMeqLYNeQRJi", "expires_in": 172800, // seconds (2 days) "scope": "manage_project:{projectKey}", "token_type": "Bearer" } ``` By default, access tokens issued through the client credentials flow expire after **48** hours. Parameters are provided using the `application/x-www-form-urlencoded` media type. The [scope](/api/scopes.md) parameter is optional, but recommended. ### Password flow To obtain an access token through the password flow, provide the `email` and unencrypted `password` of the [Customer](/urn?urn=ctp%3Aapi%3Atype%3ACustomer) in addition to your OAuth client credentials. The response contains the access token and refresh token. If an access token expires, you can use the refresh token to obtain a new access token without supplying the Customer's `email` and `password` again. By default, access tokens issued through the password flow expire after **48** hours. #### Password flow for global Customers Use this flow when your Customer is not associated with any Stores. To obtain an access token for a Customer in a specific Store, see [Password flow for Customers in a Store](/api/authorization.md#password-flow-for-customers-in-a-store). ```bash POST https://{auth_host}/oauth/{projectKey}/customers/token Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ== Content-Type: application/x-www-form-urlencoded grant_type=password&username={email}&password={password}&scope={scope} ``` ##### Example request ```bash $curl https://{auth_host}/oauth/{projectKey}/customers/token -X POST --basic --user "{clientId}:{clientSecret}" -d "grant_type=password&username=alice@example.com&password=secret&scope=view_published_products:{projectKey} manage_my_orders:{projectKey} manage_my_profile:{projectKey}" ``` ##### Example response ```json { "access_token": "v-dZ10ZCpvbGfwcFniXqfkAj0vq1yZVI", "expires_in": 172800, // seconds (2 days) "scope": "view_published_products:{projectKey} manage_my_orders:{projectKey} manage_my_profile:{projectKey} customer_id:{id}", "refresh_token": "{projectKey}:OWStLG0eaeVs7Yx3-mHcn8iAZohBohCiJSDdK1UCJ9U", "token_type": "Bearer" } ``` #### Password flow for Customers in a Store Use this flow when a Customer belongs to one or more Stores. The access token is valid only for the Store specified in the request. ```bash POST https://{auth_host}/oauth/{projectKey}/in-store/key={storeKey}/customers/token Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ== Content-Type: application/x-www-form-urlencoded grant_type=password&username={email}&password={password}&scope={scope} ``` ### Refresh token flow The refresh token flow is used when the access token obtained through the password flow expires. It lets you continue the user’s session or provide ongoing access without asking the user to log in again, thereby maintaining a seamless user experience. To obtain an access token through the refresh token flow, provide the OAuth client credentials and the refresh token. ```bash POST https://{auth_host}/oauth/token Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ== Content-Type: application/x-www-form-urlencoded grant_type=refresh_token&refresh_token={token} ``` Each successful refresh token request returns a new access token with a fresh lifetime. Refreshing an access token does not extend the validity of the refresh token itself. By default, refresh tokens expire 200 days after last usage or if the limit of **10 million** refresh tokens is exceeded (in the latter case, the least recently used tokens expire first). Therefore a refresh token that is frequently used will never expire. ### Tokens for anonymous sessions Anonymous sessions give users access to resources or services that do not require personal identification. This is useful in scenarios where you need to offer certain functionality to your customers without requiring them to log in or create an account. To obtain an access token for an anonymous session, the OAuth client needs the `create_anonymous_token` scope. The regular [client credentials flow](/api/authorization.md#client-credentials-flow) is used. These access tokens are similar to those issued with the [password flow](/api/authorization.md#password-flow), but instead of being linked to a specific customer, they are associated with an `anonymousId`. In addition to the access token, a refresh token is issued. The refresh token is the only way to get a new access token for the associated `anonymousId`. By default, access tokens issued for anonymous sessions expire after **48** hours. The `anonymousId` is either generated by the API or an unused ID can be supplied by adding the `anonymous_id={id}` parameter. ```bash POST https://{auth_host}/oauth/{projectKey}/anonymous/token Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ== Content-Type: application/x-www-form-urlencoded grant_type=client_credentials&scope={scope} ``` #### Example request ```bash $curl https://{auth_host}/oauth/{projectKey}/anonymous/token -X POST --basic --user "{clientId}:{clientSecret}" -d "grant_type=client_credentials&scope=view_published_products:{projectKey} manage_my_orders:{projectKey} manage_my_profile:{projectKey}&anonymous_id={uniqueId}" ``` #### Example response ```json { "access_token": "v-dZ10ZCpvbGfwcFniXqfkAj0vq1yZVI", "expires_in": 172800, // seconds (2 days) "scope": "view_published_products:{projectKey} manage_my_orders:{projectKey} manage_my_profile:{projectKey} anonymous_id={uniqueId}", "refresh_token": "{projectKey}:OWStLG0eaeVs7Yx3-mHcn8iAZohBohCiJSDdK1UCJ9U", "token_type": "Bearer" } ``` ### Introspection The authorization service also implements [OAuth 2.0 Token Introspection](https://datatracker.ietf.org/doc/html/rfc7662) available under `/oauth/introspect`. This feature lets you verify the active state of an OAuth 2.0 access token and retrieve meta-information such as the `scope`. Like the other endpoints, it is protected by client authentication. A client can always introspect its own access tokens. A client with `introspect_oauth_tokens:{projectKey}` permission (also implied by `manage_project`) can introspect any access token in that project, even if it was issued to a different client. If the requesting client does not have the permission to introspect the given token, it is treated as not active and no further information is returned. This endpoint can only introspect tokens that are issued by the [internal OAuth 2.0 service](/api/authorization.md#request-an-access-token-using-the-internal-oauth-20-service). External OAuth tokens must be introspected at the external service. #### Example request ```bash $curl https://{auth_host}/oauth/introspect -X POST --basic --user "{clientId}:{clientSecret}" -d "token=nbzLp_xTvAmPJnilFuZGaiukILpuaCxQ" ``` #### Example response (active) ```json { "active": true, "scope": "view_products:example-project-26", "exp": 1501158800852, // Unix epoch (Thu Jul 27 2017 12:33:20 GMT+0000) "client_id": "tl-zzoobQGyBbFhqccWB_ZiK" } ``` #### Example response (inactive) ```json { "active": false } ``` If `active` is true, the access token can currently be used with the API, within the `scope`. The `exp` timestamp indicates when this token will expire. You may cache the result, but consider that a token can not only expire, but also be revoked earlier (for example if the client that issued the token is deleted). The [RFC 7662, Section 4](https://datatracker.ietf.org/doc/html/rfc7662#section-4) summarizes the tradeoff in the second-last paragraph. ## Request an access token using an external OAuth server To use OAuth 2.0 Bearer tokens issued by another service, provide an RFC 7662-compliant [OAuth 2.0 Token Introspection](https://datatracker.ietf.org/doc/html/rfc7662) endpoint to your Project using the [Set ExternalOAuth](/api/projects/project.md#set-externaloauth) update action. The Authorization API calls the provided endpoint to verify the validity of the token and check the token's scopes. The API only accepts its own scopes. Any scopes that are not listed in the [Scopes](/api/scopes.md) section are ignored. Some services, especially OpenID Connect implementations, might already provide such an endpoint and might allow embedding permissions specific to the API into the scope. In other cases, you might need to implement a service specifically to verify the token or create the scope. A Project that uses tokens issued by an external OAuth service can continue to use tokens issued by the built-in authorization service. The APIs validate the tokens against the respective introspection endpoints with no additional configuration required. The API might cache External OAuth tokens for up to 30 minutes to improve response times. Using external OAuth tokens affects performance. If the token introspection fails, the API call fails. If the introspection takes 200 ms to return a result, then the API call also takes 200 ms longer to complete. ![External OAuth sequence diagram](https://docs.commercetools.com/api/images/external-auth.svg) ### Headers When calling the introspection endpoint of an external OAuth server, in addition to the `Authorization` header, the request will also contain a [correlation ID](/api/general-concepts.md#correlation-id) if there is one available: - `X-Correlation-ID` - A correlation ID can be used to track a request. The same correlation ID will be returned to the original caller of the API. ### Secure the OAuth introspection endpoint As specified in [RFC 7662](https://datatracker.ietf.org/doc/html/rfc7662), the OAuth introspection endpoint must not be publicly accessible. You need to configure the Authorization Header that you want the API to use. For example, you can use [HTTP Basic Authentication](https://en.wikipedia.org/wiki/Basic_access_authentication) by saving a header like `Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==`. You can also use OAuth 2.0 Bearer tokens, and refresh the used token on a regular basis by updating the Project configuration. ### Handle permissions for customer accounts or anonymous sessions If you want to use external OAuth tokens with the `/me` endpoints, you'll have to add an already existing customer account, or an anonymous session, into the scope. For a customer account, add `customer_id:{id}`, for an anonymous session, add `anonymous_id:{id}` to the scope. The synchronization of customer accounts between the external service and the API should, for performance reasons, not be done during the token verification. Ideally, the customer accounts are created before a token for the customer is issued to be used with the APIs. When you construct the `scope` value for an external OAuth token, include every scope required by the target endpoint. Don't rely on implied permissions when defining the token scope. For example, to read Products, include `view_products:{projectKey}` explicitly in the token scope. ### Limits and error cases The External OAuth token introspection affects the performance and uptime of the API. Therefore, you should carefully consider the technology used to implement the introspection and your hosting options. Regardless of the technology choice, ensure that the network latency between the [Region](/api/general-concepts.md#regions) where your Project is located and your introspection endpoint is as low as possible. #### Time limits If the introspection does not respond fast enough, then the whole API call is blocked. As a result, we enforce the following limits: - The introspection endpoint must return a result within 500 ms to the Authorization API. This includes the network latency between the two. We recommend that your introspection endpoint returns results much faster than 500 ms. A good target is to respond within less than 50 ms. #### Error cases In any error case (no response within the time limit or a bad response like a `500` HTTP status code) the API call fails. The introspection is not retried within an API call. Further API calls will try to reach the introspection endpoint again. The following errors codes are returned when the introspection endpoint does not respond successfully: - [502 or 504 ExternalOAuthFailed](/api/errors.md#externaloauthfailed) ### Examples Assuming you have configured the URL `https://example.org/oauth/introspect` and the Authorization Header `Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==`, and you make a request to `/{projectKey}/products`, your endpoint will receive the following request: ```json POST /oauth/introspect Host: example.org Content-Type: application/x-www-form-urlencoded Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ== token={token} ``` If your endpoint responds with the following, the API request will succeed: ```json HTTP/1.1 200 OK Content-Type: application/json { "active": true, "scope": "view_published_products:{projectKey}" } ``` If your endpoint responds with one of the following, the API request will not succeed, either because the token is invalid, or because the client does not have the permission to view products: ```json HTTP/1.1 200 OK Content-Type: application/json { "active": false } ``` ```json HTTP/1.1 200 OK Content-Type: application/json { "active": true, "scope": "view_orders:{projectKey}" } ``` The following example shows a response for a token that can be used with the `/me` endpoints: ```json HTTP/1.1 200 OK Content-Type: application/json { "active": true, "scope": "view_products:{projectKey} manage_my_orders:{projectKey} manage_my_profile:{projectKey} customer_id:{id}" } ``` ## Use an access token Upon successful completion of an authorization flow, the OAuth 2.0 service returns an `access_token`. Use the access token in the `Authorization` header of all requests as follows: ```bash POST /{{projectKey}}/channels HTTP/1.1 Host: api.{region}.commercetools.com Authorization: Bearer {accesstoken} ... ``` The HTTP API does not support sending access tokens as URI parameters, as defined in [RFC 6750 section 2.3](https://datatracker.ietf.org/doc/html/rfc6750#section-2.3). The remaining lifetime of an access token is indicated by its `expires_in` field. ## Manage token requests For security reasons, we advise requesting tokens sparingly and keeping the number of active tokens to a minimum whenever possible. We do not recommend requesting a token for every work item. If a client application requests too many tokens, it might be rate-limited. We recommend getting new tokens when appropriate using automatic token management. Our SDK clients provide support for automatic token management, or you can implement token management yourself. ### Short-lived applications In some scenarios, your SDK clients are short-lived. For example, a script triggered by a cron job which creates a client every time the job runs, or a function in a serverless Function-as-a-Service environment. We recommend the following approaches when working with short-lived client applications to reduce the number of requested tokens. One approach is to store a token either in the filesystem, a cache, or the application's configuration. You can then refresh the token at a regular interval. In this approach, all instances of your application use the same token. If using the TypeScript SDK, you can pass an existing token to the client using [withExistingTokenFlow](/api/dev-tooling/ts-sdk-middleware.md#withexistingtokenflow). In a serverless FaaS environment, you should be able to use the global execution context to store your client across warm invocations (when the FaaS re-uses a function instance and it is not subject to a cold-start). [Here](/api/downloads/lambda-reusing-client-example.js) is an example for an AWS Lambda function that uses the [execution context](https://docs.aws.amazon.com/lambda/latest/dg/running-lambda-code.html). ### Create anonymous sessions only once necessary At first sight, creating a new token with a new anonymous session on the first request is the most straight forward implementation. However, this pattern results in a very high number of unused anonymous sessions, for example if a stateless web crawler acts like a new visitor on every request or if visitors drop off after only browsing the site. To avoid creating unused anonymous sessions, hold a visitor-independent [client credentials flow](/api/authorization.md#client-credentials-flow) token (for example with only the `view_published_products` scope) and only request a token with an anonymous session when the visitor creates a cart, shopping list or other visitor-specific resource. A single API Client can be used to create both types of tokens. Note that the number of refresh tokens is limited to **10 million**. If the limit is exceeded, the least recently used refresh tokens are deleted. Creating new refresh tokens continues to work. ## Revoke tokens The authorization service implements [Auth 2.0 Token Revocation](https://datatracker.ietf.org/doc/html/rfc7009) under `/oauth/token/revoke`. This endpoint provides a mechanism to invalidate access and refresh tokens within the authorization server. For example, when a customer logs out, changes identity, or uninstalls your application, you might want to revoke the tokens associated with the customer. This behavior prevents the abuse of abandoned tokens and can contribute to a better customer experience. Only tokens that were issued to the client making the revocation request are allowed to be revoked by the client. To revoke a token, it is necessary to provide the token, and optionally a type hint. The type hint can either be `refresh_token` or `access_token`. Parameters are provided using the `application/x-www-form-urlencoded` media type. This endpoint will revoke an existing token, even if the type hint is incorrect. For example, if you provide an access token, and the type hint suggests that it is a refresh token, the endpoint will still revoke it. Providing an accurate token hint will result in a faster response time. However, if you are unsure about the token type, it is more efficient to not provide the hint at all. ### Example request ```bash $curl https://{auth_host}/oauth/token/revoke -X POST --basic --user "{clientId}:{clientSecret}" -d "token={token}&token_type_hint={access_token|refresh_token}" ``` ### Response The endpoint will only provide a status code for the response: - `200` - the token was found and revoked, or the token request was invalid. - `5xx` - in case of a server error, the client has to assume that the token still exists, and should retry after a reasonable delay. ## Related pages - [Area overview page with navigation](/api.md) - [Next page: Scopes](/api/scopes.md)