@auth/fastify
@auth/fastify
is currently experimental. The API will change in the future.
Fastify Auth is the official Fastify integration for Auth.js. It provides a simple way to add authentication to your Fastify app in a few lines of code.
Installationβ
- npm
- Yarn
- pnpm
npm install @auth/fastify
yarn add @auth/fastify
pnpm add @auth/fastify
Usageβ
import { FastifyAuth } from "@auth/fastify"
import formbodyParser from "@fastify/formbody"
import GitHub from "@auth/fastify/providers/github"
import Fastify from "fastify"
// If app is served through a proxy, trust the proxy to allow HTTPS protocol to be detected
const fastify = Fastify({ trustProxy: true });
// Make sure to use a form body parser so Auth.js can receive data from the client
fastify.register(formbodyParser)
fastify.register(FastifyAuth({ providers: [ GitHub ] }), { prefix: '/auth' })
Don't forget to set the AUTH_SECRET
environment variable. This should be a minimum of 32 characters, random string. On UNIX systems you can use openssl rand -hex 32
or check out https://generate-secret.vercel.app/32
.
You will also need to load the environment variables into your runtime environment. For example in Node.js with a package like dotenv
or Deno.env
in Deno.
Provider Configurationβ
The callback URL used by the providers must be set to the following, unless you mount the FastifyAuth
handler on a different path:
[origin]/auth/callback/[provider]
Signing in and signing outβ
Once your application is mounted you can sign in or out by making requests to the following REST API endpoints from your client-side code.
NB: Make sure to include the csrfToken
in the request body for all sign-in and sign-out requests.
Managing the sessionβ
If you are using Fastify with a template engine (e.g @fastify/view with EJS, Pug), you can make the session data available to all routes via a preHandler hook as follows
import { getSession } from "@auth/fastify"
// Decorating the reply is not required but will optimise performance
fastify.decorateReply('session', null)
export async function authSession(req: FastifyRequest, reply: FastifyReply) {
reply.session = await getSession(req, authConfig)
}
fastify.addHook("preHandler", authSession)
// Now in your route
fastify.get("/", (req, reply) => {
const session = reply.session;
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:
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β
You can protect routes with hooks by checking for the presence of a session and then redirect to a login page if the session is not present.
export async function authenticatedUser(
req: FastifyRequest,
reply: FastifyReply
) {
reply.session ??= await getSession(req, authConfig);
if (!reply.session?.user) {
reply.redirect("/auth/signin?error=SessionRequired");
}
}
Per Routeβ
To protect a single route, simply register the preHandler hook to the route as follows:
// This route is protected
fastify.get("/profile", { preHandler: [authenticatedUser] }, (req, reply) => {
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:
fastify.register(
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)
})
},
{ prefix: "/protected" }
)
Accountβ
Usually contains information about the provider being used
and also extends TokenSet
, which is different tokens returned by OAuth Providers.
Extendsβ
Partial
<OpenIDTokenEndpointResponse
>
Propertiesβ
providerβ
provider: string;
Provider's id for this account. Eg.: "google"
providerAccountIdβ
providerAccountId: string;
This value depends on the type of the provider being used to create the account.
- oauth/oidc: The OAuth account's id, returned from the
profile()
callback. - email: The user's email address.
- credentials:
id
returned from theauthorize()
callback
typeβ
type: ProviderType;
Provider's type for this account
expires_atβ
expires_at?: number;
Calculated value based on [OAuth2TokenEndpointResponse.expires_in]([object Object]).
It is the absolute timestamp (in seconds) when the [OAuth2TokenEndpointResponse.access_token]([object Object]) expires.
This value can be used for implementing token rotation together with [OAuth2TokenEndpointResponse.refresh_token]([object Object]).
Seeβ
- https://authjs.dev/guides/basics/refresh-token-rotation#database-strategy
- https://www.rfc-editor.org/rfc/rfc6749#section-5.1
userIdβ
userId?: string;
id of the user this account belongs to
Seeβ
https://authjs.dev/reference/core/adapters#user
Profileβ
The user info returned from your OAuth provider.
Seeβ
https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims
Sessionβ
The active session of the logged in user.
Extendsβ
DefaultSession
Userβ
The shape of the returned object in the OAuth providers' profile
callback,
available in the jwt
and session
callbacks,
or the second parameter of the session
callback, when using a database.