Skip to content

Commit a6198cf

Browse files
benoitgrelardcmathesonPaul Asjes
authored
Use new session management (#13)
* Hypothetical accessToken/refreshToken example * Real-life refresh example * Updated workos-node and cleaned code a bit * Fix missing import * Reorganized and added comments * Shape NextJS sdk API/usage * Implement feedback * Fix how we handle an error in the callback * Use new package * Use latest version * Use latest version * Update package.json --------- Co-authored-by: Cameron Matheson <[email protected]> Co-authored-by: Paul Asjes <[email protected]>
1 parent f7e6e5d commit a6198cf

File tree

10 files changed

+2636
-509
lines changed

10 files changed

+2636
-509
lines changed

.env.local.example

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
1-
# Available in your WorkOS dashboard
21
WORKOS_CLIENT_ID=
32
WORKOS_API_KEY=
43
WORKOS_REDIRECT_URI=http://localhost:3000/callback
4+
WORKOS_COOKIE_PASSWORD=
55

6-
# Your JWT secret key
7-
JWT_SECRET_KEY=

package-lock.json

Lines changed: 2608 additions & 304 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,16 @@
66
"dev": "next dev",
77
"build": "next build",
88
"start": "next start",
9-
"lint": "next lint"
9+
"reset": "rm -rf node_modules && rm -rf .next && npm i",
10+
"start-local-dev": "rm -rf .next && npm run prepare && npm run dev",
11+
"lint": "next lint",
12+
"prepare": "relative-deps"
1013
},
1114
"dependencies": {
1215
"@radix-ui/react-icons": "^1.3.0",
1316
"@radix-ui/themes": "^2.0.1",
14-
"@workos-inc/node": "^5.0.0",
15-
"jose": "^5.1.1",
16-
"next": "14.0.1",
17+
"@workos-inc/nextjs": "0.1.0",
18+
"next": "14.1.3",
1719
"react": "^18",
1820
"react-dom": "^18"
1921
},
@@ -23,6 +25,10 @@
2325
"@types/react-dom": "^18",
2426
"eslint": "^8",
2527
"eslint-config-next": "14.0.1",
28+
"relative-deps": "^1.0.7",
2629
"typescript": "^5"
30+
},
31+
"relativeDependencies": {
32+
2733
}
2834
}

src/app/account/page.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
import { getUser } from "../../auth";
1+
import { getUser } from "@workos-inc/nextjs";
22
import { Text, Heading, TextFieldInput, Flex, Box } from "@radix-ui/themes";
33

44
export default async function AccountPage() {
5-
const { user } = await getUser();
5+
const { user } = await getUser({ ensureSignedIn: true });
66

7-
const userFields = user && [
7+
const userFields = [
88
["First name", user.firstName],
99
["Last name", user.lastName],
1010
["Email", user.email],

src/app/callback/route.ts

Lines changed: 1 addition & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1 @@
1-
import { SignJWT } from "jose";
2-
import { NextRequest, NextResponse } from "next/server";
3-
import { getJwtSecretKey, workos, getClientId } from "../../auth";
4-
5-
export async function GET(request: NextRequest) {
6-
const code = request.nextUrl.searchParams.get("code");
7-
8-
if (code) {
9-
try {
10-
// Use the code returned to us by AuthKit and authenticate the user with WorkOS
11-
const { user } = await workos.userManagement.authenticateWithCode({
12-
clientId: getClientId(),
13-
code,
14-
});
15-
16-
// Create a JWT token with the user's information
17-
const token = await new SignJWT({
18-
// Here you might lookup and retrieve user details from your database
19-
user,
20-
})
21-
.setProtectedHeader({ alg: "HS256", typ: "JWT" })
22-
.setIssuedAt()
23-
.setExpirationTime("1h")
24-
.sign(getJwtSecretKey());
25-
26-
const url = request.nextUrl.clone();
27-
28-
// Cleanup params
29-
url.searchParams.delete("code");
30-
31-
// Redirect to the requested path and store the session
32-
url.pathname = "/";
33-
const response = NextResponse.redirect(url);
34-
35-
response.cookies.set({
36-
name: "token",
37-
value: token,
38-
path: "/",
39-
httpOnly: true,
40-
secure: true,
41-
sameSite: "lax",
42-
});
43-
44-
return response;
45-
} catch (error) {
46-
const errorRes = {
47-
error: error instanceof Error ? error.message : String(error),
48-
};
49-
console.error(errorRes);
50-
return NextResponse.redirect(new URL("/error", request.url));
51-
}
52-
}
53-
54-
return NextResponse.redirect(new URL("/error", request.url));
55-
}
1+
export { authkitCallbackRoute as GET } from "@workos-inc/nextjs";

src/app/components/sign-in-button.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
1-
import { clearCookie, getAuthorizationUrl, getUser } from "../../auth";
1+
import { getSignInUrl, getUser, signOut } from "@workos-inc/nextjs";
22
import { Button, Flex } from "@radix-ui/themes";
33

44
export async function SignInButton({ large }: { large?: boolean }) {
5-
const { isAuthenticated } = await getUser();
6-
const authorizationUrl = await getAuthorizationUrl();
5+
const { user } = await getUser();
6+
const authorizationUrl = await getSignInUrl();
77

8-
if (isAuthenticated) {
8+
if (user) {
99
return (
1010
<Flex gap="3">
1111
<form
1212
action={async () => {
1313
"use server";
14-
await clearCookie();
14+
await signOut();
1515
}}
1616
>
1717
<Button type="submit" size={large ? "3" : "2"}>

src/app/error/page.tsx

Lines changed: 0 additions & 32 deletions
This file was deleted.

src/app/page.tsx

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
1-
import { Button, Flex, Heading, Text } from "@radix-ui/themes";
21
import NextLink from "next/link";
2+
import { getUser } from "@workos-inc/nextjs";
3+
import { Button, Flex, Heading, Text } from "@radix-ui/themes";
34
import { SignInButton } from "./components/sign-in-button";
4-
import { getUser } from "../auth";
55

66
export default async function HomePage() {
7-
const { isAuthenticated, user } = await getUser();
8-
7+
const { user } = await getUser();
98
return (
109
<Flex direction="column" align="center" gap="2">
11-
{isAuthenticated ? (
10+
{user ? (
1211
<>
1312
<Heading size="8">
1413
Welcome back{user?.firstName && `, ${user?.firstName}`}

src/auth.ts

Lines changed: 0 additions & 76 deletions
This file was deleted.

src/middleware.ts

Lines changed: 4 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,6 @@
1-
import { NextRequest, NextResponse } from "next/server";
2-
import { getAuthorizationUrl, verifyJwtToken } from "./auth";
1+
import { authkitMiddleware } from "@workos-inc/nextjs";
32

4-
export async function middleware(request: NextRequest) {
5-
const { cookies } = request;
6-
const { value: token } = cookies.get("token") ?? { value: null };
3+
export default authkitMiddleware();
74

8-
const hasVerifiedToken = token && (await verifyJwtToken(token));
9-
10-
// Redirect unauthenticated users to the AuthKit flow
11-
if (!hasVerifiedToken) {
12-
const authorizationUrl = await getAuthorizationUrl();
13-
const response = NextResponse.redirect(authorizationUrl);
14-
15-
response.cookies.delete("token");
16-
17-
return response;
18-
}
19-
20-
return NextResponse.next();
21-
}
22-
23-
// Match against the account page
24-
export const config = { matcher: ["/account/:path*"] };
5+
// Match against the pages
6+
export const config = { matcher: ["/", "/account/:path*"] };

0 commit comments

Comments
 (0)