Skip to content

Commit 4a404b3

Browse files
authored
Merge pull request #1 from songkeys/main
feat: add fastify example
2 parents 16af091 + 83d971b commit 4a404b3

File tree

26 files changed

+628
-47
lines changed

26 files changed

+628
-47
lines changed

apps/dev/fastify/.env.example

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
AUTH_SECRET=
2+
3+
AUTH_GITHUB_ID=
4+
AUTH_GITHUB_SECRET=
5+
6+
AUTH_GOOGLE_ID=
7+
AUTH_GOOGLE_SECRET=

apps/dev/fastify/.gitignore

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# API keys and secrets
2+
.env
3+
4+
# Dependency directory
5+
node_modules
6+
7+
# Editors
8+
.idea
9+
*.iml
10+
.vscode/settings.json
11+
12+
# OS metadata
13+
.DS_Store
14+
Thumbs.db
15+
16+
# Ignore built ts files
17+
dist/**/*
18+
19+
# Ignore built css files
20+
/public/css/output.css
21+

apps/dev/fastify/.prettierignore

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
2+
.DS_Store
3+
node_modules
4+
/dist
5+
/.turbo
6+
/package
7+
.env
8+
.env.*
9+
!.env.example
10+
11+
# Ignore files for PNPM, NPM and YARN
12+
pnpm-lock.yaml
13+
package-lock.json
14+
yarn.lock

apps/dev/fastify/README.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
> 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).
2+
3+
<p align="center">
4+
<br/>
5+
<a href="https://authjs.dev" target="_blank"><img width="150px" src="https://authjs.dev/img/logo-sm.png" /></a>
6+
<h3 align="center">Auth.js Example App with <a href="https://fastify.dev">Fastify</a></h3>
7+
<p align="center">
8+
Open Source. Full Stack. Own Your Data.
9+
</p>
10+
<p align="center" style="align: center;">
11+
<a href="https://npm.im/@auth/fastify">
12+
<img alt="npm" src="https://img.shields.io/npm/v/@auth/fastify?color=green&label=@auth/fastify&style=flat-square">
13+
</a>
14+
<a href="https://bundlephobia.com/result?p=@auth/fastify">
15+
<img src="https://img.shields.io/bundlephobia/minzip/@auth/fastify?label=size&style=flat-square" alt="Bundle Size"/>
16+
</a>
17+
<a href="https://www.npmtrends.com/@auth/fastify">
18+
<img src="https://img.shields.io/npm/dm/@auth/fastify?label=%20downloads&style=flat-square" alt="Downloads" />
19+
</a>
20+
<a href="https://npm.im/next-auth">
21+
<img src="https://img.shields.io/badge/TypeScript-blue?style=flat-square" alt="TypeScript" />
22+
</a>
23+
</p>
24+
</p>
25+
26+
# Documentation
27+
28+
- [fastify.authjs.dev](https://fastify.authjs.dev)

apps/dev/fastify/api/index.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import { app } from "../src/app.js"
2+
3+
export default app

apps/dev/fastify/package.json

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
{
2+
"name": "fastify-auth-app",
3+
"description": "Fastify + Auth.js Developer app",
4+
"type": "module",
5+
"private": true,
6+
"scripts": {
7+
"start": "node dist/server.js",
8+
"clean": "rm -rf dist",
9+
"build": "pnpm build:ts && pnpm build:css",
10+
"build:ts": "tsc",
11+
"build:css": "tailwindcss -i ./public/css/style.css -o ./public/css/output.css",
12+
"dev": "tsx watch --env-file=.env src/server.ts & pnpm build:css -w",
13+
"debug": "tsx watch --inspect --env-file=.env src/server.ts & pnpm build:css -w",
14+
"lint": "eslint src/*.ts --fix",
15+
"prettier": "prettier src/*.ts --write"
16+
},
17+
"author": "Songkeys (https://github.com/songkeys)",
18+
"license": "MIT",
19+
"dependencies": {
20+
"@auth/fastify": "workspace:*",
21+
"fastify": "^5.0.0",
22+
"@fastify/view": "^10.0.1",
23+
"@fastify/static": "^8.0.1",
24+
"pug": "^3.0.2",
25+
"tailwindcss": "^3.4.3"
26+
},
27+
"devDependencies": {
28+
"@prettier/plugin-pug": "^3.0.0",
29+
"@types/morgan": "^1.9.9",
30+
"@types/pug": "^2.0.10",
31+
"tsx": "^4.7.3",
32+
"typescript": "5.4.5"
33+
}
34+
}

apps/dev/fastify/public/css/style.css

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
@tailwind base;
2+
3+
@tailwind components;
4+
5+
@tailwind utilities;

apps/dev/fastify/src/app.ts

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
import Fastify from "fastify"
2+
3+
import * as path from "node:path"
4+
import {
5+
errorHandler,
6+
errorNotFoundHandler,
7+
} from "./middleware/error.middleware.js"
8+
import {
9+
authenticatedApi,
10+
authenticatedPage,
11+
currentSession,
12+
} from "./middleware/auth.middleware.js"
13+
14+
import { FastifyAuth, type Session } from "@auth/fastify"
15+
import { authConfig } from "./config/auth.config.js"
16+
17+
import * as pug from "pug"
18+
import fastifyView from "@fastify/view"
19+
import fastifyStatic from "@fastify/static"
20+
21+
declare module "fastify" {
22+
interface FastifyReply {
23+
session: Session | null
24+
}
25+
}
26+
27+
// Trust Proxy for Proxies (Heroku, Render.com, Docker behind Nginx, etc)
28+
export const fastify = Fastify({ trustProxy: true, logger: true })
29+
30+
// Decorating the reply is not required but will optimise performance
31+
// Only decorate the reply with a value type like null, as reference types like objects are shared among all requests, creating a security risk.
32+
fastify.decorateReply("session", null)
33+
34+
fastify.register(fastifyView, {
35+
engine: {
36+
pug,
37+
},
38+
root: path.join(import.meta.dirname, "..", "views"),
39+
})
40+
41+
// Serve static files
42+
// NB: Uncomment this out if you want Fastify to serve static files for you vs. using a
43+
// hosting provider which does so for you (for example through a CDN).
44+
fastify.register(fastifyStatic, {
45+
root: path.join(import.meta.dirname, "..", "public"),
46+
})
47+
48+
// Set session in reply
49+
fastify.addHook("preHandler", currentSession)
50+
51+
// Set up FastifyAuth to handle authentication
52+
// IMPORTANT: It is highly encouraged set up rate limiting on this route
53+
fastify.register(FastifyAuth(authConfig), { prefix: "/api/auth" })
54+
55+
// Routes
56+
fastify.get(
57+
"/protected",
58+
{ preHandler: [authenticatedPage] },
59+
async (req, reply) => {
60+
return reply.view("protected", { session: reply.session })
61+
}
62+
)
63+
64+
fastify.get(
65+
"/api/protected",
66+
{ preHandler: [authenticatedApi] },
67+
async (req, reply) => {
68+
return reply.send(reply.session)
69+
}
70+
)
71+
72+
fastify.get("/", async (_req, reply) => {
73+
return reply.view("index", {
74+
title: "Fastify Auth Example",
75+
user: reply.session?.user,
76+
})
77+
})
78+
79+
fastify.get("/2", async (_req, reply) => {
80+
return reply.view("index", {
81+
title: "Fastify Auth Example",
82+
user: reply.session?.user,
83+
})
84+
})
85+
86+
fastify.setErrorHandler(errorHandler)
87+
fastify.setNotFoundHandler(errorNotFoundHandler)
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import Apple from "@auth/fastify/providers/apple"
2+
import Auth0 from "@auth/fastify/providers/auth0"
3+
import AzureB2C from "@auth/fastify/providers/azure-ad-b2c"
4+
import BoxyHQSAML from "@auth/fastify/providers/boxyhq-saml"
5+
import Cognito from "@auth/fastify/providers/cognito"
6+
import Coinbase from "@auth/fastify/providers/coinbase"
7+
import Discord from "@auth/fastify/providers/discord"
8+
import Dropbox from "@auth/fastify/providers/dropbox"
9+
import Facebook from "@auth/fastify/providers/facebook"
10+
import GitHub from "@auth/fastify/providers/github"
11+
import Gitlab from "@auth/fastify/providers/gitlab"
12+
import Google from "@auth/fastify/providers/google"
13+
import Hubspot from "@auth/fastify/providers/hubspot"
14+
import Keycloak from "@auth/fastify/providers/keycloak"
15+
import LinkedIn from "@auth/fastify/providers/linkedin"
16+
import Netlify from "@auth/fastify/providers/netlify"
17+
import Okta from "@auth/fastify/providers/okta"
18+
import Passage from "@auth/fastify/providers/passage"
19+
import Pinterest from "@auth/fastify/providers/pinterest"
20+
import Reddit from "@auth/fastify/providers/reddit"
21+
import Slack from "@auth/fastify/providers/slack"
22+
import Spotify from "@auth/fastify/providers/spotify"
23+
import Twitch from "@auth/fastify/providers/twitch"
24+
import Twitter from "@auth/fastify/providers/twitter"
25+
import WorkOS from "@auth/fastify/providers/workos"
26+
import Zoom from "@auth/fastify/providers/zoom"
27+
28+
export const authConfig = {
29+
trustHost: true,
30+
debug: process.env.NODE_ENV !== "production",
31+
providers: [
32+
Apple,
33+
Auth0,
34+
AzureB2C({
35+
clientId: process.env.AUTH_AZURE_AD_B2C_ID,
36+
clientSecret: process.env.AUTH_AZURE_AD_B2C_SECRET,
37+
issuer: process.env.AUTH_AZURE_AD_B2C_ISSUER,
38+
}),
39+
BoxyHQSAML({
40+
clientId: "dummy",
41+
clientSecret: "dummy",
42+
issuer: process.env.AUTH_BOXYHQ_SAML_ISSUER,
43+
}),
44+
Cognito,
45+
Coinbase,
46+
Discord,
47+
Dropbox,
48+
Facebook,
49+
GitHub,
50+
Gitlab,
51+
Google,
52+
Hubspot,
53+
Keycloak,
54+
LinkedIn,
55+
Netlify,
56+
Okta,
57+
Passage,
58+
Pinterest,
59+
Reddit,
60+
Slack,
61+
Spotify,
62+
Twitch,
63+
Twitter,
64+
WorkOS({
65+
connection: process.env.AUTH_WORKOS_CONNECTION!,
66+
}),
67+
Zoom,
68+
],
69+
}

apps/dev/fastify/src/errors.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
export class HttpError extends Error {
2+
status: number
3+
constructor(status: number, message: string) {
4+
super(message)
5+
this.status = status
6+
}
7+
}
8+
9+
export class NotFoundError extends HttpError {
10+
constructor(message: string, status = 404) {
11+
super(status, message)
12+
this.name = "NotFoundError"
13+
}
14+
}

0 commit comments

Comments
 (0)