2022-12-06 17:25:56 +00:00
# Protected API handlers
2023-02-20 09:50:33 +00:00
The App SDK provides helpers which ensure, that incoming requests are sent from Saleor dashboard.
Example of such situation could be a change of the application configuration iframe.
> **Warning**
> This handler only works for requests originated from frontend calls. It checks JWT token from the client, which is available
> in AppBridge. Do not call this endpoint from backend context (calling it from API function will fail)
2022-12-06 17:25:56 +00:00
## How to protect the endpoint
First, create handler for your business logic. The only difference from usual NextJS handler is an additional argument `ctx` of type `ProtectedHandlerContext` , which contains additional data related to the request:
```typescript
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
};
```
`createProtectedHandler` will check if:
2023-01-11 15:55:10 +00:00
- the request has `saleor-api-url` header of the Saleor instance
- the API URL has been registered, with help of the APL
2022-12-06 17:25:56 +00:00
- the request has `authorization-bearer`
2023-01-11 15:55:10 +00:00
- the auth token is a valid JWT token created by the Saleor running on the given URL
2023-03-14 11:31:11 +00:00
- user has required permissions in the token
2022-12-06 17:25:56 +00:00
For example purposes our endpoint will only log welcome message:
```typescript
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.
2023-03-14 11:31:11 +00:00
*
* Last argument is optional array of permissions that will be checked. If user doesn't have them, will return 401 before handler is called
2022-12-06 17:25:56 +00:00
*/
2023-03-14 11:31:11 +00:00
export default createProtectedHandler(handler, saleorApp.apl, ["MANAGE_ORDERS"]);
2022-12-06 17:25:56 +00:00
```
2023-01-11 15:55:10 +00:00
To make your requests successfully communicate with the backend, `saleor-api-url` and `authorization-bearer` headers are required:
2022-12-06 17:25:56 +00:00
```typescript
fetch("/api/protected", {
headers: {
/**
2023-01-11 15:55:10 +00:00
* Both API URL and token are available in the appBridgeState. Based on those
2022-12-06 17:25:56 +00:00
* headers the backend will check if the request has enough permissions to
* perform the action.
*/
2023-01-12 12:39:49 +00:00
"saleor-api-url": saleorApiUrl,
2022-12-06 17:25:56 +00:00
"authorization-bearer": token,
},
});
```
If you want to read more about `appBridgeState` , check [App Bridge ](./app-bridge.md ) documentation.
2023-03-14 11:31:11 +00:00
### Using `useAuthenticatedFetch()` hook
Instead of manually attaching headers with AppBridge context, you can use `useAuthenticatedFetch()` hook
Since it requires AppBridge, it's only available in browser context. It depends on `Window` object,
so your app will break if Next.js tries to render it server-side. Hence, ensure component that uses the hook is imported with dynamic()
Component must be within `AppBridgeProvider` to have access to the AppBridge
```tsx
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 just call the fetch function
*/
fetch("/api/protected");
}, [fetch]);
return < div > Your UI< / div > ;
};
```