npm package: @relab/nestjs-auth
Description: Auth helpers for Nest.js
Author: Sergey Zwezdin
Latest version: 1.2.0

# @relab/nestjs-auth

Authentication and authorization helpers for NestJS (Fastify) applications. Provides decorators and guards for JWT authentication and role-based access control, with support for extracting the current user from requests.

## Features

- **BaseAuth**: Factory for creating a project-specific `Auth` decorator for JWT authentication and role-based access control.
- **Auth**: (Recommended) Your own pre-configured decorator for authentication and authorization, created using `BaseAuth`.
- **CurrentUser**: Parameter decorator to access the current authenticated user from the request.
- **JwtGuard**: Guard for JWT authentication, compatible with Fastify and GraphQL.
- **createRolesGuard**: Factory for creating custom role guards.
- **SocketAuth**: Middleware for authenticating Socket.IO connections using JWT tokens from headers or cookies.

## Installation

```bash
pnpm add @relab/nestjs-auth
# or
yarn add @relab/nestjs-auth
# or
npm install @relab/nestjs-auth
```

> **Note:** This package is designed for use with [NestJS](https://nestjs.com/) and [Fastify](https://www.fastify.io/). Make sure you have `@nestjs/common`, `@nestjs/core`, `@nestjs/passport`, `@nestjs/graphql`, `fastify`, and `rxjs` installed as peer dependencies.

## Usage

### Creating a Project-wide Auth Decorator

For better type safety and convenience, you can create a project-specific `Auth` decorator using the `BaseAuth` factory. This allows you to define your user and role types once and use the `Auth` decorator throughout your application:

```typescript
// auth.decorator.ts
import { BaseAuth } from '@relab/nestjs-auth';
import { Role } from './role.enum';
import { CurrentUserDto } from './current-user.dto';

export const Auth = BaseAuth<Role, CurrentUserDto>(user => user?.role);
```

You can now use your custom `Auth` decorator in controllers:

```typescript
import { Controller, Get } from '@nestjs/common';
import { Auth, CurrentUser } from './auth.decorator';
import { CurrentUserDto } from './current-user.dto';

@Controller('profile')
export class ProfileController {
  // JWT authentication only
  @Get('me')
  @Auth()
  getMe(@CurrentUser() user: CurrentUserDto) {
    return user;
  }

  // JWT authentication + role-based access
  @Get('admin')
  @Auth('admin')
  getAdminData(@CurrentUser() user: CurrentUserDto) {
    return { admin: true, user };
  }
}
```

### Custom Role Guard

You can create a custom roles guard using `createRolesGuard` if you need advanced role resolution logic:

```typescript
import { createRolesGuard } from '@relab/nestjs-auth';
import { UseGuards } from '@nestjs/common';

const MyRolesGuard = createRolesGuard((user) => user?.role);

@UseGuards(MyRolesGuard)
class SomeController {}
```

#### Example: Using `SocketAuth` in a NestJS Gateway

For a more idiomatic NestJS approach, you can use `SocketAuth` directly in your WebSocket gateway:

```typescript
import { WebSocketGateway, WebSocketServer, OnGatewayInit, OnGatewayConnection, OnGatewayDisconnect } from '@nestjs/websockets';
import { Server, Socket } from 'socket.io';
import { JwtService } from '@nestjs/jwt';
import { SocketAuth } from '@relab/nestjs-auth';

@WebSocketGateway()
export class WebsocketsGateway implements OnGatewayInit<Server>, OnGatewayConnection<Socket>, OnGatewayDisconnect<Socket> {
  @WebSocketServer()
  server: Server;

  constructor(private readonly jwtService: JwtService) {}

  afterInit(server: Server) {
    server.use(SocketAuth(this.jwtService));
  }

  handleConnection(client: Socket) {
    // Access the authenticated user:
    const user = client.data.user;
    // ...
  }

  handleDisconnect(client: Socket) {
    // ...
  }
}
```

This approach ensures that all incoming socket connections are authenticated using JWT, and the user payload is available on `client.data.user` in your gateway handlers.

## API Reference

### `BaseAuth(resolveRole: (user: TUser | undefined) => TRole | undefined)`
- Factory function to create a project-specific `Auth` decorator.
- Returns a decorator: `(...roles: TRole[]) => MethodDecorator & ClassDecorator`.
- If roles are provided, only users with matching roles can access the route.
- `resolveRole` is a function to extract the role from the user object.

### `Auth(...roles: TRole[])`
- Your project-specific decorator, created using `BaseAuth`.
- Use with or without roles for authentication and authorization.

### `CurrentUser()`
- Parameter decorator to access the current authenticated user from the request.
- Returns `undefined` if no user is present.

### `JwtGuard`
- Guard for JWT authentication, compatible with Fastify and GraphQL.
- Can be used directly with `@UseGuards(JwtGuard)`.

### `createRolesGuard(resolveRole)`
- Factory function to create a custom role guard.
- `resolveRole` is a function to extract the role from the user object.

### `SocketAuth(jwtService)`
- Middleware for authenticating Socket.IO connections using JWT.
- Accepts a `JwtService` instance.
- Checks for a JWT token in the `Authorization` header (as `Bearer <token>`) or in a cookie named `access_token`.
- On success, attaches the decoded user to `socket.data.user`. Calls `next()` on success, or passes an `UnauthorizedException` to `next()` on failure.

## License

MIT