|
| 1 | +# AuthKit Remix Library |
| 2 | + |
| 3 | +The AuthKit library for Next.js provides convenient helpers for authentication and session management using WorkOS & AuthKit with Next.js. |
| 4 | + |
| 5 | +## Installation |
| 6 | + |
| 7 | +Install the package with: |
| 8 | + |
| 9 | +``` |
| 10 | +npm i @workos-inc/authkit-nextjs |
| 11 | +``` |
| 12 | + |
| 13 | +or |
| 14 | + |
| 15 | +``` |
| 16 | +yarn add @workos-inc/authkit-nextjs |
| 17 | +``` |
| 18 | + |
| 19 | +## Pre-flight |
| 20 | + |
| 21 | +Make sure the following values are present in your `.env.local` environment variables file. The client ID and API key can be found in the [WorkOS dashboard](https://dashboard.workos.com), and the redirect URI can also be configured there. |
| 22 | + |
| 23 | +```sh |
| 24 | +WORKOS_CLIENT_ID="client_..." # retrieved from the WorkOS dashboard |
| 25 | +WORKOS_API_KEY="sk_test_..." # retrieved from the WorkOS dashboard |
| 26 | +WORKOS_REDIRECT_URI="http://localhost:3000/callback" # configured in the WorkOS dashboard |
| 27 | +WORKOS_COOKIE_PASSWORD="<your password>" # generate a secure password here |
| 28 | +``` |
| 29 | + |
| 30 | +`WORKOS_COOKIE_PASSWORD` is the private key used to encrypt the session cookie. It has to be at least 32 characters long. You can use the [1Password generator](https://1password.com/password-generator/) or the `openssl` library to generate a strong password via the command line: |
| 31 | + |
| 32 | +``` |
| 33 | +openssl rand -base64 24 |
| 34 | +``` |
| 35 | + |
| 36 | +To use the `signOut` method, you'll need to set your app's homepage in your WorkOS dashboard settings under "Redirects". |
| 37 | + |
| 38 | +### Optional configuration |
| 39 | + |
| 40 | +Certain environment variables are optional and can be used to debug or configure cookie settings. |
| 41 | + |
| 42 | +```sh |
| 43 | +WORKOS_COOKIE_MAX_AGE='600' # maximum age of the cookie in seconds. Defaults to 31 days |
| 44 | +WORKOS_API_HOSTNAME='api.workos.com' # base WorkOS API URL |
| 45 | +WORKOS_API_HTTPS=true # whether to use HTTPS in API calls |
| 46 | +WORKOS_API_PORT=3000 # port to use for API calls |
| 47 | +``` |
| 48 | + |
| 49 | +## Setup |
| 50 | + |
| 51 | +### Callback route |
| 52 | + |
| 53 | +WorkOS requires that you have a callback URL to redirect users back to after they've authenticated. In your Next.js app, [expose an API route](https://nextjs.org/docs/app/building-your-application/routing/route-handlers) and add the following. |
| 54 | + |
| 55 | +```ts |
| 56 | +import { handleAuth } from '@workos-inc/authkit-nextjs'; |
| 57 | + |
| 58 | +export const GET = handleAuth(); |
| 59 | +``` |
| 60 | + |
| 61 | +Make 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:3000/auth/callback` then you'd put the above code in `/app/auth/callback/route.ts`. |
| 62 | + |
| 63 | +You can also control the pathname the user will be sent to after signing-in by passing a `returnPathname` option to `handleAuth` like so: |
| 64 | + |
| 65 | +```ts |
| 66 | +export const GET = handleAuth({ returnPathname: '/dashboard' }); |
| 67 | +``` |
| 68 | + |
| 69 | +### Middleware |
| 70 | + |
| 71 | +This library relies on [Next.js middleware](https://nextjs.org/docs/app/building-your-application/routing/middleware) to provide session management for routes. Put the following in your `middleware.ts` file in the root of your project: |
| 72 | + |
| 73 | +```ts |
| 74 | +import { authkitMiddleware } from '@workos-inc/authkit-nextjs'; |
| 75 | + |
| 76 | +export default authkitMiddleware(); |
| 77 | + |
| 78 | +// Match against pages that require auth |
| 79 | +// Leave this out if you want auth on every resource (including images, css etc.) |
| 80 | +export const config = { matcher: ['/', '/admin'] }; |
| 81 | +``` |
| 82 | + |
| 83 | +## Usage |
| 84 | + |
| 85 | +### Get the current user |
| 86 | + |
| 87 | +For pages where you want to display a signed-in and signed-out view, use `getUser` to retrieve the user profile from WorkOS. |
| 88 | + |
| 89 | +```jsx |
| 90 | +import Link from 'next/link'; |
| 91 | +import { getSignInUrl, getSignUpUrl, getUser, signOut } from '@workos-inc/authkit-nextjs'; |
| 92 | + |
| 93 | +export default async function HomePage() { |
| 94 | + // Retrieves the user from the session or returns `null` if no user is signed in |
| 95 | + const { user } = await getUser(); |
| 96 | + |
| 97 | + if (!user) { |
| 98 | + // Get the URL to redirect the user to AuthKit to sign in |
| 99 | + const signInUrl = await getSignInUrl(); |
| 100 | + |
| 101 | + // Get the URL to redirect the user to AuthKit to sign up |
| 102 | + const signUpUrl = await getSignUpUrl(); |
| 103 | + |
| 104 | + return ( |
| 105 | + <> |
| 106 | + <Link href={signInUrl}>Log in</Link> |
| 107 | + <Link href={signUpUrl}>Sign Up</Link> |
| 108 | + </> |
| 109 | + ); |
| 110 | + } |
| 111 | + |
| 112 | + return ( |
| 113 | + <form |
| 114 | + action={async () => { |
| 115 | + 'use server'; |
| 116 | + await signOut(); |
| 117 | + }} |
| 118 | + > |
| 119 | + <p>Welcome back {user?.firstName && `, ${user?.firstName}`}</p> |
| 120 | + <button type="submit">Sign out</button> |
| 121 | + </form> |
| 122 | + ); |
| 123 | +} |
| 124 | +``` |
| 125 | +
|
| 126 | +### Requiring auth |
| 127 | +
|
| 128 | +For pages where a signed-in user is mandatory, you can use the `ensureSignedIn` option: |
| 129 | +
|
| 130 | +```jsx |
| 131 | +const { user } = await getUser({ ensureSignedIn: true }); |
| 132 | +``` |
| 133 | +
|
| 134 | +Enabling `ensureSignedIn` will redirect users to AuthKit if they attempt to access the page without being authenticated. |
| 135 | +
|
| 136 | +### Middleware auth |
| 137 | +
|
| 138 | +The default behavior of this library is to request authentication via the `getUser` method on a per-page basis. There are some use cases where you don't want to call `getUser` (e.g. you don't need user data for your page) or if you'd prefer a "secure by default" approach where every route defined in your middleware matcher is protected unless specified otherwise. In those cases you can opt-in to use middleware auth instead: |
| 139 | +
|
| 140 | +```ts |
| 141 | +import { authkitMiddleware } from '@workos-inc/authkit-nextjs'; |
| 142 | +
|
| 143 | +export default authkitMiddleware({ |
| 144 | + middlewareAuth: { |
| 145 | + enabled: true, |
| 146 | + unauthenticatedPaths: ['/', '/about'], |
| 147 | + }, |
| 148 | +}); |
| 149 | +
|
| 150 | +// Match against pages that require auth |
| 151 | +// Leave this out if you want auth on every resource (including images, css etc.) |
| 152 | +export const config = { matcher: ['/', '/admin/:path*', '/about'] }; |
| 153 | +``` |
| 154 | +
|
| 155 | +In the above example the `/admin` page will require a user to be signed in, whereas `/` and `/about` can be accessed without signing in. |
| 156 | +
|
| 157 | +`unauthenticatedPaths` uses the same glob logic as the [Next.js matcher](https://nextjs.org/docs/pages/building-your-application/routing/middleware#matcher). |
| 158 | +
|
| 159 | +### Signing out |
| 160 | +
|
| 161 | +Use the `signOut` method to sign out the current logged in user and redirect to your app's homepage. The homepage redirect is set in your WorkOS dashboard settings under "Redirect". |
| 162 | +
|
| 163 | +### Visualizing an impersonation |
| 164 | +
|
| 165 | +Render the `Impersonation` component in your app so that it is clear when someone is [impersonating a user](https://workos.com/docs/user-management/impersonation). |
| 166 | +The component will display a frame with some information about the impersonated user, as well as a button to stop impersonating. |
| 167 | +
|
| 168 | +```jsx |
| 169 | +import { Impersonation } from '@workos-inc/authkit-nextjs'; |
| 170 | +
|
| 171 | +export default function App() { |
| 172 | + return ( |
| 173 | + <div> |
| 174 | + <Impersonation /> |
| 175 | + {/* Your app content */} |
| 176 | + </div> |
| 177 | + ); |
| 178 | +} |
| 179 | +``` |
| 180 | +
|
| 181 | +### Get the access token |
| 182 | +
|
| 183 | +Sometimes it is useful to obtain the access token directly, for instance to make API requests to another service. |
| 184 | +
|
| 185 | +```jsx |
| 186 | +import { getUser } from '@workos-inc/authkit-nextjs'; |
| 187 | +
|
| 188 | +export default async function HomePage() { |
| 189 | + const { accessToken } = await getUser(); |
| 190 | +
|
| 191 | + if (!accessToken) { |
| 192 | + return <div>Not signed in</div>; |
| 193 | + } |
| 194 | +
|
| 195 | + const serviceData = await fetch('/api/path', { |
| 196 | + headers: { |
| 197 | + Authorization: `Bearer ${accessToken}`, |
| 198 | + }, |
| 199 | + }); |
| 200 | +
|
| 201 | + return <div>{serviceData}</div>; |
| 202 | +} |
| 203 | +``` |
| 204 | +
|
| 205 | +### Debugging |
| 206 | +
|
| 207 | +To enable debug logs, initialize the middleware with the debug flag enabled. |
| 208 | +
|
| 209 | +```js |
| 210 | +import { authkitMiddleware } from '@workos-inc/authkit-nextjs'; |
| 211 | +
|
| 212 | +export default authkitMiddleware({ debug: true }); |
| 213 | +``` |
| 214 | +
|
| 215 | +### Troubleshooting |
| 216 | +
|
| 217 | +#### NEXT_REDIRECT error when using try/catch blocks |
| 218 | +
|
| 219 | +Wrapping a `getUser({ ensureSignedIn: true })` call in a try/catch block will cause a `NEXT_REDIRECT` error. This is because `getUser` will attempt to redirect the user to AuthKit if no session is detected and redirects in Next must be [called outside a try/catch](https://nextjs.org/docs/app/building-your-application/data-fetching/server-actions-and-mutations#redirecting). |
0 commit comments