RiserBob logoRiserBobv1.0.0
HomeDocsCLIRelease notes

Getting started

  • Introduction
  • Installation
  • Quick start
  • Project structure

Core concepts

  • Routing
  • Request
  • Responses
  • Error handling

Middleware

  • Middleware
  • Authentication
  • Logger and CORS

Data

  • Validation

Structure and tooling

  • Modules
  • CLI

Examples

  • Build a project
  • Mongoose
  • Drizzle ORM
  • Sequelize
  • JWT and cookies
  • File uploads

Packages

  • Cookies

Resources

  • Troubleshooting
  • Release notes
  • License
  • Security
  • Contributing
Middleware

Authentication

Protect routes with AuthMiddleware, your own token verifier and a cookie, a Bearer header or both.

AuthMiddleware reads a token from the request and asks your verifier whether it is valid. RiserBob does not decide what a token is, so you can use JWTs, session ids or anything else.

Protect a route

TypeScript
import { AuthMiddleware } from 'riser-bob' const auth = new AuthMiddleware(async (token) => {  // Return the user for a valid token, or null for an invalid one.  const payload = await verifyMyToken(token)   return payload ? { id: payload.userId, role: payload.role } : null}) bob.spongGet(  '/me',  async (spongReq, spongRes) => {    return spongRes.json({ user: spongReq.user })  },  auth.middleware)

On success the middleware sets spongReq.user and spongReq.auth, then continues the chain.

Where the token comes from

The second constructor argument chooses the source of the token.

TypeScript
new AuthMiddleware(verifier, {  mode: 'cookie', // 'cookie' | 'bearer' | 'both'  cookieName: 'token', // default: 'token'})
ModeReads the token from
'bearer'The Authorization: Bearer <token> header only.
'cookie'The cookie named cookieName only.
'both' (default)The Authorization header when it is present, otherwise the cookie.
  • The Bearer scheme is matched without regard to case.
  • In 'both' mode, a request that has an Authorization header is judged by that header alone. If it is not a valid Bearer <token>, the answer is 401 and the cookie is not tried.
  • The cookie is read with a plain get. If you set it with setSigned, verify the signature in your own code.

Browser apps usually use mode: 'cookie' with an httpOnly cookie, because JavaScript on the page cannot read it. Mobile apps and other APIs usually use mode: 'bearer'. See JWT and cookies for a complete cookie flow.

What the client sees

SituationResponse
No token, or a malformed Authorization header401 with { success: false, message: 'Authentication token is missing or invalid.' }
The verifier returns null or undefined401 with { success: false, message: 'Token is invalid or expired.' }
The verifier throwsLogged on the server, then handled by the central error handler: an HttpError keeps its status, anything else becomes 500.

The token verifier

TypeScript
type VerifiedUser = { id: string; [key: string]: unknown } type TokenVerifier = (  token: string) => Promise<VerifiedUser | null> | VerifiedUser | null

Whatever your verifier returns is stored on spongReq.user, so it must have an id. Add anything else you want handlers to read, such as a role. Return null to reject the token.

Return null for a bad token instead of throwing. Throwing is for real failures, such as a missing secret, and ends as a 500.

Read the user in a handler

TypeScript
readonly me: SpongHandler = async (spongReq, spongRes) => {  const authUser = spongReq.user   if (!authUser) {    return spongRes.SpongUnauthorized({ success: false, message: "Not authenticated" })  }   return spongRes.SpongOK({ success: true, data: { id: authUser.id } })}

The middleware already rejects requests without a user, but TypeScript still sees spongReq.user as optional, so the check keeps the types honest.

In a module

In a generated module the controller owns verifyToken, and the module hands it to AuthMiddleware. See Modules.

A generated controller returns null from verifyToken until you implement it, so every protected route answers 401. That is expected. See Troubleshooting.
PreviousMiddlewareNextLogger and CORS

On this page

  • Protect a route
  • Where the token comes from
  • What the client sees
  • The token verifier
  • Read the user in a handler
  • In a module