@rs-tech-hub/nestjs-auth-core

Core authentication infrastructure for NestJS applications. Provides JWT-based authentication, guards, decorators, and strategies for both REST and GraphQL endpoints with support for access/refresh tokens and service-to-service authentication.


📚 Table of Contents


🔑 License

This package requires a valid commercial license. A valid license key must be configured to use this package.

Visit https://rstechhub.gumroad.com to purchase a license.

✨ Features

  • 🔐 JWT-based authentication (access & refresh tokens)
  • 🛡️ Authentication guards for REST and GraphQL
  • 🎯 Parameter decorators for user data extraction
  • 🔓 Public route support with @Public() decorator
  • 🔄 Refresh token strategy and guard
  • 🔧 Basic authentication for admin/internal tools
  • 🌐 Service-to-service authentication
  • 📊 Works seamlessly with both REST and GraphQL

📋 Prerequisites

  • Node.js >= 18
  • TypeScript >= 5.1.0
  • NestJS >= 11.1.6
  • Prisma ORM v7.0+ (for user data)

🚀 Quick Start

Installation

# npm
npm install @rs-tech-hub/nestjs-auth-core \
  @rs-tech-hub/nestjs-prisma \
  @nestjs/jwt \
  @nestjs/passport \
  @nestjs/config \
  passport-jwt \
  express-basic-auth

# yarn
yarn add @rs-tech-hub/nestjs-auth-core \
  @rs-tech-hub/nestjs-prisma \
  @nestjs/jwt \
  @nestjs/passport \
  @nestjs/config \
  passport-jwt \
  express-basic-auth

# pnpm
pnpm add @rs-tech-hub/nestjs-auth-core \
  @rs-tech-hub/nestjs-prisma \
  @nestjs/jwt \
  @nestjs/passport \
  @nestjs/config \
  passport-jwt \
  express-basic-auth

Environment Variables

# JWT Configuration
JWT_SECRET=your-secret-key-here
JWT_REFRESH_SECRET=your-refresh-secret-here

# Optional: Basic Auth for admin endpoints
BASIC_AUTH_ERROR_USERNAME=admin
BASIC_AUTH_ERROR_PASSWORD=secure-password

# Optional: Service-to-service auth
SERVICE_TOKEN=internal-service-token

Module Setup

import { Module } from "@nestjs/common";
import { ConfigModule } from "@nestjs/config";
import {
  JwtGlobalModule,
  PassportGlobalModule,
} from "@rs-tech-hub/nestjs-auth-core";

@Module({
  imports: [ConfigModule.forRoot(), PassportGlobalModule, JwtGlobalModule],
})
export class AppModule {}

🔧 Usage

REST API Authentication

import { Controller, Get, Post, Body, UseGuards } from "@nestjs/common";
import {
  AuthGuard,
  CurrentUser,
  CurrentUserId,
  Public,
  AuthenticatedUser,
} from "@rs-tech-hub/nestjs-auth-core";

@Controller("users")
@UseGuards(AuthGuard)
export class UsersController {
  @Get("me")
  async getCurrentUser(@CurrentUser() user: AuthenticatedUser) {
    return { id: user.sub, email: user.email, role: user.role };
  }

  @Get("profile")
  async getProfile(@CurrentUserId() userId: string) {
    return this.userService.findById(userId);
  }

  @Public()
  @Post("register")
  async register(@Body() dto: RegisterDto) {
    return this.authService.register(dto);
  }
}

GraphQL Authentication

import { Resolver, Query, Mutation, Args, UseGuards } from "@nestjs/graphql";
import {
  GqlAuthGuard,
  CurrentUser,
  Public,
  AuthenticatedUser,
} from "@rs-tech-hub/nestjs-auth-core";

@Resolver()
@UseGuards(GqlAuthGuard)
export class UserResolver {
  @Query(() => User)
  async me(@CurrentUser() user: AuthenticatedUser) {
    return this.userService.findById(user.sub);
  }

  @Public()
  @Query(() => String)
  async health() {
    return "OK";
  }

  @Mutation(() => AuthResponse)
  async login(
    @Args("email") email: string,
    @Args("password") password: string
  ) {
    return this.authService.login(email, password);
  }
}

Refresh Token Flow

import { Controller, Post, UseGuards } from "@nestjs/common";
import {
  JwtRefreshGuard,
  RefreshToken,
  CurrentUserId,
} from "@rs-tech-hub/nestjs-auth-core";

@Controller("auth")
export class AuthController {
  @Post("refresh")
  @UseGuards(JwtRefreshGuard)
  async refresh(
    @RefreshToken() refreshToken: string,
    @CurrentUserId() userId: string
  ) {
    return this.authService.refreshAccessToken(refreshToken, userId);
  }
}

Basic Authentication (Admin/Internal)

import { Controller, Get, UseGuards } from "@nestjs/common";
import { BasicAuthGuard } from "@rs-tech-hub/nestjs-auth-core";

@Controller("admin")
@UseGuards(BasicAuthGuard)
export class AdminController {
  @Get("dashboard")
  async getDashboard() {
    return { message: "Admin Dashboard" };
  }
}

Service-to-Service Authentication

import { Controller, Post, UseGuards } from "@nestjs/common";
import { ServiceAuthGuard } from "@rs-tech-hub/nestjs-auth-core";

@Controller("internal")
@UseGuards(ServiceAuthGuard)
export class InternalController {
  @Post("sync")
  async syncData() {
    // Only accessible with valid SERVICE_TOKEN header
    return this.dataService.sync();
  }
}

📖 API Reference

Guards

AuthGuard

JWT authentication guard for REST endpoints.

@Controller("api")
@UseGuards(AuthGuard)
export class ApiController {}

GqlAuthGuard

JWT authentication guard for GraphQL resolvers.

@Resolver()
@UseGuards(GqlAuthGuard)
export class UserResolver {}

JwtRefreshGuard

Guard for refresh token validation.

@Post('refresh')
@UseGuards(JwtRefreshGuard)
async refresh(@RefreshToken() token: string) {}

BasicAuthGuard

HTTP Basic authentication guard (username/password).

@Controller("admin")
@UseGuards(BasicAuthGuard)
export class AdminController {}

ServiceAuthGuard

Service-to-service authentication using shared token.

@Controller("internal")
@UseGuards(ServiceAuthGuard)
export class InternalController {}

Decorators

@Public()

Marks routes/resolvers as public (no authentication required).

@Public()
@Get('status')
async getStatus() {
  return { status: 'ok' };
}

@CurrentUser()

Extracts the authenticated user object from the request.

async getProfile(@CurrentUser() user: AuthenticatedUser) {
  return user; // { sub, email, role, iat, exp }
}

@CurrentUserId()

Extracts only the user ID from the authenticated user.

async getMyData(@CurrentUserId() userId: string) {
  return this.service.findByUserId(userId);
}

@RefreshToken()

Extracts the refresh token from cookies or headers.

async refresh(@RefreshToken() token: string) {
  return this.authService.refreshAccessToken(token);
}

📝 Interfaces

AuthenticatedUser

interface AuthenticatedUser {
  sub: string; // User ID
  email: string; // User email
  role: string; // User role(s)
  iat?: number; // Issued at (Unix timestamp)
  exp?: number; // Expires at (Unix timestamp)
}

JwtPayload

interface JwtPayload {
  sub: string; // User ID
  email: string; // User email
  role: string; // User role(s)
  iat?: number; // Issued at
  exp?: number; // Expires at
}

🔄 Complete Authentication Flow

import { Injectable } from "@nestjs/common";
import { JwtService } from "@nestjs/jwt";

@Injectable()
export class AuthService {
  constructor(private jwtService: JwtService) {}

  async login(email: string, password: string) {
    // 1. Validate credentials
    const user = await this.validateUser(email, password);

    // 2. Generate tokens
    const payload = { sub: user.id, email: user.email, role: user.role };

    return {
      accessToken: this.jwtService.sign(payload),
      refreshToken: this.jwtService.sign(payload, {
        secret: process.env.JWT_REFRESH_SECRET,
        expiresIn: "7d",
      }),
    };
  }

  async refreshAccessToken(refreshToken: string) {
    // Verify refresh token and issue new access token
    const payload = this.jwtService.verify(refreshToken, {
      secret: process.env.JWT_REFRESH_SECRET,
    });

    return {
      accessToken: this.jwtService.sign({
        sub: payload.sub,
        email: payload.email,
        role: payload.role,
      }),
    };
  }
}

⚠️ Error Codes

Error CodeDescription
auth-error:invalid-credentialsInvalid username or password
auth-error:no-token-providedNo authentication token provided
auth-error:invalid-tokenToken is invalid or malformed
auth-error:expired-tokenToken has expired
auth-error:user-not-foundUser does not exist
auth-error:user-inactiveUser account is inactive
auth-error:user-not-verifiedUser email not verified
auth-error:service-not-configuredService authentication not configured

💡 Best Practices

  1. Use appropriate guards: AuthGuard for REST, GqlAuthGuard for GraphQL
  2. Mark public routes: Always use @Public() for unauthenticated endpoints
  3. Secure secrets: Use strong, unique values for JWT_SECRET and JWT_REFRESH_SECRET
  4. Token expiration: Keep access tokens short-lived (15min-1hr), refresh tokens longer (7d)
  5. Role-based access: Use the role field in AuthenticatedUser for authorization
  6. Refresh tokens: Store refresh tokens securely (httpOnly cookies recommended)

📄 License

This package requires a valid commercial license. See LICENSE.txt for details. By using this software, you agree to the terms outlined in the Software License Agreement (SLA.md). The license grants you specific rights to use, modify, and deploy the software within the scope defined in the agreement. For full terms, conditions, and restrictions, please refer to the Software License Agreement.

📧 Support

For technical support and inquiries: