Skip to main content

@auth/express

warning

@auth/express is currently experimental. The API will change in the future.

Express Auth is the official Express integration for Auth.js. It provides a simple way to add authentication to your Express app in a few lines of code.

Installation​

npm install @auth/express

Usage​

src/routes/auth.route.ts
import { ExpressAuth } from "@auth/express"
import GitHub from "@auth/express/providers/github"
import express from "express"

const app = express()

// If app is served through a proxy, trust the proxy to allow HTTPS protocol to be detected
// https://expressjs.com/en/guide/behind-proxies.html
app.set('trust proxy', true)
app.use("/auth/*", ExpressAuth({ providers: [ GitHub ] }))

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 ExpressAuth 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 Express with a template engine (e.g EJS, Pug), you can make the session data available to all routes via middleware as follows

app.ts
import { getSession } from "@auth/express"

export function authSession(req: Request, res: Response, next: NextFunction) {
res.locals.session = await getSession(req)
next()
}

app.use(authSession)

// Now in your route
app.get("/", (req, res) => {
const { session } = res.locals
res.render("index", { user: session?.user })
})

Authorization​

You can protect routes by checking for the presence of a session and then redirect to a login page if the session is not present. This can either be done per route, or for a group of routes using a middleware such as the following:

export async function authenticatedUser(
req: Request,
res: Response,
next: NextFunction
) {
const session = res.locals.session ?? (await getSession(req, authConfig))
if (!session?.user) {
res.redirect("/login")
} else {
next()
}
}

Per Route​

To protect a single route, simply add the middleware to the route as follows:

app.ts
// This route is protected
app.get("/profile", authenticatedUser, (req, res) => {
const { session } = res.locals
res.render("profile", { user: session?.user })
})

// This route is not protected
app.get("/", (req, res) => {
res.render("index")
})

app.use("/", root)

Per Group of Routes​

To protect a group of routes, define a router and add the middleware to the router as follows:

routes/protected.route.ts
import { Router } from "express"

const router = Router()

router.use(authenticatedUser) // All routes defined after this will be protected

router.get("/", (req, res) => {
res.render("protected")
})

export default router

Then we mount the router as follows:

app.ts
import protected from "./routes/protected.route"

app.use("/protected", 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.


AuthError​

Base error class for all Auth.js errors. It's optimized to be printed in the server logs in a nicely formatted way via the logger.error option.

Extends​

  • Error

Properties​

type​

type: ErrorType;

The error type. Used to identify the error in the logs.


CredentialsSignin​

Can be thrown from the authorize callback of the Credentials provider. When an error occurs during the authorize callback, two things can happen:

  1. The user is redirected to the signin page, with error=CredentialsSignin&code=credentials in the URL. code is configurable.
  2. If you throw this error in a framework that handles form actions server-side, this error is thrown, instead of redirecting the user, so you'll need to handle.

Extends​

  • SignInError

Properties​

code​

code: string;

The error code that is set in the code query parameter of the redirect URL.

⚠ NOTE: This property is going to be included in the URL, so make sure it does not hint at sensitive errors.

The full error is always logged on the server, if you need to debug.

Generally, we don't recommend hinting specifically if the user had either a wrong username or password specifically, try rather something like "Invalid credentials".

type​

type: ErrorType;

The error type. Used to identify the error in the logs.

Inherited from​

SignInError.type