From d171f75eefaa59a1613f760bc758d6e4ec2b97b3 Mon Sep 17 00:00:00 2001 From: Songkeys Date: Tue, 1 Oct 2024 02:39:42 +0800 Subject: [PATCH 1/2] feat: add fastify example --- apps/dev/fastify/.env.example | 7 + apps/dev/fastify/.gitignore | 21 +++ apps/dev/fastify/.prettierignore | 14 ++ apps/dev/fastify/README.md | 28 ++++ apps/dev/fastify/api/index.js | 3 + apps/dev/fastify/package.json | 34 +++++ apps/dev/fastify/public/css/style.css | 5 + apps/dev/fastify/src/app.ts | 81 +++++++++++ apps/dev/fastify/src/config/auth.config.ts | 69 +++++++++ apps/dev/fastify/src/errors.ts | 14 ++ .../fastify/src/middleware/auth.middleware.ts | 28 ++++ .../src/middleware/error.middleware.ts | 22 +++ apps/dev/fastify/src/server.ts | 18 +++ apps/dev/fastify/tsconfig.json | 16 +++ apps/dev/fastify/views/error.pug | 5 + apps/dev/fastify/views/index.pug | 11 ++ apps/dev/fastify/views/layout.pug | 34 +++++ apps/dev/fastify/views/protected.pug | 15 ++ apps/examples/fastify/package.json | 2 +- .../fastify/src/config/auth.config.ts | 123 ++++++++-------- docs/vercel.json | 2 +- package.json | 1 + packages/frameworks-fastify/src/index.ts | 29 ++-- pnpm-lock.yaml | 135 ++++++++++++++++++ 24 files changed, 637 insertions(+), 80 deletions(-) create mode 100644 apps/dev/fastify/.env.example create mode 100644 apps/dev/fastify/.gitignore create mode 100644 apps/dev/fastify/.prettierignore create mode 100644 apps/dev/fastify/README.md create mode 100644 apps/dev/fastify/api/index.js create mode 100644 apps/dev/fastify/package.json create mode 100644 apps/dev/fastify/public/css/style.css create mode 100644 apps/dev/fastify/src/app.ts create mode 100644 apps/dev/fastify/src/config/auth.config.ts create mode 100644 apps/dev/fastify/src/errors.ts create mode 100644 apps/dev/fastify/src/middleware/auth.middleware.ts create mode 100644 apps/dev/fastify/src/middleware/error.middleware.ts create mode 100644 apps/dev/fastify/src/server.ts create mode 100644 apps/dev/fastify/tsconfig.json create mode 100644 apps/dev/fastify/views/error.pug create mode 100644 apps/dev/fastify/views/index.pug create mode 100644 apps/dev/fastify/views/layout.pug create mode 100644 apps/dev/fastify/views/protected.pug diff --git a/apps/dev/fastify/.env.example b/apps/dev/fastify/.env.example new file mode 100644 index 0000000000..6959cc6e03 --- /dev/null +++ b/apps/dev/fastify/.env.example @@ -0,0 +1,7 @@ +AUTH_SECRET= + +AUTH_GITHUB_ID= +AUTH_GITHUB_SECRET= + +AUTH_GOOGLE_ID= +AUTH_GOOGLE_SECRET= \ No newline at end of file diff --git a/apps/dev/fastify/.gitignore b/apps/dev/fastify/.gitignore new file mode 100644 index 0000000000..01fd4ed6db --- /dev/null +++ b/apps/dev/fastify/.gitignore @@ -0,0 +1,21 @@ +# API keys and secrets +.env + +# Dependency directory +node_modules + +# Editors +.idea +*.iml +.vscode/settings.json + +# OS metadata +.DS_Store +Thumbs.db + +# Ignore built ts files +dist/**/* + +# Ignore built css files +/public/css/output.css + diff --git a/apps/dev/fastify/.prettierignore b/apps/dev/fastify/.prettierignore new file mode 100644 index 0000000000..f97e266fdd --- /dev/null +++ b/apps/dev/fastify/.prettierignore @@ -0,0 +1,14 @@ + +.DS_Store +node_modules +/dist +/.turbo +/package +.env +.env.* +!.env.example + +# Ignore files for PNPM, NPM and YARN +pnpm-lock.yaml +package-lock.json +yarn.lock diff --git a/apps/dev/fastify/README.md b/apps/dev/fastify/README.md new file mode 100644 index 0000000000..b8124cc9f9 --- /dev/null +++ b/apps/dev/fastify/README.md @@ -0,0 +1,28 @@ +> The example repository is maintained from a [monorepo](https://github.com/nextauthjs/next-auth/tree/main/apps/examples/fastify). Pull Requests should be opened against [`nextauthjs/next-auth`](https://github.com/nextauthjs/next-auth). + +

+
+ +

Auth.js Example App with Fastify

+

+ Open Source. Full Stack. Own Your Data. +

+

+ + npm + + + Bundle Size + + + Downloads + + + TypeScript + +

+

+ +# Documentation + +- [fastify.authjs.dev](https://fastify.authjs.dev) diff --git a/apps/dev/fastify/api/index.js b/apps/dev/fastify/api/index.js new file mode 100644 index 0000000000..37795e6772 --- /dev/null +++ b/apps/dev/fastify/api/index.js @@ -0,0 +1,3 @@ +import { app } from "../src/app.js" + +export default app diff --git a/apps/dev/fastify/package.json b/apps/dev/fastify/package.json new file mode 100644 index 0000000000..1c27aba00e --- /dev/null +++ b/apps/dev/fastify/package.json @@ -0,0 +1,34 @@ +{ + "name": "fastify-auth-app", + "description": "Fastify + Auth.js Developer app", + "type": "module", + "private": true, + "scripts": { + "start": "node dist/server.js", + "clean": "rm -rf dist", + "build": "pnpm build:ts && pnpm build:css", + "build:ts": "tsc", + "build:css": "tailwindcss -i ./public/css/style.css -o ./public/css/output.css", + "dev": "tsx watch --env-file=.env src/server.ts & pnpm build:css -w", + "debug": "tsx watch --inspect --env-file=.env src/server.ts & pnpm build:css -w", + "lint": "eslint src/*.ts --fix", + "prettier": "prettier src/*.ts --write" + }, + "author": "Songkeys (https://github.com/songkeys)", + "license": "MIT", + "dependencies": { + "@auth/fastify": "workspace:*", + "fastify": "^5.0.0", + "@fastify/view": "^10.0.1", + "@fastify/static": "^8.0.1", + "pug": "^3.0.2", + "tailwindcss": "^3.4.3" + }, + "devDependencies": { + "@prettier/plugin-pug": "^3.0.0", + "@types/morgan": "^1.9.9", + "@types/pug": "^2.0.10", + "tsx": "^4.7.3", + "typescript": "5.4.5" + } +} diff --git a/apps/dev/fastify/public/css/style.css b/apps/dev/fastify/public/css/style.css new file mode 100644 index 0000000000..7f393742af --- /dev/null +++ b/apps/dev/fastify/public/css/style.css @@ -0,0 +1,5 @@ +@tailwind base; + +@tailwind components; + +@tailwind utilities; diff --git a/apps/dev/fastify/src/app.ts b/apps/dev/fastify/src/app.ts new file mode 100644 index 0000000000..c46f53bdbe --- /dev/null +++ b/apps/dev/fastify/src/app.ts @@ -0,0 +1,81 @@ +import Fastify from "fastify" + +import * as path from "node:path" +import { + errorHandler, + errorNotFoundHandler, +} from "./middleware/error.middleware.js" +import { + authenticatedApi, + authenticatedPage, + currentSession, +} from "./middleware/auth.middleware.js" + +import { FastifyAuth } from "@auth/fastify" +import { authConfig } from "./config/auth.config.js" + +import * as pug from "pug" +import fastifyView from "@fastify/view" +import fastifyStatic from "@fastify/static" + +// Trust Proxy for Proxies (Heroku, Render.com, Docker behind Nginx, etc) +export const fastify = Fastify({ trustProxy: true, logger: true }) + +// Decorating the reply is not required but will optimise performance +// Only decorate the reply with a value type like null, as reference types like objects are shared among all requests, creating a security risk. +fastify.decorateReply("session", null) + +fastify.register(fastifyView, { + engine: { + pug, + }, + root: path.join(import.meta.dirname, "..", "views"), +}) + +// Serve static files +// NB: Uncomment this out if you want Fastify to serve static files for you vs. using a +// hosting provider which does so for you (for example through a CDN). +fastify.register(fastifyStatic, { + root: path.join(import.meta.dirname, "..", "public"), +}) + +// Set session in reply +fastify.addHook("preHandler", currentSession) + +// Set up FastifyAuth to handle authentication +// IMPORTANT: It is highly encouraged set up rate limiting on this route +fastify.register(FastifyAuth(authConfig), { prefix: "/api/auth" }) + +// Routes +fastify.get( + "/protected", + { preHandler: [authenticatedPage] }, + async (req, reply) => { + return reply.view("protected", { session: reply.session }) + } +) + +fastify.get( + "/api/protected", + { preHandler: [authenticatedApi] }, + async (req, reply) => { + return reply.send(reply.session) + } +) + +fastify.get("/", async (_req, reply) => { + return reply.view("index", { + title: "Fastify Auth Example", + user: reply.session?.user, + }) +}) + +fastify.get("/2", async (_req, reply) => { + return reply.view("index", { + title: "Fastify Auth Example", + user: reply.session?.user, + }) +}) + +fastify.setErrorHandler(errorHandler) +fastify.setNotFoundHandler(errorNotFoundHandler) diff --git a/apps/dev/fastify/src/config/auth.config.ts b/apps/dev/fastify/src/config/auth.config.ts new file mode 100644 index 0000000000..a85bb2d1f7 --- /dev/null +++ b/apps/dev/fastify/src/config/auth.config.ts @@ -0,0 +1,69 @@ +import Apple from "@auth/express/providers/apple" +import Auth0 from "@auth/express/providers/auth0" +import AzureB2C from "@auth/express/providers/azure-ad-b2c" +import BoxyHQSAML from "@auth/express/providers/boxyhq-saml" +import Cognito from "@auth/express/providers/cognito" +import Coinbase from "@auth/express/providers/coinbase" +import Discord from "@auth/express/providers/discord" +import Dropbox from "@auth/express/providers/dropbox" +import Facebook from "@auth/express/providers/facebook" +import GitHub from "@auth/express/providers/github" +import Gitlab from "@auth/express/providers/gitlab" +import Google from "@auth/express/providers/google" +import Hubspot from "@auth/express/providers/hubspot" +import Keycloak from "@auth/express/providers/keycloak" +import LinkedIn from "@auth/express/providers/linkedin" +import Netlify from "@auth/express/providers/netlify" +import Okta from "@auth/express/providers/okta" +import Passage from "@auth/express/providers/passage" +import Pinterest from "@auth/express/providers/pinterest" +import Reddit from "@auth/express/providers/reddit" +import Slack from "@auth/express/providers/slack" +import Spotify from "@auth/express/providers/spotify" +import Twitch from "@auth/express/providers/twitch" +import Twitter from "@auth/express/providers/twitter" +import WorkOS from "@auth/express/providers/workos" +import Zoom from "@auth/express/providers/zoom" + +export const authConfig = { + trustHost: true, + debug: process.env.NODE_ENV !== "production" ? true : false, + providers: [ + Apple, + Auth0, + AzureB2C({ + clientId: process.env.AUTH_AZURE_AD_B2C_ID, + clientSecret: process.env.AUTH_AZURE_AD_B2C_SECRET, + issuer: process.env.AUTH_AZURE_AD_B2C_ISSUER, + }), + BoxyHQSAML({ + clientId: "dummy", + clientSecret: "dummy", + issuer: process.env.AUTH_BOXYHQ_SAML_ISSUER, + }), + Cognito, + Coinbase, + Discord, + Dropbox, + Facebook, + GitHub, + Gitlab, + Google, + Hubspot, + Keycloak, + LinkedIn, + Netlify, + Okta, + Passage, + Pinterest, + Reddit, + Slack, + Spotify, + Twitch, + Twitter, + WorkOS({ + connection: process.env.AUTH_WORKOS_CONNECTION!, + }), + Zoom, + ], +} diff --git a/apps/dev/fastify/src/errors.ts b/apps/dev/fastify/src/errors.ts new file mode 100644 index 0000000000..43853cfe84 --- /dev/null +++ b/apps/dev/fastify/src/errors.ts @@ -0,0 +1,14 @@ +export class HttpError extends Error { + status: number + constructor(status: number, message: string) { + super(message) + this.status = status + } +} + +export class NotFoundError extends HttpError { + constructor(message: string, status = 404) { + super(status, message) + this.name = "NotFoundError" + } +} diff --git a/apps/dev/fastify/src/middleware/auth.middleware.ts b/apps/dev/fastify/src/middleware/auth.middleware.ts new file mode 100644 index 0000000000..498cf82012 --- /dev/null +++ b/apps/dev/fastify/src/middleware/auth.middleware.ts @@ -0,0 +1,28 @@ +//// @ts-nocheck +import { getSession } from "@auth/fastify" +import { authConfig } from "../config/auth.config.js" +import { FastifyReply, FastifyRequest } from "fastify" + +export async function authenticatedApi( + req: FastifyRequest, + reply: FastifyReply +) { + reply.session ??= (await getSession(req, authConfig)) ?? null + if (!reply.session) { + reply.status(401).send({ message: "Not Authenticated" }) + } +} + +export async function authenticatedPage( + req: FastifyRequest, + reply: FastifyReply +) { + reply.session ??= (await getSession(req, authConfig)) ?? null + if (!reply.session) { + return reply.view("unauthenticated") + } +} + +export async function currentSession(req: FastifyRequest, reply: FastifyReply) { + reply.session = (await getSession(req, authConfig)) ?? null +} diff --git a/apps/dev/fastify/src/middleware/error.middleware.ts b/apps/dev/fastify/src/middleware/error.middleware.ts new file mode 100644 index 0000000000..701e77ffd2 --- /dev/null +++ b/apps/dev/fastify/src/middleware/error.middleware.ts @@ -0,0 +1,22 @@ +//// @ts-nocheck +import { HttpError, NotFoundError } from "../errors.js" +import { FastifyReply, FastifyRequest } from "fastify" + +export const errorHandler = ( + err: HttpError | Error, + _req: FastifyRequest, + _reply: FastifyReply +): void => { + const statusCode = (err instanceof HttpError && err.status) || 500 + _reply.status(statusCode).view("error", { + title: err instanceof HttpError ? err.status : err.name, + message: err.message, + }) +} + +export const errorNotFoundHandler = ( + _req: FastifyRequest, + _reply: FastifyReply +): void => { + new NotFoundError("Not Found") +} diff --git a/apps/dev/fastify/src/server.ts b/apps/dev/fastify/src/server.ts new file mode 100644 index 0000000000..1e0a75062c --- /dev/null +++ b/apps/dev/fastify/src/server.ts @@ -0,0 +1,18 @@ +const { fastify } = await import("./app.js") + +// const address = fastify.server.address() +// const port = (typeof address === "object" && address?.port) || 3000 + +const port = Number(process.env.PORT) || 3000 + +const start = async () => { + try { + await fastify.listen({ port }) + fastify.log.info(`server listening on ${fastify.server.address()}`) + } catch (err) { + fastify.log.error(err) + process.exit(1) + } +} + +start() diff --git a/apps/dev/fastify/tsconfig.json b/apps/dev/fastify/tsconfig.json new file mode 100644 index 0000000000..6b8858be5f --- /dev/null +++ b/apps/dev/fastify/tsconfig.json @@ -0,0 +1,16 @@ +{ + "compilerOptions": { + "module": "NodeNext", + "esModuleInterop": true, + "target": "esnext", + "noImplicitAny": true, + "moduleResolution": "NodeNext", + "sourceMap": true, + "outDir": "dist", + "baseUrl": ".", + "skipLibCheck": true, + "strict": true + }, + "include": ["src/**/*.ts"], + "exclude": ["node_modules"] +} diff --git a/apps/dev/fastify/views/error.pug b/apps/dev/fastify/views/error.pug new file mode 100644 index 0000000000..4d62885b53 --- /dev/null +++ b/apps/dev/fastify/views/error.pug @@ -0,0 +1,5 @@ +extends layout + +block content + h1=title + p=message diff --git a/apps/dev/fastify/views/index.pug b/apps/dev/fastify/views/index.pug new file mode 100644 index 0000000000..46708a98ee --- /dev/null +++ b/apps/dev/fastify/views/index.pug @@ -0,0 +1,11 @@ +extends layout + +block content + h1=title + p + | This is an example site to demonstrate how to use #{ ' ' } + a(href="https://expressjs.com/") Express + | #{ ' ' } with #{ ' ' } + a(href="https://authjs.dev/reference/express") Express Auth + | + | for authentication. diff --git a/apps/dev/fastify/views/layout.pug b/apps/dev/fastify/views/layout.pug new file mode 100644 index 0000000000..ed1bf74915 --- /dev/null +++ b/apps/dev/fastify/views/layout.pug @@ -0,0 +1,34 @@ +doctype html +html + head + title=title + meta(name="viewport" content="width=device-width, initial-scale=1.0") + body + div + div + if session + div + if session.user.image + img(src=`${session.user.image}` style="width:64px;border-radius:50%;") + span + | Signed in as #{ ' ' } + strong= session.user.email || session.user.name + a( + href="/api/auth/signout" + ) Sign out + else + span You are not signed in #{ ' ' } + a#sign-indiv( + href="/api/auth/signin" + ) Sign in + + nav + ul + li + a(href="/") Home + li + a(href="/protected") Protected + li + a(href="/api/protected") Protected (API) + + block content diff --git a/apps/dev/fastify/views/protected.pug b/apps/dev/fastify/views/protected.pug new file mode 100644 index 0000000000..97790e3b32 --- /dev/null +++ b/apps/dev/fastify/views/protected.pug @@ -0,0 +1,15 @@ +extends layout + +block content + if session + h1 Protected page + p + | This is a protected content. You can access this content because you are + | signed in. + p Session expiry: #{ session.expires ? session.expires : '' } + else + h1 Access Denied + p + | You must be #{ ' ' } + a(href="/api/auth/signin") signed in + | #{ ' ' } to view this page diff --git a/apps/examples/fastify/package.json b/apps/examples/fastify/package.json index 7195a07718..905e542a7f 100644 --- a/apps/examples/fastify/package.json +++ b/apps/examples/fastify/package.json @@ -32,4 +32,4 @@ "tsx": "^4.7.0", "typescript": "5.3.3" } -} \ No newline at end of file +} diff --git a/apps/examples/fastify/src/config/auth.config.ts b/apps/examples/fastify/src/config/auth.config.ts index db4708f04c..a85bb2d1f7 100644 --- a/apps/examples/fastify/src/config/auth.config.ts +++ b/apps/examples/fastify/src/config/auth.config.ts @@ -1,68 +1,69 @@ -import Apple from "@auth/fastify/providers/apple" -import Auth0 from "@auth/fastify/providers/auth0" -import AzureB2C from "@auth/fastify/providers/azure-ad-b2c" -import BoxyHQSAML from "@auth/fastify/providers/boxyhq-saml" -import Cognito from "@auth/fastify/providers/cognito" -import Coinbase from "@auth/fastify/providers/coinbase" -import Discord from "@auth/fastify/providers/discord" -import Dropbox from "@auth/fastify/providers/dropbox" -import Facebook from "@auth/fastify/providers/facebook" -import GitHub from "@auth/fastify/providers/github" -import GitLab from "@auth/fastify/providers/gitlab" -import Google from "@auth/fastify/providers/google" -import Hubspot from "@auth/fastify/providers/hubspot" -import Keycloak from "@auth/fastify/providers/keycloak" -import LinkedIn from "@auth/fastify/providers/linkedin" -import Netlify from "@auth/fastify/providers/netlify" -import Okta from "@auth/fastify/providers/okta" -import Passage from "@auth/fastify/providers/passage" -import Pinterest from "@auth/fastify/providers/pinterest" -import Reddit from "@auth/fastify/providers/reddit" -import Slack from "@auth/fastify/providers/slack" -import Spotify from "@auth/fastify/providers/spotify" -import Twitch from "@auth/fastify/providers/twitch" -import Twitter from "@auth/fastify/providers/twitter" -import WorkOS from "@auth/fastify/providers/workos" -import Zoom from "@auth/fastify/providers/zoom" +import Apple from "@auth/express/providers/apple" +import Auth0 from "@auth/express/providers/auth0" +import AzureB2C from "@auth/express/providers/azure-ad-b2c" +import BoxyHQSAML from "@auth/express/providers/boxyhq-saml" +import Cognito from "@auth/express/providers/cognito" +import Coinbase from "@auth/express/providers/coinbase" +import Discord from "@auth/express/providers/discord" +import Dropbox from "@auth/express/providers/dropbox" +import Facebook from "@auth/express/providers/facebook" +import GitHub from "@auth/express/providers/github" +import Gitlab from "@auth/express/providers/gitlab" +import Google from "@auth/express/providers/google" +import Hubspot from "@auth/express/providers/hubspot" +import Keycloak from "@auth/express/providers/keycloak" +import LinkedIn from "@auth/express/providers/linkedin" +import Netlify from "@auth/express/providers/netlify" +import Okta from "@auth/express/providers/okta" +import Passage from "@auth/express/providers/passage" +import Pinterest from "@auth/express/providers/pinterest" +import Reddit from "@auth/express/providers/reddit" +import Slack from "@auth/express/providers/slack" +import Spotify from "@auth/express/providers/spotify" +import Twitch from "@auth/express/providers/twitch" +import Twitter from "@auth/express/providers/twitter" +import WorkOS from "@auth/express/providers/workos" +import Zoom from "@auth/express/providers/zoom" export const authConfig = { trustHost: true, + debug: process.env.NODE_ENV !== "production" ? true : false, providers: [ - // Apple, - // Auth0, - // AzureB2C({ - // clientId: process.env.AUTH_AZURE_AD_B2C_ID, - // clientSecret: process.env.AUTH_AZURE_AD_B2C_SECRET, - // issuer: process.env.AUTH_AZURE_AD_B2C_ISSUER, - // }), - // BoxyHQSAML({ - // clientId: "dummy", - // clientSecret: "dummy", - // issuer: process.env.AUTH_BOXYHQ_SAML_ISSUER, - // }), - // Cognito, - // Coinbase, - // Discord, - // Dropbox, - // Facebook, - // GitHub, - // GitLab, + Apple, + Auth0, + AzureB2C({ + clientId: process.env.AUTH_AZURE_AD_B2C_ID, + clientSecret: process.env.AUTH_AZURE_AD_B2C_SECRET, + issuer: process.env.AUTH_AZURE_AD_B2C_ISSUER, + }), + BoxyHQSAML({ + clientId: "dummy", + clientSecret: "dummy", + issuer: process.env.AUTH_BOXYHQ_SAML_ISSUER, + }), + Cognito, + Coinbase, + Discord, + Dropbox, + Facebook, + GitHub, + Gitlab, Google, - // Hubspot, - // Keycloak, - // LinkedIn, - // Netlify, - // Okta, - // Passage, - // Pinterest, - // Reddit, - // Slack, - // Spotify, - // Twitch, - // Twitter, - // WorkOS({ - // connection: process.env.AUTH_WORKOS_CONNECTION!, - // }), - // Zoom, + Hubspot, + Keycloak, + LinkedIn, + Netlify, + Okta, + Passage, + Pinterest, + Reddit, + Slack, + Spotify, + Twitch, + Twitter, + WorkOS({ + connection: process.env.AUTH_WORKOS_CONNECTION!, + }), + Zoom, ], } diff --git a/docs/vercel.json b/docs/vercel.json index 8097bc349c..76fd1c16dd 100644 --- a/docs/vercel.json +++ b/docs/vercel.json @@ -30,4 +30,4 @@ "schedule": "42 */2 * * *" } ] -} \ No newline at end of file +} diff --git a/package.json b/package.json index 4a1cebe2c3..768801c0c8 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ "dev:sveltekit": "turbo run dev --parallel --continue --filter=sveltekit-auth-app...", "dev:express": "turbo run dev --parallel --continue --filter=express-auth-app...", "dev:qwik": "turbo run dev --parallel --continue --filter=qwik-auth-app...", + "dev:fastify": "turbo run dev --parallel --continue --filter=fastify-auth-app...", "dev:docs": "turbo run dev --filter=docs", "email": "fake-smtp-server", "lint": "eslint --cache .", diff --git a/packages/frameworks-fastify/src/index.ts b/packages/frameworks-fastify/src/index.ts index 74cba331d9..bb504718cf 100644 --- a/packages/frameworks-fastify/src/index.ts +++ b/packages/frameworks-fastify/src/index.ts @@ -45,7 +45,7 @@ * * ```ts title="app.ts" * import { getSession } from "@auth/fastify" - * + * * // Decorating the reply is not required but will optimise performance * // Only decorate the reply with a value type like null, as reference types like objects are shared among all requests, creating a security risk. * fastify.decorateReply('session', null) @@ -62,18 +62,7 @@ * reply.view("index.pug", { user: session?.user }) * }) * ``` - * - * Note for TypeScript, you may want to augment the Fastify types to include the `session` property on the reply object. This can be done by creating a @types/fastify/index.d.ts file: - * - * ```ts title="@types/fastify/index.d.ts" - * import { Session } from "@auth/core/types"; - * declare module "fastify" { - * interface FastifyReply { - * session: Session | null; - * } - * } - * ``` - * + * * You may need to add `"typeRoots": ["@types"]` to `compilerOptions` in your tsconfig.json. * * ## Authorization @@ -99,13 +88,13 @@ * const session = reply.session; * reply.view("profile.pug", { user: session?.user }) * }); - * + * * // This route is not protected * fastify.get("/", (req, reply) => { * reply.view("index"); * }); * ``` - * + * * ### Per Group of Routes * To protect a group of routes, create a plugin and register the authenication hook and routes to the instance as follows: * @@ -114,11 +103,11 @@ * async (instance) => { * // All routes on this instance will be protected because of the preHandler hook * instance.addHook("preHandler", authenticatedUser) - * + * * instance.get("/", (req, reply) => { * reply.view("protected.pug") * }) - * + * * instance.get("/me", (req, reply) => { * reply.send(reply.session?.user) * }) @@ -141,6 +130,12 @@ import type { FastifyRequest, FastifyPluginAsync } from "fastify" import formbody from "@fastify/formbody" import { toWebRequest, toFastifyReply } from "./lib/index.js" +declare module "fastify" { + interface FastifyReply { + session: Session | null + } +} + export type FastifyAuthConfig = Omit export type { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f1d33a6fe8..574974430b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -141,6 +141,43 @@ importers: specifier: 5.4.5 version: 5.4.5 + apps/dev/fastify: + dependencies: + '@auth/fastify': + specifier: workspace:* + version: link:../../../packages/frameworks-fastify + '@fastify/static': + specifier: ^8.0.1 + version: 8.0.1 + '@fastify/view': + specifier: ^10.0.1 + version: 10.0.1 + fastify: + specifier: ^5.0.0 + version: 5.0.0 + pug: + specifier: ^3.0.2 + version: 3.0.2 + tailwindcss: + specifier: ^3.4.3 + version: 3.4.3(ts-node@10.9.2(@types/node@20.12.7)(typescript@5.4.5)) + devDependencies: + '@prettier/plugin-pug': + specifier: ^3.0.0 + version: 3.0.0(prettier@3.3.3) + '@types/morgan': + specifier: ^1.9.9 + version: 1.9.9 + '@types/pug': + specifier: ^2.0.10 + version: 2.0.10 + tsx: + specifier: ^4.7.3 + version: 4.7.3 + typescript: + specifier: 5.4.5 + version: 5.4.5 + apps/dev/nextjs: dependencies: next: @@ -2751,6 +2788,9 @@ packages: resolution: {integrity: sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@fastify/accept-negotiator@2.0.0': + resolution: {integrity: sha512-/Sce/kBzuTxIq5tJh85nVNOq9wKD8s+viIgX0fFMDBdw95gnpf53qmF1oBgJym3cPFliWUuSloVg/1w/rH0FcQ==} + '@fastify/ajv-compiler@4.0.1': resolution: {integrity: sha512-DxrBdgsjNLP0YM6W5Hd6/Fmj43S8zMKiFJYgi+Ri3htTGAowPVG/tG1wpnWLMjufEnehRivUCKZ1pLDIoZdTuw==} @@ -2774,6 +2814,15 @@ packages: '@fastify/merge-json-schemas@0.1.1': resolution: {integrity: sha512-fERDVz7topgNjtXsJTTW1JKLy0rhuLRcquYqNR9rF7OcVpCa2OVW49ZPDIhaRRCaUuvVxI+N416xUoF76HNSXA==} + '@fastify/send@3.1.1': + resolution: {integrity: sha512-LdiV2mle/2tH8vh6GwGl0ubfUAgvY+9yF9oGI1iiwVyNUVOQamvw5n+OFu6iCNNoyuCY80FFURBn4TZCbTe8LA==} + + '@fastify/static@8.0.1': + resolution: {integrity: sha512-7idyhbcgf14v4bjWzUeHEFvnVxvNJ1n5cyGPgFtwTZjnjUQ1wgC7a2FQai7OGKqCKywDEjzbPhAZRW+uEK1LMg==} + + '@fastify/view@10.0.1': + resolution: {integrity: sha512-rXtBN0oVDmoRZAS7lelrCIahf+qFtlMOOas8VPdA7JvrJ9ChcF7e36pIUPU0Vbs3KmHxESUb7XatavUZEe/k5Q==} + '@firebase/app-check-interop-types@0.3.2': resolution: {integrity: sha512-LMs47Vinv2HBMZi49C09dJxp0QT5LwDzFaVGf/+ITHe3BlIhUiLNttkATSXplc89A2lAaeTqjgqVkiRfUGyQiQ==} @@ -3521,6 +3570,10 @@ packages: cpu: [x64] os: [win32] + '@lukeed/ms@2.0.2': + resolution: {integrity: sha512-9I2Zn6+NJLfaGoz9jN3lpwDgAYvfGeNYdbAIjJOqzs4Tpc+VU3Jqq4IofSUBKajiDS8k9fZIg18/z13mpk1bsA==} + engines: {node: '>=8'} + '@manypkg/find-root@1.1.0': resolution: {integrity: sha512-mki5uBvhHzO8kYYix/WRy2WX8S3B5wdVSc9D6KcU5lQNglP2yt58/VfLuAK49glRXChosY8ap2oJ1qgma3GUVA==} @@ -8334,6 +8387,11 @@ packages: engines: {node: '>=16 || 14 >=14.17'} hasBin: true + glob@11.0.0: + resolution: {integrity: sha512-9UiX/Bl6J2yaBbxKoEBRm4Cipxgok8kQYcOPEhScPwebu2I0HoQOuYdIO6S3hLuWoZgpDpwQZMzTFxgpkyT76g==} + engines: {node: 20 || >=22} + hasBin: true + glob@7.2.3: resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} deprecated: Glob versions prior to v9 are no longer supported @@ -9084,6 +9142,10 @@ packages: resolution: {integrity: sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==} engines: {node: '>=14'} + jackspeak@4.0.2: + resolution: {integrity: sha512-bZsjR/iRjl1Nk1UkjGpAzLNfQtzuijhn2g+pbZb98HQ1Gk8vM9hfbxeMBP+M2/UUdwj0RqGG3mlvk2MsAqwvEw==} + engines: {node: 20 || >=22} + jake@10.8.7: resolution: {integrity: sha512-ZDi3aP+fG/LchyBzUM804VjddnwfSfsdeYkwt8NcbKRvo4rFkjhs456iLFn3k2ZUWvNe4i48WACDbza8fhq2+w==} engines: {node: '>=10'} @@ -9582,6 +9644,10 @@ packages: resolution: {integrity: sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==} engines: {node: 14 || >=16.14} + lru-cache@11.0.1: + resolution: {integrity: sha512-CgeuL5uom6j/ZVrg7G/+1IXqRY8JXX4Hghfy5YE0EhoYQWvndP1kufu58cmZLNIDKnRhZrXfdS9urVWx98AipQ==} + engines: {node: 20 || >=22} + lru-cache@4.0.2: resolution: {integrity: sha512-uQw9OqphAGiZhkuPlpFGmdTU2tEuhxTourM/19qGJrxBPHAr/f8BT1a0i/lOclESnGatdJG/UCkP9kZB/Lh1iw==} @@ -10019,6 +10085,10 @@ packages: resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} engines: {node: '>=4'} + minimatch@10.0.1: + resolution: {integrity: sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==} + engines: {node: 20 || >=22} + minimatch@3.0.8: resolution: {integrity: sha512-6FsRAQsxQ61mw+qP1ZzbL9Bc78x2p5OqNgNpnoAFLTrX8n5Kxph0CsnhmKKNXTWjXqU5L0pGPR7hYk+XWZr60Q==} @@ -10088,6 +10158,10 @@ packages: resolution: {integrity: sha512-UZ7eQ+h8ywIRAW1hIEl2AqdwzJucU/Kp59+8kkZeSvafXhZjul247BvIJjEVFVeON6d7lM46XX1HXCduKAS8VA==} engines: {node: '>=16 || 14 >=14.17'} + minipass@7.1.2: + resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} + engines: {node: '>=16 || 14 >=14.17'} + minizlib@2.1.2: resolution: {integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==} engines: {node: '>= 8'} @@ -10658,6 +10732,9 @@ packages: resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} engines: {node: '>=6'} + package-json-from-dist@1.0.1: + resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} + package-manager-detector@0.2.0: resolution: {integrity: sha512-E385OSk9qDcXhcM9LNSe4sdhx8a9mAPrZ4sMLW+tmxl5ZuGtPUcdFu+MPP2jbgiWAZ6Pfe5soGFMd+0Db5Vrog==} @@ -10767,6 +10844,10 @@ packages: resolution: {integrity: sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==} engines: {node: '>=16 || 14 >=14.17'} + path-scurry@2.0.0: + resolution: {integrity: sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==} + engines: {node: 20 || >=22} + path-to-regexp@0.1.7: resolution: {integrity: sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==} @@ -16225,6 +16306,8 @@ snapshots: '@eslint/object-schema@2.1.4': {} + '@fastify/accept-negotiator@2.0.0': {} + '@fastify/ajv-compiler@4.0.1': dependencies: ajv: 8.13.0 @@ -16252,6 +16335,28 @@ snapshots: dependencies: fast-deep-equal: 3.1.3 + '@fastify/send@3.1.1': + dependencies: + '@lukeed/ms': 2.0.2 + escape-html: 1.0.3 + fast-decode-uri-component: 1.0.1 + http-errors: 2.0.0 + mime: 3.0.0 + + '@fastify/static@8.0.1': + dependencies: + '@fastify/accept-negotiator': 2.0.0 + '@fastify/send': 3.1.1 + content-disposition: 0.5.4 + fastify-plugin: 5.0.1 + fastq: 1.17.1 + glob: 11.0.0 + + '@fastify/view@10.0.1': + dependencies: + fastify-plugin: 5.0.1 + toad-cache: 3.7.0 + '@firebase/app-check-interop-types@0.3.2': {} '@firebase/app-types@0.9.2': {} @@ -17316,6 +17421,8 @@ snapshots: '@libsql/win32-x64-msvc@0.3.18': optional: true + '@lukeed/ms@2.0.2': {} + '@manypkg/find-root@1.1.0': dependencies: '@babel/runtime': 7.23.9 @@ -23705,6 +23812,15 @@ snapshots: minipass: 5.0.0 path-scurry: 1.10.1 + glob@11.0.0: + dependencies: + foreground-child: 3.1.1 + jackspeak: 4.0.2 + minimatch: 10.0.1 + minipass: 7.1.2 + package-json-from-dist: 1.0.1 + path-scurry: 2.0.0 + glob@7.2.3: dependencies: fs.realpath: 1.0.0 @@ -24617,6 +24733,10 @@ snapshots: optionalDependencies: '@pkgjs/parseargs': 0.11.0 + jackspeak@4.0.2: + dependencies: + '@isaacs/cliui': 8.0.2 + jake@10.8.7: dependencies: async: 3.2.5 @@ -25178,6 +25298,8 @@ snapshots: lru-cache@10.2.0: {} + lru-cache@11.0.1: {} + lru-cache@4.0.2: dependencies: pseudomap: 1.0.2 @@ -26034,6 +26156,10 @@ snapshots: min-indent@1.0.1: {} + minimatch@10.0.1: + dependencies: + brace-expansion: 2.0.1 + minimatch@3.0.8: dependencies: brace-expansion: 1.1.11 @@ -26111,6 +26237,8 @@ snapshots: minipass@7.1.1: {} + minipass@7.1.2: {} + minizlib@2.1.2: dependencies: minipass: 3.3.6 @@ -26792,6 +26920,8 @@ snapshots: p-try@2.2.0: {} + package-json-from-dist@1.0.1: {} + package-manager-detector@0.2.0: {} packet-reader@1.0.0: {} @@ -26910,6 +27040,11 @@ snapshots: lru-cache: 10.2.0 minipass: 5.0.0 + path-scurry@2.0.0: + dependencies: + lru-cache: 11.0.1 + minipass: 7.1.2 + path-to-regexp@0.1.7: {} path-type@4.0.0: {} From 83d971b3b3f4a1ffb8f1c527f7ee34cad7481f1f Mon Sep 17 00:00:00 2001 From: Songkeys Date: Tue, 1 Oct 2024 12:51:43 +0800 Subject: [PATCH 2/2] fix for reviews --- apps/dev/fastify/src/app.ts | 8 ++- apps/dev/fastify/src/config/auth.config.ts | 54 +++++++++---------- apps/dev/fastify/views/error.pug | 4 +- apps/dev/fastify/views/index.pug | 6 +-- apps/dev/fastify/views/layout.pug | 26 +++++---- apps/dev/fastify/views/protected.pug | 17 ++---- apps/dev/fastify/views/unauthenticated.pug | 8 +++ apps/examples/fastify/src/app.ts | 8 ++- .../fastify/src/config/auth.config.ts | 54 +++++++++---------- packages/frameworks-fastify/src/index.ts | 17 +++--- 10 files changed, 113 insertions(+), 89 deletions(-) create mode 100644 apps/dev/fastify/views/unauthenticated.pug diff --git a/apps/dev/fastify/src/app.ts b/apps/dev/fastify/src/app.ts index c46f53bdbe..b008b3b21e 100644 --- a/apps/dev/fastify/src/app.ts +++ b/apps/dev/fastify/src/app.ts @@ -11,13 +11,19 @@ import { currentSession, } from "./middleware/auth.middleware.js" -import { FastifyAuth } from "@auth/fastify" +import { FastifyAuth, type Session } from "@auth/fastify" import { authConfig } from "./config/auth.config.js" import * as pug from "pug" import fastifyView from "@fastify/view" import fastifyStatic from "@fastify/static" +declare module "fastify" { + interface FastifyReply { + session: Session | null + } +} + // Trust Proxy for Proxies (Heroku, Render.com, Docker behind Nginx, etc) export const fastify = Fastify({ trustProxy: true, logger: true }) diff --git a/apps/dev/fastify/src/config/auth.config.ts b/apps/dev/fastify/src/config/auth.config.ts index a85bb2d1f7..1798ef1f43 100644 --- a/apps/dev/fastify/src/config/auth.config.ts +++ b/apps/dev/fastify/src/config/auth.config.ts @@ -1,33 +1,33 @@ -import Apple from "@auth/express/providers/apple" -import Auth0 from "@auth/express/providers/auth0" -import AzureB2C from "@auth/express/providers/azure-ad-b2c" -import BoxyHQSAML from "@auth/express/providers/boxyhq-saml" -import Cognito from "@auth/express/providers/cognito" -import Coinbase from "@auth/express/providers/coinbase" -import Discord from "@auth/express/providers/discord" -import Dropbox from "@auth/express/providers/dropbox" -import Facebook from "@auth/express/providers/facebook" -import GitHub from "@auth/express/providers/github" -import Gitlab from "@auth/express/providers/gitlab" -import Google from "@auth/express/providers/google" -import Hubspot from "@auth/express/providers/hubspot" -import Keycloak from "@auth/express/providers/keycloak" -import LinkedIn from "@auth/express/providers/linkedin" -import Netlify from "@auth/express/providers/netlify" -import Okta from "@auth/express/providers/okta" -import Passage from "@auth/express/providers/passage" -import Pinterest from "@auth/express/providers/pinterest" -import Reddit from "@auth/express/providers/reddit" -import Slack from "@auth/express/providers/slack" -import Spotify from "@auth/express/providers/spotify" -import Twitch from "@auth/express/providers/twitch" -import Twitter from "@auth/express/providers/twitter" -import WorkOS from "@auth/express/providers/workos" -import Zoom from "@auth/express/providers/zoom" +import Apple from "@auth/fastify/providers/apple" +import Auth0 from "@auth/fastify/providers/auth0" +import AzureB2C from "@auth/fastify/providers/azure-ad-b2c" +import BoxyHQSAML from "@auth/fastify/providers/boxyhq-saml" +import Cognito from "@auth/fastify/providers/cognito" +import Coinbase from "@auth/fastify/providers/coinbase" +import Discord from "@auth/fastify/providers/discord" +import Dropbox from "@auth/fastify/providers/dropbox" +import Facebook from "@auth/fastify/providers/facebook" +import GitHub from "@auth/fastify/providers/github" +import Gitlab from "@auth/fastify/providers/gitlab" +import Google from "@auth/fastify/providers/google" +import Hubspot from "@auth/fastify/providers/hubspot" +import Keycloak from "@auth/fastify/providers/keycloak" +import LinkedIn from "@auth/fastify/providers/linkedin" +import Netlify from "@auth/fastify/providers/netlify" +import Okta from "@auth/fastify/providers/okta" +import Passage from "@auth/fastify/providers/passage" +import Pinterest from "@auth/fastify/providers/pinterest" +import Reddit from "@auth/fastify/providers/reddit" +import Slack from "@auth/fastify/providers/slack" +import Spotify from "@auth/fastify/providers/spotify" +import Twitch from "@auth/fastify/providers/twitch" +import Twitter from "@auth/fastify/providers/twitter" +import WorkOS from "@auth/fastify/providers/workos" +import Zoom from "@auth/fastify/providers/zoom" export const authConfig = { trustHost: true, - debug: process.env.NODE_ENV !== "production" ? true : false, + debug: process.env.NODE_ENV !== "production", providers: [ Apple, Auth0, diff --git a/apps/dev/fastify/views/error.pug b/apps/dev/fastify/views/error.pug index 4d62885b53..904c3bccb0 100644 --- a/apps/dev/fastify/views/error.pug +++ b/apps/dev/fastify/views/error.pug @@ -1,5 +1,5 @@ extends layout block content - h1=title - p=message + h1(class="text-3xl font-bold")= title + p= message diff --git a/apps/dev/fastify/views/index.pug b/apps/dev/fastify/views/index.pug index 46708a98ee..3781e616a5 100644 --- a/apps/dev/fastify/views/index.pug +++ b/apps/dev/fastify/views/index.pug @@ -1,11 +1,11 @@ extends layout block content - h1=title + h1(class="text-3xl font-bold")= title p | This is an example site to demonstrate how to use #{ ' ' } - a(href="https://expressjs.com/") Express + a(href="https://fastify.dev/", class="mb-2 font-medium underline") Fastify | #{ ' ' } with #{ ' ' } - a(href="https://authjs.dev/reference/express") Express Auth + a(href="https://authjs.dev/reference/fastify", class="underline") Fastify Auth | | for authentication. diff --git a/apps/dev/fastify/views/layout.pug b/apps/dev/fastify/views/layout.pug index ed1bf74915..32cc435314 100644 --- a/apps/dev/fastify/views/layout.pug +++ b/apps/dev/fastify/views/layout.pug @@ -1,29 +1,35 @@ doctype html html head - title=title - meta(name="viewport" content="width=device-width, initial-scale=1.0") - body - div - div + title= title + link(rel="stylesheet", href="/css/output.css") + meta(name="viewport", content="width=device-width, initial-scale=1.0") + body(class="flex flex-col items-center") + div(class="flex w-[90%] max-w-2xl flex-col justify-start gap-2") + div( + class="mb-2 flex items-center justify-between gap-2 rounded-b-md bg-gray-100 p-2 pl-4" + ) if session - div + div(class="flex flex-row items-center gap-2") if session.user.image - img(src=`${session.user.image}` style="width:64px;border-radius:50%;") + img(src=`${session.user.image}`, class="h-8 w-8 rounded-full") span | Signed in as #{ ' ' } strong= session.user.email || session.user.name a( + class="rounded-md bg-blue-600 px-5 py-2.5 font-medium text-white", href="/api/auth/signout" ) Sign out else - span You are not signed in #{ ' ' } + span(class="") You are not signed in a#sign-indiv( + , + class="rounded-md bg-blue-600 px-5 py-2.5 font-medium text-white", href="/api/auth/signin" ) Sign in - nav - ul + nav(class="mb-4") + ul(class="flex flex-row gap-4 underline") li a(href="/") Home li diff --git a/apps/dev/fastify/views/protected.pug b/apps/dev/fastify/views/protected.pug index 97790e3b32..9ceaac767c 100644 --- a/apps/dev/fastify/views/protected.pug +++ b/apps/dev/fastify/views/protected.pug @@ -1,15 +1,8 @@ extends layout block content - if session - h1 Protected page - p - | This is a protected content. You can access this content because you are - | signed in. - p Session expiry: #{ session.expires ? session.expires : '' } - else - h1 Access Denied - p - | You must be #{ ' ' } - a(href="/api/auth/signin") signed in - | #{ ' ' } to view this page + h1(class="mb-2 text-3xl font-medium") Protected page + p + | This is a protected content. You can access this content because you are + | signed in. + p Session expiry: #{ session.expires ? session.expires : '' } diff --git a/apps/dev/fastify/views/unauthenticated.pug b/apps/dev/fastify/views/unauthenticated.pug new file mode 100644 index 0000000000..6b334387bd --- /dev/null +++ b/apps/dev/fastify/views/unauthenticated.pug @@ -0,0 +1,8 @@ +extends layout + +block content + h1(class="mb-2 text-3xl font-medium") Access Denied + p + | You must be #{ ' ' } + a(href="/api/auth/signin", class="underline") signed in + | #{ ' ' } to view this page diff --git a/apps/examples/fastify/src/app.ts b/apps/examples/fastify/src/app.ts index 229be62a82..e4b6f6f07f 100644 --- a/apps/examples/fastify/src/app.ts +++ b/apps/examples/fastify/src/app.ts @@ -12,13 +12,19 @@ import { currentSession, } from "./middleware/auth.middleware.js" -import { FastifyAuth } from "@auth/fastify" +import { FastifyAuth, type Session } from "@auth/fastify" import { authConfig } from "./config/auth.config.js" import * as pug from "pug" import fastifyView from "@fastify/view" import fastifyStatic from "@fastify/static" +declare module "fastify" { + interface FastifyReply { + session: Session | null + } +} + // Trust Proxy for Proxies (Heroku, Render.com, Docker behind Nginx, etc) export const fastify = Fastify({ trustProxy: true, logger: true }) diff --git a/apps/examples/fastify/src/config/auth.config.ts b/apps/examples/fastify/src/config/auth.config.ts index a85bb2d1f7..1798ef1f43 100644 --- a/apps/examples/fastify/src/config/auth.config.ts +++ b/apps/examples/fastify/src/config/auth.config.ts @@ -1,33 +1,33 @@ -import Apple from "@auth/express/providers/apple" -import Auth0 from "@auth/express/providers/auth0" -import AzureB2C from "@auth/express/providers/azure-ad-b2c" -import BoxyHQSAML from "@auth/express/providers/boxyhq-saml" -import Cognito from "@auth/express/providers/cognito" -import Coinbase from "@auth/express/providers/coinbase" -import Discord from "@auth/express/providers/discord" -import Dropbox from "@auth/express/providers/dropbox" -import Facebook from "@auth/express/providers/facebook" -import GitHub from "@auth/express/providers/github" -import Gitlab from "@auth/express/providers/gitlab" -import Google from "@auth/express/providers/google" -import Hubspot from "@auth/express/providers/hubspot" -import Keycloak from "@auth/express/providers/keycloak" -import LinkedIn from "@auth/express/providers/linkedin" -import Netlify from "@auth/express/providers/netlify" -import Okta from "@auth/express/providers/okta" -import Passage from "@auth/express/providers/passage" -import Pinterest from "@auth/express/providers/pinterest" -import Reddit from "@auth/express/providers/reddit" -import Slack from "@auth/express/providers/slack" -import Spotify from "@auth/express/providers/spotify" -import Twitch from "@auth/express/providers/twitch" -import Twitter from "@auth/express/providers/twitter" -import WorkOS from "@auth/express/providers/workos" -import Zoom from "@auth/express/providers/zoom" +import Apple from "@auth/fastify/providers/apple" +import Auth0 from "@auth/fastify/providers/auth0" +import AzureB2C from "@auth/fastify/providers/azure-ad-b2c" +import BoxyHQSAML from "@auth/fastify/providers/boxyhq-saml" +import Cognito from "@auth/fastify/providers/cognito" +import Coinbase from "@auth/fastify/providers/coinbase" +import Discord from "@auth/fastify/providers/discord" +import Dropbox from "@auth/fastify/providers/dropbox" +import Facebook from "@auth/fastify/providers/facebook" +import GitHub from "@auth/fastify/providers/github" +import Gitlab from "@auth/fastify/providers/gitlab" +import Google from "@auth/fastify/providers/google" +import Hubspot from "@auth/fastify/providers/hubspot" +import Keycloak from "@auth/fastify/providers/keycloak" +import LinkedIn from "@auth/fastify/providers/linkedin" +import Netlify from "@auth/fastify/providers/netlify" +import Okta from "@auth/fastify/providers/okta" +import Passage from "@auth/fastify/providers/passage" +import Pinterest from "@auth/fastify/providers/pinterest" +import Reddit from "@auth/fastify/providers/reddit" +import Slack from "@auth/fastify/providers/slack" +import Spotify from "@auth/fastify/providers/spotify" +import Twitch from "@auth/fastify/providers/twitch" +import Twitter from "@auth/fastify/providers/twitter" +import WorkOS from "@auth/fastify/providers/workos" +import Zoom from "@auth/fastify/providers/zoom" export const authConfig = { trustHost: true, - debug: process.env.NODE_ENV !== "production" ? true : false, + debug: process.env.NODE_ENV !== "production", providers: [ Apple, Auth0, diff --git a/packages/frameworks-fastify/src/index.ts b/packages/frameworks-fastify/src/index.ts index bb504718cf..a84c9dc035 100644 --- a/packages/frameworks-fastify/src/index.ts +++ b/packages/frameworks-fastify/src/index.ts @@ -63,6 +63,17 @@ * }) * ``` * + * Note for TypeScript, you may want to augment the Fastify types to include the `session` property on the reply object. This can be done by creating a @types/fastify/index.d.ts file: + * + * ```ts title="@types/fastify/index.d.ts" + * import { Session } from "@auth/core/types"; + * declare module "fastify" { + * interface FastifyReply { + * session: Session | null; + * } + * } + * ``` + * * You may need to add `"typeRoots": ["@types"]` to `compilerOptions` in your tsconfig.json. * * ## Authorization @@ -130,12 +141,6 @@ import type { FastifyRequest, FastifyPluginAsync } from "fastify" import formbody from "@fastify/formbody" import { toWebRequest, toFastifyReply } from "./lib/index.js" -declare module "fastify" { - interface FastifyReply { - session: Session | null - } -} - export type FastifyAuthConfig = Omit export type {