Using the API with Mobile or Browser Apps
commercetools Composable Commerce offers OAuth scopes and endpoints designed to enable a secure communication with the API from a mobile or browser app. This tutorial teaches you how you can use them. It will walk you through on how to display Products, creating a Customer account and putting a Product into a Cart.
To follow this tutorial, you should have a Project set up, as described in Getting Started.
Why we can't trust a mobile or browser app like a server
When we write a frontend that renders webpages on a server, we can trust that this code is secured from inspection, and that no man-in-the-middle attack can be performed because we control which certificates are trusted. However, when the code that communicates with the API runs on a mobile device or inside a browser, it is rather easy to inspect the code (and extract secrets, such as the OAuth client) or perform a man-in-the-middle attack (for example to steal an OAuth token).
While we give the frontend server far-reaching access to the data (for example it can access the orders of all customers), we trust it to use the API only appropriately (for example it will only render order data of the customer logged into the session). If we gave the same access to an app, there is a large risk that a hacker could access all of this data (for example the hacker could steal an OAuth token, and use it to access the order data of all customers).
Limiting access with OAuth scopes
To limit the access of an app to the data it can view or edit via the API, we can use OAuth scopes. The app should not be able to edit products, but it should display them. The view_published_products
and view_categories
scopes enable the app to retrieve only published products and categories, but not to edit that data.
We want to give the app access to some data only if it is asking for it on behalf of a customer: for example it should not have access to orders of all customers, but if a specific customer has logged in, it should be able to access their order data. We can use the OAuth password flow with the scopes manage_my_orders
(for cart and order data) and manage_my_profile
(for account-related data), along with the /me
endpoints, for that.
Creating an OAuth client
First, we need to create an OAuth client with the permissions view_published_products
, manage_my_orders
and manage_my_profile
and view_categories
. In the Merchant Center, go to the "Developer Settings" section and create a new API Client with the template "Mobile client & single-page application client" that contains the required permissions.
Copy or download the client credentials, they cannot be revealed after creation for security reasons.
Creating a regular token with the Client Credentials Flow
If we don't want to force the customer to immediately log in upon opening the app, we need to utilize the API without using the OAuth password flow. We use the OAuth client we just created to get a regular token with the three scopes we need.
$curl https://auth.{region}.commercetools.com/oauth/token --basic --user "{client_id}:{client_secret}" -X POST -d "grant_type=client_credentials&scope=view_published_products:{projectKey} manage_my_orders:{projectKey} manage_my_profile:{projectKey} view_categories:{projectKey} "
The response contains the token in the field access_token
:
{"access_token": "vkFuQ6oTwj8_Ye4eiRSsqMeqLYNeQRJi","token_type": "Bearer","expires_in": 172800,"refresh_token": "{projectKey}:OWStLG0eaeVs7Yx3-mHcn8iAZohBohCiJSDdK1UCJ9U","scope": "view_published_products:{projectKey} manage_my_orders:{projectKey} manage_my_profile:{projectKey} view_categories:{projectKey}"}
This token can now be used to access products, for example:
$curl -sH "Authorization: Bearer vkFuQ6oTwj8_Ye4eiRSsqMeqLYNeQRJi" https://api.{region}.commercetools.com/{projectKey}/product-projections?staged=true&limit=10
Creating a new Customer
Eventually, the customer will either need to log in or create a new account. The manage_my_profile
scope authorizes the token to sign up a customer.
After we have collected important information like name, email, and password from the customer, we can send their data to the API:
POST /{projectKey}/me/signup
with:
{"firstName": "Alice","lastName": "Doe","email": "alice@example.com","password": "secret"}
The command could look like following:
$curl -sH "Authorization: Bearer {access_token}" -X POST -d '{"firstName": "Alice","lastName": "Doe","email": "alice1@example.com","password": "secret"}' https://api.{region}.commercetools.com/{projectKey}/me/signup
Creating a token bound to a Customer with the Password Flow
Let's create a Password Flow token for this customer (note that we use /oauth/{projectKey}/customers/token
now):
$curl https://auth.{region}.commercetools.com/oauth/{projectKey}/customers/token --basic --user "{client_id}:{client_secret}" -X POST -d "grant_type=password&username=alice@example.com&password=secret&scope=view_published_products:{projectKey} manage_my_orders:{projectKey} manage_my_profile:{projectKey} view_categories:{projectKey}"
In addition to the regular access_token
, this response also contains the refresh_token
:
{"access_token": "v-dZ10ZCpvbGfwcFniXqfkAj0vq1yZVI","expires_in": 172800,"scope": "view_published_products:{projectKey} manage_my_orders:{projectKey} manage_my_profile:{projectKey}","refresh_token": "{projectKey}:OWStLG0eaeVs7Yx3-mHcn8iAZohBohCiJSDdK1UCJ9U","token_type": "Bearer"}
We can save the refresh token securely (for example on the mobile device) to get a new access token, without saving the email or password of the user.
$curl https://auth.{region}.commercetools.com/oauth/{projectKey}/customers/token --basic --user "{client_id}:{client_secret}" -X POST -d "grant_type=refresh_token&refresh_token={projectKey}:OWStLG0eaeVs7Yx3-mHcn8iAZohBohCiJSDdK1UCJ9U"
Note that if the customer changes their password, access tokens and refresh tokens become invalid and your app has to ask the user for the new password to get new tokens.
Using a Password Flow token
Our password flow token can be used for the same requests as before, for example we can retrieve a list of products. But we can also access data specific to the customer we've logged in with. We don't use the regular endpoints (such as /carts/
), but the endpoints designed to be used with the password flow (such as /me/carts
) instead.
For example, we can view their account data:
$curl -sH "Authorization: Bearer v-dZ10ZCpvbGfwcFniXqfkAj0vq1yZVI" https://api.{region}.commercetools.com/{projectKey}/me
or view their carts:
$curl -sH "Authorization: Bearer v-dZ10ZCpvbGfwcFniXqfkAj0vq1yZVI" https://api.{region}.commercetools.com/{projectKey}/me/carts
Writing with a Password Flow token
We also have write access to the data of the customer. For example, we can create a new cart:
POST /{projectKey}/me/carts
with:
{"currency": "USD","country": "US"}
This looks very similar to the regular Create Cart, but there is a big difference: The cart will automatically belong to the customer we've logged in with, for example the customerId
will be the ID of Alice.
We can now use this cart much like we're using any other cart, for example we can add a line item:
POST /{projectKey}/me/carts/<cart-id>
with:
{"version": <cart-version>,"actions": [{"action": "addLineItem","productId": "<product-id>","variantId": 1,"quantity": 1}]}
CORS and Browser Apps
Cross-origin resource sharing (CORS) is a mechanism implemented in web browsers, which will either allow or deny requests coming from your web app to the commercetools servers. When your app sends an HTTP request to our domain, the browser will send an additional preflight request, to see which headers are accepted by our servers.
Currently, the Composable Commerce API will respond with the following Access-Control-Allow-Headers
value: Accept, Authorization, Content-Type, Origin, User-Agent, X-Correlation-ID
. That effectively means you can use these 6 headers when sending requests from your browser apps directly to our servers.
Conclusion
You've seen how to get a regular token to view products without having to log in a customer, how to get a token with the password flow and how to use it with the /me
endpoints. Now you can securely use the Composable Commerce APIs from a mobile app or a browser application!