Restricting API Access
Even though Saleor implements complex authorization and authentication mechanisms, you might want to restrict access to your Saleor Cloud instance for specific use cases.
Below, we explore two ways Saleor Cloud allows you to restrict access to the API, as well as a practical example of how to use one of them.
Allowed API origins
If the list of the origins you expect to call your API is known in advance, you can automatically reject the unknown ones.
In the project view of your Saleor Cloud dashboard, you can customize the allowed origins. The default option is to "Allow All" but you can also specify a list of origins or set it to "Dashboard only".
We don't recommend using the "Allow All" setting on production environments. It's a good practice to restrict the access to the API to only the origins you expect.
Changing the settings to only allow the selected origins can affect the installed apps. If you want your app to call the Saleor API from the client, you need to add the app's origin to the list of allowed origins. You can read more about the app's access scopes in the App permissions document.
You don't need to specify the Saleor Cloud dashboard origin, as it is always allowed to call the Saleor API.
API Password Protection
Another way to restrict access to your Saleor Cloud instance is to protect it with a password through Basic Auth. This way, you can ensure that only those with the credentials can access the API.
After enabling password protection, users trying to open the Saleor Dashboard will be prompted to enter the Basic Auth username and password besides their own Saleor Cloud credentials.
Combined with a server-side proxy, this can be a useful tool to obscure the Saleor API from unauthorized access. We will explore this in more detail in the example below.
Example: Password-protected API proxy
Overview
By default, Saleor exposes some parts of its API publicly, like product catalog or checkout. This behavior doesn't have to align with the requirements of your business. However, Saleor Cloud allows you to restrict access to the API by setting up a Basic Auth.
Imagine you don't want your products to be publicly accessible. To achieve this, we will create a proxy server that will know the credentials and the API URL and thus be able to access the Saleor API. The only way to get to the Saleor API will be through that proxy server.
Here is how it may look in practice in the example of a simple Next.js application. At the moment, it calls the Saleor API directly:
Next.js gives you the ability to create API routes, which are server-side endpoints that must be created in the pages/api
directory.
While we chose to use Next.js in this example, you can use any server-side technology to create the proxy server.
Implementation
Step 1: Protect the Saleor API with a password
Set up "API Password Protection" in the Saleor Cloud dashboard as described above.
Step 2: Visit your current implementation
In the current implementation, your Next.js application calls the Saleor API directly:
In a production-grade Next.js application, you most likely would use some GraphQL client (like Apollo Client) to fetch the data from the Saleor API. However, for simplicity, we will use the native fetch
API in this example.
async function getProducts() {
const response = await fetch("https://your-store.saleor.cloud/graphql", { // The URL of your Saleor instance
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
// The GraphQL query you want to execute
query: `
query GetProducts {
products(first: 10) {
edges {
node {
id
}
}
}
}
`,
}),
});
const data = await response.json();
// ...
}
const ProductList = () => {
useEffect(() => {
getProducts();
}, []);
return (
// ...
);
}
Our goal is to change the code above as little as possible when introducing the proxy server.
Step 3: Create a proxy API route
In most cases, you would call the Saleor GraphQL API straight from the React component. However, given that we want to obscure the Saleor API behind Basic Auth, we can't just pass the credentials to the client. They would be easily accessible to anyone who inspects the code.
Instead, we will create a proxy API route that will know our GraphQL endpoint's credentials and address. As long as we don't expose the credentials to the client, we are sure that our proxy server is the only one that can access the Saleor API directly.
Here is what the proxy API route may look like:
// pages/api/saleor.js
export default async (req, res) => {
const username = process.env.SALEOR_API_USERNAME; // Take the Basic Auth username from an environment variable
const password = process.env.SALEOR_API_PASSWORD; // Take the Basic Auth password from an environment variable
const token = Buffer.from(`${username}:${password}`).toString("base64"); // Encode the credentials to Base64
const response = await fetch("https://your-store.saleor.cloud/graphql", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Basic ${token}`, // Using the Basic Auth header to authenticate the Saleor API
},
body: JSON.stringify({
query: `
// Read the query from the request body
`,
}),
});
res.status(200).json(data);
};
Step 4: Update the Next.js application to use the proxy
Our last step will be to update the client-side code to fetch products via the route we just implemented:
async function getProducts() {
// Using the proxy API route instead of the Saleor API directly
const response = await fetch("/api/saleor", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
// ...
});
// ...
}