Skip to main content

@auth/fastify

warning

@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 install @auth/fastify

Usage​

src/routes/auth.route.ts
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

app.ts
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:

@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​

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:

app.ts
// 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:

app.ts
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 the authorize() 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​

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.