Skip to main content

Protected API Handlers

The App SDK provides helpers which ensure that incoming requests are sent from the Saleor dashboard. An example of such a situation could be a change in the application configuration iframe.

Warning This handler works only for requests originating from front-end calls. It checks the JWT token from the client, which is available in AppBridge. Please do not call this endpoint from the backend context (calling it from API function will fail).

How to protect the endpoint

First, create a handler for your business logic. The only difference from the usual NextJS handler is an additional argument ctx of type ProtectedHandlerContext, which contains additional data related to the request:

export type ProtectedHandlerContext = {
baseUrl: string; // the URL your application is available
authData: AuthData; // Auth Data which can be used to communicate with the Saleor API
user: {
email: string;
userPermissions: string[];
};
};

createProtectedHandler will check if:

  • the request has saleor-api-url header of the Saleor instance
  • the API URL has been registered with the help of the APL
  • the request has an authorization-bearer
  • the auth token is a valid JWT token created by the Saleor running on the given URL
  • user has required permissions in the token

For example purposes, our endpoint will only log the welcome message:

import {
createProtectedHandler,
ProtectedHandlerContext,
} from "@saleor/app-sdk/handlers/next";
import { NextApiRequest, NextApiResponse } from "next";
import { saleorApp } from "../../../saleor-app";

export const handler = async (
req: NextApiRequest,
res: NextApiResponse,
ctx: ProtectedHandlerContext
) => {
console.log(`Greetings from ${ctx.authData.domain}`);
res.status(200);
};

/**
* If any of the requirements is failed, an error response will be returned.
* Otherwise, provided handler function fill be called.
*
* Last argument is optional array of permissions that will be checked. If user doesn't have them, will return 401 before handler is called
*/
export default createProtectedHandler(handler, saleorApp.apl, [
"MANAGE_ORDERS",
]);
Expand ▼

To make your requests successfully communicate with the backend, saleor-api-url and authorization-bearer headers are required:

fetch("/api/protected", {
headers: {
/**
* Both API URL and token are available in the appBridgeState. Based on those
* headers the backend will check if the request has enough permissions to
* perform the action.
*/
"saleor-api-url": saleorApiUrl,
"authorization-bearer": token,
},
});

If you want to read more about appBridgeState, check App Bridge documentation.

Using useAuthenticatedFetch() hook

Instead of manually attaching headers with AppBridge context, use the useAuthenticatedFetch() hook.

Since it requires AppBridge, it's only available in a browser context. It depends on the window object, so your app will break if Next.js tries to render it server-side. Hence, ensure the component that uses the hook is imported with dynamic().

The component must be within AppBridgeProvider to have access to the AppBridge.

import { useAuthenticatedFetch } from "@saleor/app-sdk/app-bridge";
import { useEffect } from "react";

export const ClientComponent = () => {
const fetch = useAuthenticatedFetch();

useEffect(() => {
/**
* Auth headers are set up automatically, so you can call the fetch function
*/
fetch("/api/protected");
}, [fetch]);

return <div>Your UI</div>;
};