---
title: AuthKit Integration
description: Use FGA with AuthKit for role-aware sessions and seamless authorization.
showNextPage: true
originalPath: .tmp-workos-clone/packages/docs/content/fga/authkit-integration.mdx
---

## Introduction

FGA integrates with [AuthKit](/authkit) to provide two layers of authorization. Organization-level roles and permissions are embedded directly in the session token for instant checks. Resource-scoped permissions are checked through the [Authorization API](/fga/access-checks).

---

## What's in the session token

When a user authenticates, their session token includes organization-level role information:

```json
{
  sub: "user_01HXYZ..."
  org_id: "org_01HXYZ..."
  role: "org_member"
  permissions: ["org:view", "workspace:view", "project:view"]
}
```

Your application can check these permissions directly from the token without making API calls.

### Why only organization-level roles?

Resource-scoped roles are intentionally excluded from the JWT:

- **Token size** – Users might have roles on hundreds of resources, bloating the JWT beyond practical limits
- **Freshness** – Resource assignments change frequently; stale tokens would cause mismatches
- **Performance** – Larger tokens mean slower requests and verification

For resource-level permissions, use the [Authorization API](/fga/access-checks)—it's fast and always current.

---

## FGA and organization memberships

FGA role assignments are scoped to organization memberships, not users directly. When you assign a role on a resource, the subject is the organization membership ID (`om_...`), which represents a user's relationship to a specific organization.

This means FGA access checks require the organization membership ID rather than the user ID. You can include this ID in your JWT using [JWT Templates](/authkit/jwt-templates):

```json
{
  "organization_membership_id": "{{ organization_membership.id }}"
}
```

This produces a token with the membership ID alongside the default claims:

```json
{
  "sub": "user_01HXYZ...",
  "org_id": "org_01HXYZ...",
  "role": "org_member",
  "permissions": ["org:view", "workspace:view"],
  ...
  "organization_membership_id": "om_01HXYZ..."
}
```

Your application can then extract the membership ID from the JWT and pass it to FGA access checks without needing an additional API call.

---

## Two layers of authorization

**Organization layer (JWT)** – Check the token directly for org-wide features like navigation and settings. Instant, no API call needed.

**Resource layer (API)** – Call the Authorization API for specific resource access. Checks the full permission hierarchy including inheritance.

```text
Can this user edit this project?

1. Quick check: Does the JWT include project:edit for all projects?
   → If yes, authorized (no API call)

2. Otherwise: Call the API for this specific project
   → Checks direct assignments and inheritance
```

---

## When roles change

**API checks** reflect changes immediately.

**JWT permissions** require a session refresh since the token was issued at sign-in. Resource roles aren't in the JWT, so API checks always return current data.
