DEV Community

Cover image for Building Secure Multi-App Authentication with rugi-auth: A Complete Guide
edmondgi
edmondgi

Posted on

Building Secure Multi-App Authentication with rugi-auth: A Complete Guide

Centralized authentication that scales across your entire application ecosystem

Introduction

In today's microservices and multi-application architectures, managing authentication can become a nightmare.
Each service needs to verify users, handle tokens, manage roles, and maintain security-often duplicating logic across multiple codebases. What if you could centralize all of this into a single, secure, battle-tested authentication service?

Enter rugi-auth: a production-ready, centralized authentication service built with TypeScript, Express, and Prisma.
It provides enterprise-grade security features while remaining simple to integrate and deploy.

What is rugi-auth?

rugi-auth is a secure, centralized authentication service designed for modern application architectures.
It enables a single user identity to work seamlessly across multiple applications while maintaining granular, app-specific role management.
Think of it as your own Auth0 or Okta, but open-source and fully customizable.

Core Philosophy

  • Centralized Identity: One user account works across all your applications
  • Security First: Built with industry-standard security practices from day one
  • Developer Friendly: Simple integration, comprehensive documentation, and TypeScript support
  • Production Ready: Battle-tested features like rate limiting, audit logging, and token rotation

Key Features

1. Multi-App Architecture

Unlike traditional auth systems that tie users to a single application, rugi-auth supports multiple applications (clients) with a shared user base. Each user can have different roles in different applications:

User: john@example.com
├── E-commerce App    → roles: ['customer', 'reviewer']
├── Admin Dashboard   → roles: ['admin']
└── Content Platform  → roles: ['author', 'editor']
Enter fullscreen mode Exit fullscreen mode

This architecture is perfect for:

  • SaaS platforms with multiple products
  • Microservices architectures
  • Organizations with separate internal and customer-facing apps
  • White-label solutions

2. Multiple Authentication Methods

rugi-auth supports various authentication methods, all configurable per application:

  • Email + Password: Traditional authentication with secure password hashing
  • Email + OTP: Passwordless authentication via one-time passwords
  • OAuth Providers: Google, GitHub, Microsoft, and Facebook (with more coming)
  • Custom Methods: Extensible architecture for adding new providers

Each application can enable or disable specific authentication methods based on their needs.

3. App-Specific Role Management

Roles are scoped to applications, meaning a user can be an "admin" in one app and a "user" in another.

This provides:

  • Granular Permissions: Fine-grained access control per application
  • Security Isolation: Roles in one app don't affect another
  • Flexible Management: Assign roles programmatically or via API

4. JWT with RS256 and JWKS

rugi-auth uses industry-standard JWT tokens signed with RSA-256:

  • RS256 Algorithm: Asymmetric encryption ensures tokens can be verified without exposing secrets
  • JWKS Endpoint: Public keys are exposed via /.well-known/jwks.json for easy token verification
  • Key Rotation: Support for key rotation without service downtime
  • Stateless Verification: Consumer applications verify tokens without database lookups

5. Refresh Token Rotation

For enhanced security, refresh tokens are rotated on every use:

// First refresh
POST /refresh
{ refresh_token: "old-token" }
 { access_token: "...", refresh_token: "new-token-1" }

// Second refresh (old token is now invalid)
POST /refresh
{ refresh_token: "new-token-1" }
 { access_token: "...", refresh_token: "new-token-2" }
Enter fullscreen mode Exit fullscreen mode

This prevents token reuse attacks and ensures compromised tokens become useless quickly.

6. Comprehensive Audit Logging

Every authentication event is logged for security auditing:

  • User registrations
  • Login attempts (successful and failed)
  • Token refreshes
  • Role assignments
  • Password reset requests
  • OTP requests and usage

This provides complete visibility into authentication activities for compliance and security monitoring.


Use Cases

1. Microservices Architecture

In a microservices setup, each service needs to verify user identity. With rugi-auth, services can verify JWT tokens independently without sharing databases or secrets:

// In your microservice
import { createAuthMiddleware } from 'rugi-auth/client';

const auth = createAuthMiddleware({
  jwksUri: 'https://auth.example.com/.well-known/jwks.json',
  issuer: 'rugi-auth',
  audience: 'your-service-id',
});

app.get('/api/orders', auth, (req, res) => {
  // req.user is automatically populated
  const orders = getOrdersForUser(req.user.userId);
  res.json({ orders });
});
Enter fullscreen mode Exit fullscreen mode

Benefits:

  • No shared database between services
  • Stateless token verification
  • Independent service scaling
  • Centralized user management

2. Multi-Product SaaS Platform

If you're building a SaaS platform with multiple products (e.g., a CRM, an analytics dashboard, and a marketing tool), rugi-auth enables:

  • Single sign-on across all products
  • Product-specific roles and permissions
  • Unified user management
  • Centralized billing and subscription tracking

3. White-Label Solutions

For white-label applications where you need to support multiple client organizations:

  • Each client gets their own application instance
  • Users can have different roles per client
  • Centralized authentication reduces operational overhead
  • Easy onboarding of new clients

4. Enterprise Applications

Large organizations often have multiple internal tools:

  • HR systems
  • Project management tools
  • Internal dashboards
  • Customer-facing applications

rugi-auth provides a single identity provider for all these systems while maintaining appropriate access controls.

5. API Gateway Authentication

Use rugi-auth as the authentication layer for your API gateway:

  • All API requests are authenticated via JWT
  • Gateway verifies tokens using JWKS
  • Backend services receive validated user context
  • Centralized token management

Benefits

1. Reduced Development Time

Instead of implementing authentication in every application, you set it up once:

  • No repeated code: Authentication logic lives in one place
  • Faster feature development: Focus on business logic, not auth
  • Consistent behavior: All apps use the same authentication flow
  • Easy updates: Security improvements benefit all applications

2. Enhanced Security

rugi-auth implements security best practices out of the box:

  • Argon2id Password Hashing: Memory-hard algorithm resistant to GPU attacks
  • Rate Limiting: Redis-backed distributed rate limiting prevents brute force attacks
  • Timing Attack Protection: Constant-time operations prevent user enumeration
  • Token Rotation: Refresh tokens rotate on use, limiting attack windows
  • Audit Logging: Complete visibility into authentication events

3. Scalability

Designed for scale:

  • Stateless Tokens: No database lookups for token verification
  • Redis Rate Limiting: Distributed rate limiting across multiple instances
  • Horizontal Scaling: Run multiple instances behind a load balancer
  • Database Optimization: Efficient queries with proper indexing

4. Developer Experience

Built with developers in mind:

  • TypeScript Support: Full type safety and IntelliSense
  • Lightweight Client: Consumer apps only need 2 dependencies (jsonwebtoken, jwks-rsa)
  • Comprehensive Documentation: Integration guides, API references, and examples
  • CLI Tools: Scaffold projects, generate keys, create superadmins
  • Swagger UI: Interactive API documentation at /docs

5. Flexibility

Highly configurable to fit your needs:

  • Per-App Settings: Enable/disable authentication methods per application
  • Custom Roles: Define roles specific to each application
  • Email Configuration: Customize email templates and SMTP settings per app
  • OAuth Providers: Enable Google, GitHub, Microsoft, or Facebook per app

6. Cost Efficiency

Open-source alternative to commercial solutions:

  • No Per-User Fees: Unlike Auth0 or Okta, no cost per user
  • Self-Hosted: Full control over infrastructure and data
  • No Vendor Lock-in: Your data, your rules
  • Customizable: Modify to fit your exact requirements

Security Measures

Security is at the core of rugi-auth. Here's a deep dive into the security measures implemented:

1. Password Security

Argon2id Hashing

rugi-auth uses Argon2id, the winner of the Password Hashing Competition, for password hashing:

// Configuration
const ARGON2_OPTIONS = {
  type: argon2.argon2id,      // Hybrid approach (resistant to both side-channel and GPU attacks)
  memoryCost: 65536,           // 64MB memory
  timeCost: 3,                // 3 iterations
  parallelism: 4,             // 4 threads
};
Enter fullscreen mode Exit fullscreen mode

Why Argon2id?

  • Memory-Hard: Requires significant memory, making GPU attacks expensive
  • Side-Channel Resistant: Constant-time operations prevent timing attacks
  • Tunable: Adjust memory, time, and parallelism based on your security needs

Timing Attack Protection

The login flow is designed to prevent timing attacks that could reveal whether a user exists:

// Both paths take similar time
// Non-existent user: hash verification attempt (constant time)
// Wrong password: hash verification attempt (constant time)
// Result: Attacker can't distinguish between "user doesn't exist" and "wrong password"
Enter fullscreen mode Exit fullscreen mode

This is tested to ensure execution times are within 50-100ms of each other, regardless of whether the user exists or the password is wrong.

2. Token Security

RS256 Algorithm

Tokens are signed using RS256 (RSA with SHA-256), an asymmetric algorithm:

  • Private Key: Used by auth service to sign tokens (never exposed)
  • Public Key: Used by consumer apps to verify tokens (exposed via JWKS)
  • Benefits: Consumer apps can verify tokens without knowing the secret

JWKS (JSON Web Key Set)

Public keys are exposed via a standard JWKS endpoint:

GET /.well-known/jwks.json
{
  "keys": [
    {
      "kty": "RSA",
      "kid": "abc123",
      "use": "sig",
      "n": "...",
      "e": "AQAB"
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode

This follows OAuth 2.0 and OpenID Connect standards, making integration with standard libraries straightforward.

Token Claims

Tokens include standard JWT claims plus custom claims:

{
  sub: "user-id",           // Subject (user ID)
  aud: "client-id",         // Audience (application client ID)
  tid: "app-id",            // Tenant ID (application ID)
  roles: ["admin", "user"], // User roles for this app
  iss: "rugi-auth",         // Issuer
  iat: 1234567890,          // Issued at
  exp: 1234567890           // Expires at
}
Enter fullscreen mode Exit fullscreen mode

Refresh Token Rotation

Refresh tokens rotate on every use:

  1. Client uses refresh token to get new access token
  2. Server generates new refresh token
  3. Old refresh token is immediately invalidated
  4. Client must save the new refresh token

This ensures that if a refresh token is compromised, it can only be used once before becoming invalid.

3. Rate Limiting

rugi-auth implements Redis-backed distributed rate limiting:

Authentication Endpoints

// Standard rate limiter
windowMs: 15 minutes
maxRequests: 100 requests per window
Enter fullscreen mode Exit fullscreen mode

Sensitive Operations

// Stricter rate limiter for password reset, OTP requests
windowMs: 15 minutes
maxRequests: 3 requests per window
Enter fullscreen mode Exit fullscreen mode

Features:

  • Distributed: Works across multiple server instances
  • Redis-Backed: Persistent rate limiting across restarts
  • IP-Based: Uses req.ip (respects trust proxy setting)
  • Graceful Fallback: Falls back to memory store if Redis is unavailable

4. Input Validation

All inputs are validated using Joi schemas:

  • Email Validation: RFC-compliant email validation
  • Password Strength: Configurable password requirements
  • Client Credentials: Validates client_id and client_secret format
  • Token Validation: Validates token structure before processing

5. SQL Injection Protection

rugi-auth uses Prisma ORM, which:

  • Parameterized Queries: All queries use parameterized statements
  • Type Safety: TypeScript types prevent invalid queries
  • SQL Injection Prevention: Built-in protection against SQL injection

6. CORS and Security Headers

Configurable CORS and security headers:

  • CORS: Configurable allowed origins
  • Helmet.js: Security headers (X-Content-Type-Options, X-Frame-Options, etc.)
  • HTTPS Enforcement: Can enforce HTTPS in production

7. Audit Logging

Comprehensive audit logging for security monitoring:

// All events are logged
- LOGIN (successful and failed)
- REGISTER
- REFRESH
- REVOKE
- ROLE_ASSIGN
- PASSWORD_RESET_REQUEST
- PASSWORD_RESET_COMPLETE
- OTP_REQUEST
- OTP_LOGIN
Enter fullscreen mode Exit fullscreen mode

Each log entry includes:

  • User ID (if applicable)
  • Action type
  • Timestamp
  • Metadata (IP address, user agent, etc.)

8. Client Secret Security

For confidential applications, client secrets are:

  • Hashed: Stored as Argon2id hashes (not plaintext)
  • Validated: Verified on every authentication request
  • Rotatable: Can be rotated without affecting existing tokens

9. Email Security

OTP and password reset emails:

  • Time-Limited: Codes expire after a set duration (default: 10 minutes)
  • Single-Use: OTP codes can only be used once
  • Rate Limited: Prevents email spam and brute force attacks

10. Database Security

  • Indexed Queries: Efficient queries prevent timing-based enumeration
  • Cascade Deletes: Proper cleanup when users or apps are deleted
  • Transaction Safety: Critical operations use database transactions

Getting Started

Quick Setup

rugi-auth can be set up in minutes:

# 1. Initialize a new project
npx rugi-auth init my-auth-service

# 2. Start infrastructure
cd my-auth-service
docker-compose up -d

# 3. Run migrations and setup
npm run prisma:migrate
npm run setup

# 4. Start the server
npm run dev
Enter fullscreen mode Exit fullscreen mode

Your authentication service is now running at http://localhost:7100!

Integration Example

Integrating with your Express application is straightforward:

// Install the lightweight client
npm install rugi-auth

// In your Express app
import { createAuthMiddleware, requireRole } from 'rugi-auth/client';

const auth = createAuthMiddleware({
  jwksUri: 'https://auth.example.com/.well-known/jwks.json',
  issuer: 'rugi-auth',
  audience: 'your-client-id',
});

// Protect routes
app.get('/api/profile', auth, (req, res) => {
  res.json({
    userId: req.user.userId,
    roles: req.user.roles,
  });
});

// Role-based access control
app.get('/api/admin', auth, requireRole('admin'), (req, res) => {
  res.json({ message: 'Admin access granted' });
});
Enter fullscreen mode Exit fullscreen mode

Authentication Flow

  1. User Registration/Login: User authenticates with rugi-auth service
  2. Token Issuance: Service issues JWT access token and refresh token
  3. API Requests: Client includes access token in Authorization: Bearer <token> header
  4. Token Verification: Your app verifies token using JWKS (no database lookup needed)
  5. Token Refresh: When access token expires, use refresh token to get new tokens

Architecture Overview

Standalone Service (Recommended)

Deploy rugi-auth as a separate service:

┌─────────────┐      ┌──────────────┐      ┌─────────────┐
│   Client    │      │  Your Apps   │      │  rugi-auth  │
│  (Browser)  │      │  (Express)   │      │   Service   │
└──────┬──────┘      └──────┬───────┘      └──────┬──────┘
       │                    │                      │
       │ 1. Login            │                      │
       │──────────────────────────────────────────>│
       │                    │                      │
       │ 2. JWT Tokens       │                      │
       │<──────────────────────────────────────────│
       │                    │                      │
       │ 3. API Request     │                      │
       │    (Bearer token)  │                      │
       │───────────────────>│                      │
       │                    │                      │
       │                    │ 4. Verify via JWKS  │
       │                    │─────────────────────>│
       │                    │                      │
       │                    │ 5. Public Key        │
       │                    │<─────────────────────│
       │                    │                      │
       │ 6. Response        │                      │
       │<───────────────────│                      │
Enter fullscreen mode Exit fullscreen mode

Benefits:

  • Microservices can verify tokens independently
  • No shared database between services
  • Centralized user management
  • Easy to scale

Package Import (Monolith)

For monolithic applications, import rugi-auth directly:

import { authMiddleware, roleMiddleware } from 'rugi-auth';

app.get('/protected', authMiddleware, (req, res) => {
  // req.user is available
});
Enter fullscreen mode Exit fullscreen mode

Real-World Example: E-Commerce Platform

Imagine you're building an e-commerce platform with:

  • Customer App: Public-facing store
  • Admin Dashboard: Internal management tool
  • Vendor Portal: For third-party sellers
  • Analytics Service: Separate microservice

With rugi-auth, you can:

  1. Single Sign-On: Users log in once, access all apps
  2. Role-Based Access:
    • Customers have customer role in customer app
    • Admins have admin role in admin dashboard
    • Vendors have vendor role in vendor portal
  3. Microservice Authentication: Analytics service verifies tokens via JWKS
  4. Centralized Management: Manage all users from one place

Comparison with Alternatives

Feature rugi-auth Auth0 Okta Firebase Auth
Cost Free (self-hosted) Per-user pricing Per-user pricing Free tier, then per-user
Self-Hosted ✅ Yes ❌ No ❌ No ❌ No
Multi-App Support ✅ Native ✅ Yes ✅ Yes ⚠️ Limited
App-Specific Roles ✅ Yes ⚠️ Complex ⚠️ Complex ❌ No
Customization ✅ Full ⚠️ Limited ⚠️ Limited ⚠️ Limited
Open Source ✅ Yes ❌ No ❌ No ❌ No
TypeScript ✅ Native ⚠️ SDK only ⚠️ SDK only ⚠️ SDK only

Best Practices

1. Token Storage

Client-Side:

  • Use httpOnly cookies when possible (prevents XSS)
  • If using localStorage, ensure HTTPS only
  • Never log tokens to console

Server-Side:

  • Store refresh tokens securely (encrypted database)
  • Implement token rotation
  • Monitor for token abuse

2. Rate Limiting

Configure appropriate rate limits:

  • Authentication: 100 requests per 15 minutes
  • Password Reset: 3 requests per 15 minutes
  • OTP Requests: 5 requests per 15 minutes

3. Monitoring

Monitor authentication events:

  • Failed login attempts
  • Token refresh patterns
  • Role assignment changes
  • Unusual access patterns

4. Key Rotation

Rotate RSA keys periodically:

  • Generate new key pair
  • Update JWKS endpoint
  • Old tokens remain valid until expiry
  • New tokens use new key

5. HTTPS

Always use HTTPS in production:

  • Protects tokens in transit
  • Prevents man-in-the-middle attacks
  • Required for secure cookies

Conclusion

rugi-auth provides a robust, secure, and developer-friendly solution for centralized authentication. Whether you're building microservices, a multi-product SaaS platform, or an enterprise application suite, rugi-auth gives you:

  • Security: Industry-standard practices out of the box
  • Scalability: Designed to handle growth
  • Flexibility: Configurable for your specific needs
  • Developer Experience: TypeScript, comprehensive docs, easy integration
  • Cost Efficiency: Open-source, self-hosted, no per-user fees

Getting Started

Join the Community

  • Report issues, suggest features, or contribute on GitHub
  • Share your integration stories and use cases

Ready to centralize your authentication? Give **rugi-auth* a try and experience the benefits of secure, scalable, multi-app authentication.*


About the Author

This article was written to help developers understand the power and capabilities of rugi-auth, a production-ready authentication service built for modern application architectures.

Keywords: Authentication, JWT, OAuth, Microservices, TypeScript, Express, Security, Multi-Tenant, RBAC, Centralized Auth

Top comments (0)