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",
]);
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>;
};