{"id":28569872,"url":"https://github.com/workos/authkit-react-router","last_synced_at":"2026-03-09T10:01:32.223Z","repository":{"id":285817972,"uuid":"946221876","full_name":"workos/authkit-react-router","owner":"workos","description":"Authentication and session helpers for using WorkOS \u0026 AuthKit with React Router 7+","archived":false,"fork":false,"pushed_at":"2026-01-09T00:27:15.000Z","size":488,"stargazers_count":12,"open_issues_count":4,"forks_count":3,"subscribers_count":7,"default_branch":"main","last_synced_at":"2026-01-11T11:28:52.564Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/workos.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-03-10T20:00:07.000Z","updated_at":"2026-01-01T20:40:52.000Z","dependencies_parsed_at":"2025-05-05T16:22:04.590Z","dependency_job_id":"f30248ee-e1b0-49cf-b58e-b98aae1f9b4f","html_url":"https://github.com/workos/authkit-react-router","commit_stats":null,"previous_names":["workos/authkit-react-router"],"tags_count":15,"template":false,"template_full_name":null,"purl":"pkg:github/workos/authkit-react-router","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/workos%2Fauthkit-react-router","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/workos%2Fauthkit-react-router/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/workos%2Fauthkit-react-router/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/workos%2Fauthkit-react-router/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/workos","download_url":"https://codeload.github.com/workos/authkit-react-router/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/workos%2Fauthkit-react-router/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30290899,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-09T02:57:19.223Z","status":"ssl_error","status_checked_at":"2026-03-09T02:56:26.373Z","response_time":61,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-06-10T17:39:28.672Z","updated_at":"2026-03-09T10:01:32.215Z","avatar_url":"https://github.com/workos.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# AuthKit React Router Library\n\n\u003e [!IMPORTANT]\n\u003e This is an early-stage port of [authkit-remix](https://github.com/workos/authkit-remix) to support React Router. The features focus on framework mode (e.g. Remix), with more planned support for library mode and more features.\n\nThe AuthKit library for React Router 7+ provides convenient helpers for authentication and session management using WorkOS \u0026 AuthKit with React Router. You can find this library in action in the [react-router-authkit-example](https://github.com/workos/react-router-authkit-example) repo.\n\n## Installation\n\nInstall the package with:\n\n```\nnpm i @workos-inc/authkit-react-router\n```\n\nor\n\n```\nyarn add @workos-inc/authkit-react-router\n```\n\n## Configuration\n\nAuthKit for React Router offers a flexible configuration system that allows you to customize various settings. You can configure the library in three ways:\n\n### 1. Environment Variables\n\nThe simplest way is to set environment variables in your `.env.local` file:\n\n```bash\nWORKOS_CLIENT_ID=\"client_...\" # retrieved from the WorkOS dashboard\nWORKOS_API_KEY=\"sk_test_...\" # retrieved from the WorkOS dashboard\nWORKOS_REDIRECT_URI=\"http://localhost:5173/callback\" # configured in the WorkOS dashboard\nWORKOS_COOKIE_PASSWORD=\"\u003cyour password\u003e\" # generate a secure password here\n```\n\n### 2. Programmatic Configuration\n\nYou can also configure AuthKit programmatically by importing the `configure` function:\n\n```typescript\nimport { configure } from '@workos-inc/authkit-react-router';\n// In your root or entry file\nconfigure({\n  clientId: 'client_1234567890',\n  apiKey: 'sk_test_1234567890',\n  redirectUri: 'http://localhost:5173/callback',\n  cookiePassword: 'your-secure-cookie-password',\n  // Optional settings\n  cookieName: 'my-custom-cookie-name',\n  apiHttps: true,\n  cookieMaxAge: 60 * 60 * 24 * 30, // 30 days\n});\n```\n\n### 3. Custom Environment Source\n\nFor non-standard environments (like Deno or Edge functions), you can provide a custom environment variable source:\n\n\u003e [!Warning]\n\u003e\n\u003e While this library includes support for custom environment sources that could theoretically work in non-Node.js runtimes like Deno or Edge functions, this functionality has not been extensively tested (yet). If you're planning to use AuthKit in these environments, you may encounter unexpected issues. We welcome feedback and contributions from users who test in these environments.\n\n```typescript\nimport { configure } from '@workos-inc/authkit-react-router';\n\nconfigure((key) =\u003e Deno.env.get(key));\n// Or combine with explicit values\nconfigure({ clientId: 'client_1234567890' }, (key) =\u003e Deno.env.get(key));\n```\n\n### Configuration Priority\n\nWhen retrieving configuration values, AuthKit follows this priority order:\n\n1. Programmatically provided values via `configure()`\n2. Environment variables (prefixed with `WORKOS_`)\n3. Default values for optional settings\n\n### Available Configuration Options\n\n\u003e [!NOTE]\n\u003e\n\u003e To print out the entire config, a `getFullConfig` function is provided for debugging purposes.\n\n| Option           | Environment Variable     | Default               | Required | Description                                   |\n| ---------------- | ------------------------ | --------------------- | -------- | --------------------------------------------- |\n| `clientId`       | `WORKOS_CLIENT_ID`       | -                     | Yes      | Your WorkOS Client ID                         |\n| `apiKey`         | `WORKOS_API_KEY`         | -                     | Yes      | Your WorkOS API Key                           |\n| `redirectUri`    | `WORKOS_REDIRECT_URI`    | -                     | Yes      | The callback URL configured in WorkOS         |\n| `cookiePassword` | `WORKOS_COOKIE_PASSWORD` | -                     | Yes      | Password for cookie encryption (min 32 chars) |\n| `cookieName`     | `WORKOS_COOKIE_NAME`     | `wos-session`         | No       | Name of the session cookie                    |\n| `apiHttps`       | `WORKOS_API_HTTPS`       | `true`                | No       | Whether to use HTTPS for API calls            |\n| `cookieMaxAge`   | `WORKOS_COOKIE_MAX_AGE`  | `34560000` (400 days) | No       | Maximum age of cookie in seconds              |\n| `apiHostname`    | `WORKOS_API_HOSTNAME`    | `api.workos.com`      | No       | WorkOS API hostname                           |\n| `apiPort`        | `WORKOS_API_PORT`        | -                     | No       | Port to use for API calls                     |\n\n\u003e [!NOTE]\n\u003e\n\u003e The `cookiePassword` must be at least 32 characters long for security reasons.\n\n## Setup\n\n### Callback route\n\nAuthKit requires that you have a callback URL to redirect users back to after they've authenticated. In your React Router app, [create a new route](https://reactrouter.com/start/framework/routing) and add the following:\n\n```ts\nimport { authLoader } from '@workos-inc/authkit-react-router';\n\nexport const loader = authLoader();\n```\n\nMake sure this route matches the `WORKOS_REDIRECT_URI` variable and the configured redirect URI in your WorkOS dashboard. For instance if your redirect URI is `http://localhost:2884/callback` then you'd put the above code in `/app/routes/callback.ts`.\n\nYou can also control the pathname the user will be sent to after signing-in by passing a `returnPathname` option to `authLoader` like so:\n\n```ts\nexport const loader = authLoader({ returnPathname: '/dashboard' });\n```\n\nIf your application needs to persist `oauthTokens` or other auth-related information after the callback is successful, you can pass an `onSuccess` option:\n\n```ts\nexport const loader = authLoader({\n  onSuccess: async ({ oauthTokens }) =\u003e {\n    await saveToDatabase(oauthTokens);\n  },\n});\n```\n\n## Usage\n\n### Access authentication data in your React Router application\n\nUse `authkitLoader` to configure AuthKit for your React Router application routes.\n\n```tsx\nimport { type LoaderFunctionArgs, useLoaderData } from 'react-router';\nimport { authkitLoader } from '@workos-inc/authkit-react-router';\n\nexport const loader = (args: LoaderFunctionArgs) =\u003e authkitLoader(args);\n\nexport function App() {\n  // Retrieves the user from the session or returns `null` if no user is signed in\n  // Other supported values include `sessionId`, `organizationId`,\n  // `role`, `permissions`, `entitlements`, `featureFlags`, and `impersonator`.\n  const { user, signInUrl, signUpUrl } = useLoaderData\u003ctypeof loader\u003e();\n\n  return (\n    \u003cdiv\u003e\n      \u003cp\u003eWelcome back {user?.firstName \u0026\u0026 `, ${user?.firstName}`}\u003c/p\u003e\n    \u003c/div\u003e\n  );\n}\n```\n\nFor pages where you want to display a signed-in and signed-out view, use `authkitLoader` to retrieve the user profile from WorkOS. You can pass in additional data by providing a loader function directly to `authkitLoader`.\n\n```tsx\nimport { type ActionFunctionArgs, type LoaderFunctionArgs, data, Form, Link, useLoaderData } from 'react-router';\nimport { getSignInUrl, getSignUpUrl, signOut, authkitLoader } from '@workos-inc/authkit-react-router';\n\nexport const loader = (args: LoaderFunctionArgs) =\u003e\n  authkitLoader(args, async ({ request, auth }) =\u003e {\n    return data({\n      signInUrl: await getSignInUrl(),\n      signUpUrl: await getSignUpUrl(),\n    });\n  });\n\nexport async function action({ request }: ActionFunctionArgs) {\n  return await signOut(request);\n}\n\nexport default function HomePage() {\n  const { user, signInUrl, signUpUrl } = useLoaderData\u003ctypeof loader\u003e();\n\n  if (!user) {\n    return (\n      \u003c\u003e\n        \u003cLink to={signInUrl}\u003eLog in\u003c/Link\u003e\n        \u003cbr /\u003e\n        \u003cLink to={signUpUrl}\u003eSign Up\u003c/Link\u003e\n      \u003c/\u003e\n    );\n  }\n\n  return (\n    \u003cForm method=\"post\"\u003e\n      \u003cp\u003eWelcome back {user?.firstName \u0026\u0026 `, ${user?.firstName}`}\u003c/p\u003e\n      \u003cbutton type=\"submit\"\u003eSign out\u003c/button\u003e\n    \u003c/Form\u003e\n  );\n}\n```\n\n### Requiring auth\n\nFor pages where a signed-in user is mandatory, you can use the `ensureSignedIn` option:\n\n```tsx\nexport const loader = (args: LoaderFunctionArgs) =\u003e authkitLoader(args, { ensureSignedIn: true });\n```\n\nEnabling `ensureSignedIn` will redirect users to AuthKit if they attempt to access the page without being authenticated.\n\n### Signing out\n\nUse the `signOut` method to sign out the current logged in user, end the session, and redirect to your app's homepage. The homepage redirect is set in your WorkOS dashboard settings under \"Redirect\".\n\nIf you would like to specify where a user is redirected, an optional `returnTo` argument can be passed. Allowed values are configured in the WorkOS Dashboard under _[Logout redirects](https://workos.com/docs/user-management/sessions/configuring-sessions/logout-redirect)_.\n\n```ts\nexport async function action({ request }: ActionFunctionArgs) {\n  // Called when the form in SignInButton is submitted\n  return await signOut(request, { returnTo: 'https://example.com' });\n}\n```\n\n### Get the access token\n\nAccess tokens are available through the `getAccessToken()` function within your loader. This design encourages server-side token usage while making the security implications explicit.\n\n```tsx\nimport { data, type LoaderFunctionArgs } from 'react-router';\nimport { authkitLoader } from '@workos-inc/authkit-react-router';\n\nexport const loader = (args: LoaderFunctionArgs) =\u003e\n  authkitLoader(args, async ({ auth, getAccessToken }) =\u003e {\n    if (!auth.user) {\n      // Not signed in - getAccessToken() would return null\n      return data({ data: null });\n    }\n\n    // Explicitly call the function to get the access token\n    const accessToken = getAccessToken();\n\n    const serviceData = await fetch('/api/path', {\n      headers: {\n        Authorization: `Bearer ${accessToken}`,\n      },\n    });\n\n    return data({\n      data: await serviceData.json(),\n    });\n  });\n```\n\n#### Security Considerations\n\nBy default, access tokens are not included in the data sent to React components. This helps prevent unintentional token exposure in:\n\n- Browser developer tools\n- HTML source code\n- Client-side logs or error reporting\n\nIf you need to expose the access token to client-side code, you can explicitly return it from your loader:\n\n```tsx\nexport const loader = (args: LoaderFunctionArgs) =\u003e\n  authkitLoader(\n    args,\n    async ({ auth, getAccessToken }) =\u003e {\n      const accessToken = getAccessToken();\n\n      return {\n        // Only expose to client if absolutely necessary\n        accessToken,\n        userData: await fetchUserData(accessToken),\n      };\n    },\n    { ensureSignedIn: true },\n  );\n```\n\n**Note:** Only expose access tokens to the client when necessary for your use case (e.g., making direct API calls from the browser). Consider alternatives like:\n\n- Making API calls server-side in your loaders\n- Creating proxy endpoints in your application\n- Using separate client-specific tokens with limited scope\n\n#### Using with `ensureSignedIn`\n\nWhen using the `ensureSignedIn` option, you can be confident that `getAccessToken()` will always return a valid token:\n\n```tsx\nexport const loader = (args: LoaderFunctionArgs) =\u003e\n  authkitLoader(\n    args,\n    async ({ auth, getAccessToken }) =\u003e {\n      // With ensureSignedIn: true, the user is guaranteed to be authenticated\n      const accessToken = getAccessToken();\n\n      // Use the token for your API calls\n      const data = await fetchProtectedData(accessToken);\n\n      return { data };\n    },\n    { ensureSignedIn: true },\n  );\n```\n\n### Using withAuth for low-level access\n\nFor advanced use cases, the `withAuth` function provides direct access to authentication data, including the access token. Unlike `authkitLoader`, this function:\n\n- Does not handle automatic token refresh\n- Does not manage cookies or session updates\n- Returns the access token directly as a property\n- Requires manual redirect handling for unauthenticated users\n\n```tsx\nimport { withAuth } from '@workos-inc/authkit-react-router';\nimport { redirect, type LoaderFunctionArgs } from 'react-router';\n\nexport const loader = async (args: LoaderFunctionArgs) =\u003e {\n  const auth = await withAuth(args);\n\n  if (!auth.user) {\n    // Manual redirect - withAuth doesn't handle this automatically\n    throw redirect('/sign-in');\n  }\n\n  // Access token is directly available as a property\n  const { accessToken, user, sessionId } = auth;\n\n  // Use the token for server-side operations\n  const apiData = await fetch('https://api.example.com/data', {\n    headers: { Authorization: `Bearer ${accessToken}` },\n  });\n\n  // Be careful what you return - accessToken will be exposed if included\n  return {\n    user,\n    apiData: await apiData.json(),\n    // accessToken, // ⚠️ Only include if client-side access is necessary\n  };\n};\n```\n\n**When to use `withAuth` vs `authkitLoader`:**\n\n- Use `authkitLoader` for most cases - it handles token refresh, cookies, and provides safer defaults\n- Use `withAuth` when you need more control or are building custom authentication flows\n- `withAuth` is useful for API routes or middleware where you don't need the full loader functionality\n\n### Advanced: Direct access to the WorkOS client\n\nFor advanced use cases or functionality not covered by the helper methods, you can access the underlying WorkOS client directly:\n\n```ts\nimport { getWorkOS } from '@workos-inc/authkit-react-router';\n\n// Get the configured WorkOS client instance\nconst workos = getWorkOS();\n\n// Use any WorkOS SDK method\nconst organizations = await workos.organizations.listOrganizations({\n  limit: 10,\n});\n```\n\n### Advanced: Custom authentication flows\n\nWhile the standard authentication flow handles session management automatically, some use cases require manually creating and storing a session. This is useful for custom authentication flows like email verification or token exchange.\n\nFor these scenarios, you can use the `saveSession` function:\n\n```ts\nimport { redirect } from 'react-router';\nimport { getWorkOS, saveSession } from '@workos-inc/authkit-react-router';\n\n// Example: Email verification flow\nasync function handleEmailVerification(request: Request) {\n  const { code } = await request.json();\n\n  // Authenticate with the WorkOS API directly\n  const authResponse = await getWorkOS().userManagement.authenticateWithEmailVerification({\n    clientId: process.env.WORKOS_CLIENT_ID,\n    code,\n  });\n\n  // Save the session data to a cookie\n  await saveSession(\n    {\n      accessToken: authResponse.accessToken,\n      refreshToken: authResponse.refreshToken,\n      user: authResponse.user,\n      impersonator: authResponse.impersonator,\n    },\n    request,\n  );\n\n  return redirect('/dashboard');\n}\n```\n\n### Debugging\n\nTo enable debug logs, pass in the debug flag when using `authkitLoader`.\n\n```ts\nimport { authkitLoader } from '@workos-inc/authkit-react-router';\n\nexport const loader = (args: LoaderFunctionArgs) =\u003e authkitLoader(args, { debug: true });\n```\n\nIf providing a loader function, you can pass the options object as the third parameter\n\n```ts\nimport { authkitLoader } from '@workos-inc/authkit-react-router';\n\nexport const loader = (args: LoaderFunctionArgs) =\u003e\n  authkitLoader(\n    args,\n    async ({ auth }) =\u003e {\n      return json({ foo: 'bar' });\n    },\n    { debug: true },\n  );\n```\n\n## Customizing Session Storage\n\nBy default, AuthKit for React Router uses cookie-based session storage with these settings:\n\n```typescript\n{\n  name: \"wos-session\", // Default or WORKOS_COOKIE_NAME if set\n  path: \"/\",\n  httpOnly: true,\n  secure: true, // When redirect URI uses HTTPS\n  sameSite: \"lax\",\n  maxAge: 34560000, // 400 days (configurable via WORKOS_COOKIE_MAX_AGE)\n  secrets: [/* your cookie password, configurable via WORKOS_COOKIE_PASSWORD */],\n}\n```\n\n### Custom Session Storage\n\nYou can provide your own session storage implementation to both `authkitLoader` and `authLoader`:\n\n```typescript\nimport { createMemorySessionStorage } from '@react-router/node';\nimport { authkitLoader, authLoader } from '@workos-inc/authkit-react-router';\n\n// Create memory-based session storage\nconst memoryStorage = createMemorySessionStorage({\n  cookie: {\n    name: 'auth-session',\n    secrets: ['test-secret'],\n    sameSite: 'lax',\n    path: '/',\n    httpOnly: true,\n    secure: false, // Use false for testing\n    maxAge: 60 * 60 * 24, // 1 day\n  },\n});\n\n// In your root loader\nexport const loader = (args) =\u003e\n  authkitLoader(args, {\n    storage: memoryStorage,\n    cookie: { name: 'auth-session' },\n  });\n\n// In your callback route\nexport const loader = authLoader({\n  storage: memoryStorage,\n  cookie: { name: 'auth-session' },\n});\n```\n\nFor code reuse and consistency, consider using a shared function:\n\n```typescript\n// app/lib/session.ts\nexport function getAuthStorage() {\n  const storage = createCookieSessionStorage({\n    /* config */\n  });\n  return { storage, cookie: { name: 'my-custom-session' } };\n}\n\n// Then in your routes\nimport { getAuthStorage } from '~/lib/session';\nexport const loader = (args) =\u003e\n  authkitLoader(args, {\n    ...getAuthStorage(),\n    // Other options...\n  });\n```\n\n\u003e [!NOTE]\n\u003e When deploying to serverless environments like AWS Lambda, ensure you pass the same storage configuration to both your main routes and the callback route to handle cold starts properly.\n\nAuthKit works with any session storage that implements React Router's `SessionStorage` interface, including Redis-based or database-backed implementations.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fworkos%2Fauthkit-react-router","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fworkos%2Fauthkit-react-router","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fworkos%2Fauthkit-react-router/lists"}