Skip to main content

Node.js

Official

Server-side SDK for verifying tokens and securing Node.js services.

Protecting Routes

~6 min

This guide shows how to restrict access to routes in a Node.js server-side application based on authentication state. You will create reusable middleware that checks whether the current user has an active session before allowing access to protected resources.

Protecting Routes

1

Prerequisites

- Complete the [Handling Authentication](../handling-authentication) guide to set up the authentication client and session cookie.

2

How It Works

The `isSignedIn` method checks whether the user's session exists and is still valid. If the access token has expired but a refresh token exists, the SDK automatically refreshes the token before returning the result. Use this method in a middleware function to gate access to protected routes.

3

Create an Authentication Middleware

src/middleware/requireAuth.ts
ts

export async function requireAuth(
  req: Request,
  res: Response,
  next: NextFunction,
): Promise<void> {
  const sessionId = req.cookies[CookieConfig.SESSION_COOKIE_NAME]

  if (!sessionId) {
    res.redirect('/sign-in')
    return
  }

  const signedIn = await auth.isSignedIn(sessionId)

  if (!signedIn) {
    res.redirect('/sign-in')
    return
  }

  next()
}
4

Apply Middleware to Routes

### Protect Individual Routes Apply the middleware to specific routes that require authentication.

src/routes/dashboard.ts
ts

app.get('/dashboard', requireAuth, (req, res) => {
  res.render('dashboard')
})

app.get('/profile', requireAuth, async (req, res) => {
  const sessionId = req.cookies[CookieConfig.SESSION_COOKIE_NAME]
  const user = await auth.getUser(sessionId)
  res.render('profile', { user })
})
5

Attach User Data to the Request

Extend the request object to carry user information, so protected route handlers can access it without fetching it again.

src/middleware/requireAuth.ts
ts

declare global {
  namespace Express {
    interface Request {
      user?: User
    }
  }
}

export async function requireAuth(
  req: Request,
  res: Response,
  next: NextFunction,
): Promise<void> {
  const sessionId = req.cookies[CookieConfig.SESSION_COOKIE_NAME]

  if (!sessionId) {
    res.redirect('/sign-in')
    return
  }

  const signedIn = await auth.isSignedIn(sessionId)

  if (!signedIn) {
    res.redirect('/sign-in')
    return
  }

  req.user = await auth.getUser(sessionId)

  next()
}
6

Handle Token Refresh Failures

The `isSignedIn` method attempts to refresh an expired access token automatically. If the refresh fails (for example, the refresh token has also expired), it returns `false`. The middleware handles this by redirecting to the sign-in route. To distinguish an expired session from a network failure, you can catch errors explicitly:

src/middleware/requireAuth.ts
ts
export async function requireAuth(
  req: Request,
  res: Response,
  next: NextFunction,
): Promise<void> {
  const sessionId = req.cookies[CookieConfig.SESSION_COOKIE_NAME]

  if (!sessionId) {
    res.redirect('/sign-in')
    return
  }

  try {
    const signedIn = await auth.isSignedIn(sessionId)

    if (!signedIn) {
      res.clearCookie(CookieConfig.SESSION_COOKIE_NAME)
      res.redirect('/sign-in')
      return
    }
  } catch (error) {
    res.status(500).send('Authentication check failed.')
    return
  }

  next()
}
7

Next Steps

- [Accessing Protected APIs](../accessing-protected-apis): Use the access token to call downstream services

ThunderID LogoThunderID Logo

Product

DocsAPIsSDKs
© Copyright Linux Foundation Europe.For web site terms of use, trademark policy and other project policies please see https://linuxfoundation.eu/en/policies.