Skip to main content
To enforce RBAC permissions in your application, it is critical to both:
  • Gate various UI and actions in your application’s frontend
  • Confirm authentication and authorization on your backend before honoring requests from the client

Frontend authorization checks

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

Conditionally render UI based on permissions

It’s good practice to adapt UI based on permissions, even if your backend will enforce permissions on the server-side.
import { useStytchIsAuthorized } from '@stytch/react/b2b';

const DocumentActions = () => {
  // Use the useStytchIsAuthorized hook to check if the current Member is authorized to perform an action.
  const { isAuthorized: canReadDocument } = useStytchIsAuthorized('documents', 'read');
  const { isAuthorized: canWriteDocument } = useStytchIsAuthorized('documents', 'write');
  return (
    <div>
      { /* Disable a button if the Member is not authorized */ }
      <button disabled={!canReadDocument}>View Document</button>}
      { /* or just hide the button entirely */ }
      {canWriteDocument && <button>Edit Document</button>}
    </div>
  );
};

Check permissions before making API requests

You should also do pre-emptive client-side authorization checks to avoid any unnecessary API requests or ensure the user isn’t about to enter a flow they cannot complete.
const canReadDocument = await stytch.rbac.isAuthorized('documents', 'read');
if (!canReadDocument) {
  throw new Error('You do not have permission to read documents');
}
loadDocument();

Built-in Stytch Resource authorization

Stytch’s frontend SDKs offer built-in RBAC protections, allowing you to make requests directly from your public client without proxying through your backend. When you call methods like organization.update() or magicLinks.email.invite() directly from the client:
  1. The frontend SDK will automatically include the logged in member’s session in the request to the Stytch API.
  2. The Stytch API will only authorize the request if the session is valid and the Member has at least one Role that grants them permission to take that action.
To enable the SDK to make these requests, enable Member actions & organization modifications in the Stytch Dashboard.

Backend authorization checks

Regardless of if you are using Stytch’s frontend SDKs, you must always perform server-side authorization checks before proceeding with a request by authorizing a valid Session Token or .
If you are using Session Tokens, session authentication will trigger an outbound call to Stytch and authorization will be done on Stytch’s servers.For example to check authorization in a python backend:
resp = stytch_client.sessions.authenticate(
  session_token='mZAYn5aLEqKUlZ_Ad9U_fWr38GaAQ1oFAhT8ds245v7Q',
  authorization_check={
    'organization_id': 'organization-test-07971b06-ac8b-4cdb-9c15-63b17e653931',
    'resource_id': 'documents',
    'action': 'edit',
  }
)

if resp.status_code != 200: # The Member is not authenticated, redirect to login page
    return 'not authenticated', 401

if not resp.authorized: # The Member is authenticated, but does not have permission to edit the document
    return 'unauthorized', 403

# Member is authenticated and has permission to edit the document
save_document_edits()

Built-in Stytch Resource authorization

Any Stytch API endpoints and Backend SDK methods that act on a default Stytch Resource (e.g. stytch.self or stytch.organization) support passing the Member’s Session Token or Session JWT to have Stytch perform authentication and authorization prior to honoring the request. This allows the authentication and authorization checks to occur as close as possible to the action being taken, streamlining your handling. For example, if a Member makes a request to delete another Member from an Organization, you can pass their Session Token or JWT into the organizations.members.delete() call. Stytch will authenticate the session and perform an authorization check prior to honoring the call.
resp = stytch_client.organizations.members.delete(
  organization_id="organization-test-07971b06-ac8b-4cdb-9c15-63b17e653931",
    member_id="member-test-32fc5024-9c09-4da3-bd2e-c9ce4da9375f",
    method_options=DeleteRequestOptions( 
        authorization=Authorization(
            session_token="<session_token>",
        ),
    ),
)