> ## Documentation Index
> Fetch the complete documentation index at: https://stytch.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Enforcing permissions

> Enforce RBAC permissions in your application's frontend and backend.

export const userTip = "Represents an end user's account in your application.";

To enforce RBAC permissions in your application, it is critical to:

* Gate UI and <Tooltip tip={userTip}>User</Tooltip> actions in the frontend
* Confirm authentication and authorization on your backend before honoring requests

## Frontend authorization checks

Use Stytch's frontend SDKs to check permissions client-side.

<Columns cols={4}>
  <Card title="React SDK" icon="react" href="/api-reference/consumer/frontend-sdks/react/methods/rbac/is-authorized" arrow={true} />

  <Card title="Next.js SDK" icon="triangle" href="/api-reference/consumer/frontend-sdks/nextjs/methods/rbac/is-authorized" arrow={true} />

  <Card title="Vanilla JS SDK" icon="square-js" href="/api-reference/consumer/frontend-sdks/vanilla-js/methods/rbac/is-authorized" arrow={true} />

  <Card title="React Native" icon="react" href="/api-reference/consumer/mobile-sdks/react-native/methods/rbac/is-authorized" arrow={true} />
</Columns>

### Conditionally render UI based on permissions

Adapt UI based on permissions, even when your backend will enforce them.

<CodeGroup>
  ```jsx React icon="react" theme={null}
  import { useEffect, useState } from 'react';
  import { useStytch } from '@stytch/react';

  const DocumentActions = () => {
    const stytch = useStytch();
    const [canReadDocument, setCanReadDocument] = useState(false);
    const [canWriteDocument, setCanWriteDocument] = useState(false);

    useEffect(() => {
      const fetchPermissions = async () => {
        setCanReadDocument(await stytch.rbac.isAuthorized('documents', 'read'));
        setCanWriteDocument(await stytch.rbac.isAuthorized('documents', 'write'));
      };
      fetchPermissions();
    }, [stytch]);

    return (
      <div>
        <button disabled={!canReadDocument}>View Document</button>
        {canWriteDocument && <button>Edit Document</button>}
      </div>
    );
  };
  ```

  ```jsx Next.js icon="triangle" theme={null}
  import { useEffect, useState } from 'react';
  import { useStytch } from '@stytch/nextjs';

  const DocumentActions = () => {
    const stytch = useStytch();
    const [canReadDocument, setCanReadDocument] = useState(false);
    const [canWriteDocument, setCanWriteDocument] = useState(false);

    useEffect(() => {
      const fetchPermissions = async () => {
        setCanReadDocument(await stytch.rbac.isAuthorized('documents', 'read'));
        setCanWriteDocument(await stytch.rbac.isAuthorized('documents', 'write'));
      };
      fetchPermissions();
    }, [stytch]);

    return (
      <div>
        <button disabled={!canReadDocument}>View Document</button>
        {canWriteDocument && <button>Edit Document</button>}
      </div>
    );
  };
  ```

  ```js Vanilla JS icon="square-js" theme={null}
  import { StytchClient } from '@stytch/vanilla-js';

  const stytch = new StytchClient('PUBLIC_TOKEN');

  const canReadDocument = await stytch.rbac.isAuthorized('documents', 'read');
  const canWriteDocument = await stytch.rbac.isAuthorized('documents', 'write');
  ```
</CodeGroup>

### Check permissions before making API requests

Pre-emptive checks avoid unnecessary requests and prevent users from entering flows they cannot complete.

```js theme={null}
const canReadDocument = await stytch.rbac.isAuthorized('documents', 'read');
if (!canReadDocument) {
  throw new Error('You do not have permission to read documents');
}
loadDocument();
```

## Backend authorization checks

Always perform server-side authorization checks by authenticating a valid Session Token or Session JWT.

<Tabs>
  <Tab title="Session Tokens">
    If you use **Session Tokens**, call the [Authenticate Session endpoint](/api-reference/consumer/api/sessions/authenticate-session) with an authorization check.

    ```python theme={null}
    resp = stytch_client.sessions.authenticate(
      session_token='mZAYn5aLEqKUlZ_Ad9U_fWr38GaAQ1oFAhT8ds245v7Q',
      authorization_check={
        'resource_id': 'documents',
        'action': 'edit',
      }
    )

    if resp.status_code != 200:
        return 'not authenticated', 401

    if not resp.authorized:
        return 'unauthorized', 403
    ```
  </Tab>

  <Tab title="Session JWTs">
    You can also authorize using **Session JWTs**. The same endpoint accepts a `session_jwt` and returns a refreshed JWT if needed.

    ```python theme={null}
    resp = stytch_client.sessions.authenticate(
      session_jwt='eyJ...',
      authorization_check={
        'resource_id': 'documents',
        'action': 'edit',
      }
    )

    if resp.status_code != 200:
        return 'not authenticated', 401

    if not resp.authorized:
        return 'unauthorized', 403
    ```
  </Tab>
</Tabs>

## What's next

* [Create an RBAC policy](/consumer-auth/authorization/create-rbac-policy)
* [Assign roles to users](/consumer-auth/authorization/assigning-roles-to-users)
