> ## Documentation Index
> Fetch the complete documentation index at: https://docs.socket.fi/llms.txt
> Use this file to discover all available pages before exploring further.

# SocketFi Auth Middleware — Express, Fastify, NestJS

> Build reusable authentication middleware with verifyAuth(). Complete examples for Express, Fastify, and NestJS with TypeScript type extensions.

Rather than calling `verifyAuth()` directly inside every route handler, the recommended pattern is to extract the verification logic into reusable middleware. This keeps your route handlers focused on business logic and ensures that no protected route accidentally skips token verification. The examples below show how to build auth middleware for Express, Fastify, and NestJS, including how to attach the verified user and wallet to the request object so downstream handlers can use them without re-verifying.

## TypeScript: extending the request type

Before writing middleware, extend the framework's request type so TypeScript knows about the `auth` property your middleware attaches:

```typescript theme={null}
// src/types/express.d.ts
import { VerifyAuthResult } from '@socketfi/server';

declare global {
  namespace Express {
    interface Request {
      auth?: VerifyAuthResult & { valid: true };
    }
  }
}
```

This gives you full type-safety when accessing `req.auth.user.id` or `req.auth.wallet.address` inside route handlers.

## Express middleware

The following `authMiddleware` function reads the token from the `Authorization` header, calls `verifyAuth()`, and either attaches the result to `req.auth` and calls `next()`, or responds immediately with a `401`:

```typescript theme={null}
import { Request, Response, NextFunction } from 'express';
import { verifyAuth } from '@socketfi/server';

export async function authMiddleware(
  req: Request,
  res: Response,
  next: NextFunction
): Promise<void> {
  const token = req.headers.authorization?.replace('Bearer ', '');

  if (!token) {
    res.status(401).json({ error: 'Unauthorized' });
    return;
  }

  const auth = await verifyAuth(token);

  if (!auth.valid) {
    res.status(401).json({ error: auth.error.code });
    return;
  }

  // Attach verified identity to the request for downstream handlers
  req.auth = auth;
  next();
}
```

### Protected Express routes

Apply `authMiddleware` to any route that requires authentication:

```typescript theme={null}
import express from 'express';
import { authMiddleware } from './middleware/auth';

const app = express();

// Single protected route
app.get('/profile', authMiddleware, async (req, res) => {
  res.json({
    userId: req.auth!.user.id,
    walletAddress: req.auth!.wallet.address,
  });
});

// Apply middleware to all routes under /api
const api = express.Router();
api.use(authMiddleware);

api.get('/balance', async (req, res) => {
  const { address } = req.auth!.wallet;
  const balance = await fetchBalance(address);
  res.json({ balance });
});

api.post('/transfer', async (req, res) => {
  const { id: userId } = req.auth!.user;
  // ... handle transfer
});

app.use('/api', api);
```

## Fastify preHandler

In Fastify, use a `preHandler` hook to run verification before each request reaches its handler. You can register it globally or on a specific route:

```typescript theme={null}
import Fastify from 'fastify';
import { verifyAuth } from '@socketfi/server';

const fastify = Fastify();

// Augment Fastify's request type
declare module 'fastify' {
  interface FastifyRequest {
    auth?: Awaited<ReturnType<typeof verifyAuth>> & { valid: true };
  }
}

// Global preHandler — runs on every registered route
fastify.addHook('preHandler', async (request, reply) => {
  const token = request.headers.authorization?.replace('Bearer ', '');

  if (!token) {
    return reply.status(401).send({ error: 'Unauthorized' });
  }

  const auth = await verifyAuth(token);

  if (!auth.valid) {
    return reply.status(401).send({ error: auth.error.code });
  }

  request.auth = auth;
});
```

### Protected Fastify routes

```typescript theme={null}
fastify.get('/profile', async (request, reply) => {
  return {
    userId: request.auth!.user.id,
    walletAddress: request.auth!.wallet.address,
  };
});

fastify.post('/transfer', async (request, reply) => {
  const { id: userId } = request.auth!.user;
  // ... handle transfer
  return { success: true };
});
```

<Note>
  If you only want to protect specific routes rather than every route, register the preHandler at the route level instead of with `addHook`: `fastify.get('/protected', { preHandler: authPreHandler }, handler)`.
</Note>

## NestJS Guard

In NestJS, implement authentication as a Guard that uses `CanActivate`. The guard runs before the route handler and throws `UnauthorizedException` if the token is invalid:

```typescript theme={null}
// src/auth/socketfi.guard.ts
import {
  Injectable,
  CanActivate,
  ExecutionContext,
  UnauthorizedException,
} from '@nestjs/common';
import { verifyAuth } from '@socketfi/server';

@Injectable()
export class SocketFiGuard implements CanActivate {
  async canActivate(context: ExecutionContext): Promise<boolean> {
    const request = context.switchToHttp().getRequest();
    const token = request.headers.authorization?.replace('Bearer ', '');

    if (!token) {
      throw new UnauthorizedException('Missing token');
    }

    const auth = await verifyAuth(token);

    if (!auth.valid) {
      throw new UnauthorizedException(auth.error.code);
    }

    // Attach verified identity so controllers can access it
    request.auth = auth;
    return true;
  }
}
```

### Protected NestJS routes

Apply `SocketFiGuard` with the `@UseGuards()` decorator at the controller or method level:

```typescript theme={null}
// src/profile/profile.controller.ts
import { Controller, Get, Req, UseGuards } from '@nestjs/common';
import { SocketFiGuard } from '../auth/socketfi.guard';
import { Request } from 'express';

@Controller('profile')
@UseGuards(SocketFiGuard) // Protects all routes in this controller
export class ProfileController {
  @Get()
  getProfile(@Req() req: Request) {
    return {
      userId: req['auth'].user.id,
      walletAddress: req['auth'].wallet.address,
    };
  }
}
```

To protect all routes in your entire application, register `SocketFiGuard` as a global guard in your `AppModule`:

```typescript theme={null}
// src/app.module.ts
import { Module } from '@nestjs/common';
import { APP_GUARD } from '@nestjs/core';
import { SocketFiGuard } from './auth/socketfi.guard';

@Module({
  providers: [
    {
      provide: APP_GUARD,
      useClass: SocketFiGuard,
    },
  ],
})
export class AppModule {}
```

## Accessing user and wallet info in handlers

Regardless of framework, once middleware attaches the `auth` object to the request, your handlers can read the verified identity without any additional SDK calls:

```typescript theme={null}
// Available after middleware runs:
const userId        = req.auth.user.id;        // e.g. "usr_01hx..."
const walletAddress = req.auth.wallet.address; // e.g. "GDZX..."

// Common pattern — look up the user in your own database
const account = await db.accounts.findOne({ socketfiId: userId });
```

<Warning>
  Never skip the middleware on routes that access user data or perform wallet operations. A missing `Authorization` header is not the same as an unauthenticated user — always handle the `!token` case explicitly and return a `401` before calling `verifyAuth()`.
</Warning>
