Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(frameworks): add @auth/fastify #9587

Open
wants to merge 38 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
11731a4
feat: add fastify framework
hillac Jan 9, 2024
426a87c
test: add session, request and response tests.
hillac Jan 9, 2024
a3835dc
docs: add docs
hillac Jan 9, 2024
0bd850e
Merge branch 'main' into main
ndom91 Jan 15, 2024
f94310a
clean up plugin and extend login test
hillac Jan 15, 2024
bc8372a
Merge branch 'main' of github.com:hillac/next-auth into main
hillac Jan 15, 2024
65632ff
Merge branch 'main' into main
ndom91 Jan 15, 2024
dc17fd0
fix some test expectations silently not running
hillac Jan 18, 2024
83bde07
support redirectProxyUrl
hillac Jan 18, 2024
4e21a20
Merge remote-tracking branch 'upstream/main' into main
hillac Mar 22, 2024
54856ff
change to latest config style
hillac Mar 22, 2024
49dff8b
change tests to vitest
hillac Mar 22, 2024
270dd13
create docs for fastify
hillac Mar 25, 2024
6ab3479
register @fastify/formbody in plugin
hillac Mar 26, 2024
32d647e
move formbody to dependencies
hillac Mar 27, 2024
825bdbd
Merge branch 'main' into auth-fastify
hillac May 12, 2024
4f89aaf
prettier format
hillac May 12, 2024
1ab4a57
configure new docs for fastify
hillac May 12, 2024
ed3a279
Merge branch 'main' into auth-fastify
hillac May 24, 2024
b49097d
docs: add fastify code tabs + add installation page code
hillac May 24, 2024
0ee816d
docs: add session managment docs
hillac May 24, 2024
eaaa907
docs: fix highlighting fastify docs
hillac May 24, 2024
5f458ff
docs: add api vs protecting note
hillac May 24, 2024
36497fd
Merge branch 'main' into auth-fastify
hillac Jun 19, 2024
8fd04e6
Merge branch 'main' into auth-fastify
Jul 11, 2024
b9583f6
Merge branch 'main' into main
ndom91 Jul 23, 2024
c88c12f
fix(docs): Code component for Fastify
ndom91 Jul 23, 2024
a17c080
chore: add fastify to turbo.json docs#build
ndom91 Jul 23, 2024
979e0b5
Merge branch 'main' into auth-fastify
Sep 29, 2024
87edcf5
lint + fix get session action url
Sep 29, 2024
3f68fee
update fastify + export config type
Sep 30, 2024
e4a355e
fix port not in hostname
Sep 30, 2024
9079f1f
fastify dev app
Sep 30, 2024
16af091
update pnpm lock + fix type
Sep 30, 2024
d171f75
feat: add fastify example
songkeys Sep 30, 2024
83d971b
fix for reviews
songkeys Oct 1, 2024
4a404b3
Merge pull request #1 from songkeys/main
hillac Oct 1, 2024
302eb31
remove unnecessary type from #1 + simplify type
Oct 1, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,10 @@ docs/docs/reference/solidstart
# Express
docs/docs/reference/express

# Fastify
docs/docs/reference/fastify



# Adapters
docs/docs/reference/adapter
Expand Down
3 changes: 3 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ packages/frameworks-sveltekit/vite.config.{js,ts}.timestamp-*
# @auth/express
packages/frameworks-express/providers

# @auth/fastify
packages/frameworks-fastify/providers

# next-auth
packages/next-auth/src/providers/oauth-types.ts
packages/next-auth/css/index.css
Expand Down
7 changes: 7 additions & 0 deletions apps/dev/fastify/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
AUTH_SECRET=

AUTH_GITHUB_ID=
AUTH_GITHUB_SECRET=

AUTH_GOOGLE_ID=
AUTH_GOOGLE_SECRET=
21 changes: 21 additions & 0 deletions apps/dev/fastify/.gitignore
Original file line number Diff line number Diff line change
@@ -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

14 changes: 14 additions & 0 deletions apps/dev/fastify/.prettierignore
Original file line number Diff line number Diff line change
@@ -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
28 changes: 28 additions & 0 deletions apps/dev/fastify/README.md
Original file line number Diff line number Diff line change
@@ -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).

<p align="center">
<br/>
<a href="https://authjs.dev" target="_blank"><img width="150px" src="https://authjs.dev/img/logo-sm.png" /></a>
<h3 align="center">Auth.js Example App with <a href="https://fastify.dev">Fastify</a></h3>
<p align="center">
Open Source. Full Stack. Own Your Data.
</p>
<p align="center" style="align: center;">
<a href="https://npm.im/@auth/fastify">
<img alt="npm" src="https://img.shields.io/npm/v/@auth/fastify?color=green&label=@auth/fastify&style=flat-square">
</a>
<a href="https://bundlephobia.com/result?p=@auth/fastify">
<img src="https://img.shields.io/bundlephobia/minzip/@auth/fastify?label=size&style=flat-square" alt="Bundle Size"/>
</a>
<a href="https://www.npmtrends.com/@auth/fastify">
<img src="https://img.shields.io/npm/dm/@auth/fastify?label=%20downloads&style=flat-square" alt="Downloads" />
</a>
<a href="https://npm.im/next-auth">
<img src="https://img.shields.io/badge/TypeScript-blue?style=flat-square" alt="TypeScript" />
</a>
</p>
</p>

# Documentation

- [fastify.authjs.dev](https://fastify.authjs.dev)
3 changes: 3 additions & 0 deletions apps/dev/fastify/api/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { app } from "../src/app.js"

export default app
34 changes: 34 additions & 0 deletions apps/dev/fastify/package.json
Original file line number Diff line number Diff line change
@@ -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"
}
}
5 changes: 5 additions & 0 deletions apps/dev/fastify/public/css/style.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
@tailwind base;

@tailwind components;

@tailwind utilities;
87 changes: 87 additions & 0 deletions apps/dev/fastify/src/app.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
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, 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 })

// 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)
69 changes: 69 additions & 0 deletions apps/dev/fastify/src/config/auth.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +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"

export const authConfig = {
trustHost: true,
debug: process.env.NODE_ENV !== "production",
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,
],
}
14 changes: 14 additions & 0 deletions apps/dev/fastify/src/errors.ts
Original file line number Diff line number Diff line change
@@ -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"
}
}
28 changes: 28 additions & 0 deletions apps/dev/fastify/src/middleware/auth.middleware.ts
Original file line number Diff line number Diff line change
@@ -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
}
22 changes: 22 additions & 0 deletions apps/dev/fastify/src/middleware/error.middleware.ts
Original file line number Diff line number Diff line change
@@ -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")
}
18 changes: 18 additions & 0 deletions apps/dev/fastify/src/server.ts
Original file line number Diff line number Diff line change
@@ -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()
Loading
Loading