npm package: @gftdcojp/auth
Description: Zero-config authentication package for Next.js applications with Firebase integration
Author: gftdcojp
Latest version: 2.3.2

# @gftdcojp/auth

🚀 **Zero-config authentication package for Next.js applications with Firebase integration.**

[![npm version](https://badge.fury.io/js/@gftdcojp/auth.svg)](https://badge.fury.io/js/@gftdcojp/auth)
[![License: Apache-2.0](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)

**Published at: https://www.npmjs.com/package/@gftdcojp/auth**

## Features

- ✅ **Zero-config setup** - Works out of the box
- ✅ **Firebase integration** - Built-in Firebase Auth support
- ✅ **Next.js compatible** - Optimized for Next.js App Router
- ✅ **TypeScript support** - Full TypeScript definitions
- ✅ **Session management** - Secure cookie-based sessions
- ✅ **Multi-tenant support** - Firebase tenant support
- ✅ **Middleware support** - Next.js middleware integration
- ✅ **Microservice authentication** - Secure inter-service JWT communication
- ✅ **JWKS support** - Decentralized public key distribution

## Installation

```bash
npm install @gftdcojp/auth
# or
yarn add @gftdcojp/auth
# or
pnpm add @gftdcojp/auth
```

### Prerequisites

Make sure you have the following environment variables configured:

```bash
# Firebase Admin SDK (Required for server-side operations)
FIREBASE_PROJECT_ID=your-firebase-project-id
FIREBASE_CLIENT_EMAIL=firebase-adminsdk-xxx@your-project.iam.gserviceaccount.com
FIREBASE_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n"
```

> **Note**: If you're using this package within the GFTD ecosystem (@100_api/, @200_user/, @120_admin/), these environment variables are not needed as the infrastructure is managed centrally.

## Quick Start

### 1. Environment Setup

Create a `.env.local` file with your Firebase configuration:

```bash
# Firebase Admin SDK (Required for server-side operations)
FIREBASE_PROJECT_ID=your-firebase-project-id
FIREBASE_CLIENT_EMAIL=firebase-adminsdk-xxx@your-project.iam.gserviceaccount.com
FIREBASE_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n"
```

### 2. Zero-Config Setup

```tsx
// app/layout.tsx
'use client'

import { AuthProvider, createClientAuthConfig } from '@gftdcojp/auth'

export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  // 🎯 Zero-config setup - no configuration needed!
  const authConfig = createClientAuthConfig()

  return (
    <html lang="en">
      <body>
        <AuthProvider config={authConfig}>
          {children}
        </AuthProvider>
      </body>
    </html>
  )
}
```

### 3. Using Authentication

```tsx
// app/page.tsx
'use client'

import { useAuth } from '@gftdcojp/ai-gftd-auth'

export default function HomePage() {
  const { user, isLoading, logout, getAfterLoginUrl } = useAuth()

  if (isLoading) return <div>Loading...</div>

  if (!user) {
    return (
      <div>
        <h1>Welcome!</h1>
        <p>Please sign in to continue.</p>
        <a href="/signin">Sign In</a>
      </div>
    )
  }

  return (
    <div>
      <h1>Welcome, {user.displayName}!</h1>
      <p>Email: {user.email}</p>
      <button onClick={() => logout().then(() => window.location.href = '/signin')}>
        Logout
      </button>
    </div>
  )
}
```

## Advanced Configuration

### Custom Redirect URLs

```tsx
// Custom redirects for your application
const authConfig = createClientAuthConfig({
  redirects: {
    afterLogin: '/dashboard',    // Custom login redirect
    afterLogout: '/welcome',     // Custom logout redirect
    onAuthError: '/help',        // Custom error redirect
  }
})
```

### API Server Configuration

```tsx
// If you have a custom API server
const authConfig = createClientAuthConfig({
  api: {
    baseUrl: 'https://your-api-server.com',
    loginEndpoint: '/api/custom/login',
    sessionEndpoint: '/api/custom/session',
    logoutEndpoint: '/api/custom/logout',
  }
})
```

## API Reference

### Client Hooks

#### `useAuth()`
Returns authentication state and methods.

```typescript
const {
  user,           // UserProfile | null
  accessToken,    // string | null
  isLoading,      // boolean
  loginWithIdToken, // (idToken: string, tenantId?: string) => Promise<void>
  logout,         // () => Promise<void>
  refreshToken,   // () => Promise<void>
  getAfterLoginUrl,   // () => string
  getAfterLogoutUrl,  // () => string
  getAuthErrorUrl,    // () => string
} = useAuth()
```

### Configuration Functions

#### `createClientAuthConfig(overrides?)`
Creates client-side authentication configuration.

#### `createServerAuthConfig(overrides?)`
Creates server-side authentication configuration.

### Components

#### `<AuthProvider config={authConfig}>`
Provides authentication context to your application.

## Server-Side Usage

### API Routes

```typescript
// app/api/auth/login/route.ts
import { createGFTDAuth, createServerAuthConfig } from '@gftdcojp/auth'

const authConfig = createServerAuthConfig()
const auth = createGFTDAuth(authConfig)

export async function POST(request: Request) {
  const { idToken } = await request.json()

  const result = await auth.handleLogin({ idToken })

  if (result.success) {
    // Set session cookie
    const response = NextResponse.json({ user: result.user })
    response.cookies.set('session', result.accessToken!)
    return response
  }

  return NextResponse.json({ error: result.error }, { status: 401 })
}
```

### Middleware

```typescript
// middleware.ts
import { createAuthMiddleware, createServerAuthConfig } from '@gftdcojp/auth'

const authConfig = createServerAuthConfig()
const middleware = createAuthMiddleware({
  authConfig,
  publicPaths: ['/', '/signin', '/api/auth/login']
})

export default middleware
```

## Firebase Configuration

The package requires the following Firebase environment variables:

- `FIREBASE_PROJECT_ID` - Your Firebase project ID
- `FIREBASE_CLIENT_EMAIL` - Firebase service account email
- `FIREBASE_PRIVATE_KEY` - Firebase service account private key

### Getting Firebase Credentials

1. Go to [Firebase Console](https://console.firebase.google.com/)
2. Select your project
3. Go to **Project Settings** → **Service Accounts**
4. Generate a new private key
5. Download the JSON file
6. Extract the values for the environment variables

## Security

- Uses HTTP-only, Secure cookies for session management
- Supports cookie signature verification
- Firebase Admin SDK for secure token validation
- Built-in CSRF protection

## License

MIT © GFTD Co., Ltd.

## Microservice Authentication

This package supports secure communication between microservices using JWT tokens.

### JWKS Endpoint

The auth service provides a JWKS endpoint for public key distribution:

```
GET /.well-known/jwks
```

This endpoint returns the public keys needed for JWT verification across all microservices.

### Internal Service Tokens

Generate short-lived JWT tokens for secure inter-service communication:

```typescript
import { createGFTDAuth, createServerAuthConfig } from '@gftdcojp/auth'

const config = createServerAuthConfig()
const auth = createGFTDAuth(config)

// Generate internal service token
const internalToken = await auth.createInternalServiceToken(
  userId,
  sessionId,
  'https://target-service.com',
  ['read:orders', 'write:orders']
)
```

### Token Verification

Microservices can verify internal JWT tokens using the JWKS endpoint:

```typescript
// Verify internal service token
const userProfile = await auth.verifyInternalServiceToken(
  token,
  'https://my-service.com'
)

if (userProfile) {
  // Token is valid - proceed with user context
  console.log('User:', userProfile.sub)
  console.log('Permissions:', userProfile.permissions)
}
```

### Security Architecture

```
1. User authenticates with Firebase
2. API Gateway (@100_api) creates internal JWT + Access Token
3. JWT sent to downstream services with Bearer header
4. Services verify JWT using JWKS endpoint
5. Services process request with authenticated user context
```

This ensures secure, decentralized microservice communication while maintaining user authentication context.

## Usage Examples

### 1. API Gateway (@100_api) Side

The API Gateway automatically creates internal JWT tokens during login:

```typescript
// apps/100_api/src/app/api/auth/login/route.ts
import { getTokenService } from '../../../../../packages/030_core/src/server/token-service'

const tokenService = getTokenService()
const internalToken = await tokenService.createInternalServiceToken(
  userId, sessionId, 'https://target-service.com', permissions
)

// Return both access token and internal service token
return { success: true, accessToken, internalServiceToken, user }
```

### 2. Microservice Client

Use the microservice client for secure service-to-service communication:

```typescript
// apps/100_api/src/lib/microservice-client.ts
import { getMicroserviceClient } from '@/lib/microservice-client'

const client = getMicroserviceClient()
const response = await client.callService(
  'https://orders.gftd.ai',
  '/api/orders',
  'GET',
  null,
  userId,
  sessionId,
  ['read:orders']
)
```

### 3. Microservice Side - JWT Verification

Microservices verify JWT tokens using the middleware:

```typescript
// Any microservice endpoint
import { createMicroserviceAuthMiddleware, getAuthenticatedUser } from '@gftdcojp/auth/middleware'

const microserviceAuth = createMicroserviceAuthMiddleware({
  expectedAudience: 'https://your-service.com',
  requiredPermissions: ['read:orders'],
  publicPaths: ['/health'], // Optional public endpoints
})

export async function GET(request: NextRequest) {
  // Apply JWT authentication
  const authResult = await microserviceAuth(request)
  if (authResult.status !== 200) {
    return authResult
  }

  // Get authenticated user
  const user = getAuthenticatedUser(request)
  // user: { userId, permissions, sessionId }

  // Process authenticated request
  return NextResponse.json({ data: 'authenticated response' })
}
```

### 4. Complete Example - Orders Service

```typescript
// apps/100_api/src/app/api/orders/route.ts
import { createMicroserviceAuthMiddleware, getAuthenticatedUser } from '@gftdcojp/auth/middleware'

const auth = createMicroserviceAuthMiddleware({
  expectedAudience: 'https://api.auth.gftd.ai',
  requiredPermissions: ['read:orders'],
})

export async function GET(request: NextRequest) {
  const authResult = await auth(request)
  if (authResult.status !== 200) return authResult

  const user = getAuthenticatedUser(request)
  // Use user.userId, user.permissions for business logic

  return NextResponse.json({
    orders: await getUserOrders(user.userId),
    user: { id: user.userId, permissions: user.permissions }
  })
}
```

### 5. Environment Variables

#### For the Authentication Server (e.g., `@100_api`)
The following environment variables are required on the server responsible for signing and issuing JWTs.

```bash
# JWT Key Configuration (for the auth signing service)
AI_GFTD_JWT_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n"
AI_GFTD_JWT_PUBLIC_KEY="-----BEGIN PUBLIC KEY-----\n...\n-----END PUBLIC KEY-----\n"
AI_GFTD_JWT_KEY_ID="auth-key-1"
```

#### For Microservice Clients (e.g., `@200_user`, `@120_admin`)
With the dynamic JWKS flow, microservice clients **no longer need** to configure the public key directly. The verification library automatically fetches the latest keys from the authentication server's `.well-known/jwks` endpoint.

You just need to ensure your service can reach the authentication server.

### 6. Development vs Production

```typescript
// Automatic environment detection
const jwksUrl = process.env.NODE_ENV === 'production'
  ? 'https://api.auth.gftd.ai/.well-known/jwks'
  : 'http://localhost:3001/.well-known/jwks'
```

## Security Considerations

### 🔐 Security Features

- **JWT Expiration**: Internal tokens expire in 5 minutes for security
- **Audience Validation**: JWTs are validated against expected service audiences
- **Permission-based Access**: Granular permission checking per endpoint
- **HTTPS Only**: All communication must use HTTPS in production
- **Key Rotation**: Support for JWT key rotation via environment variables

### ⚠️ Potential Vulnerabilities & Mitigations

#### 1. **JWT Replay Attacks**
- **Risk**: Stolen JWT could be reused within expiration window
- **Mitigation**:
  - Short expiration times (5 minutes for internal tokens)
  - Audience validation per service
  - Optional: Implement JWT ID (jti) for one-time use

#### 2. **Key Exposure**
- **Risk**: Private key exposure via environment variables
- **Mitigation**:
  - Use secure key management systems (AWS KMS, HashiCorp Vault)
  - Rotate keys regularly
  - Limit key access to authorized services only

#### 3. **Man-in-the-Middle (MITM)**
- **Risk**: JWT interception in transit
- **Mitigation**:
  - Always use HTTPS/TLS 1.3+
  - Certificate pinning for production
  - Mutual TLS (mTLS) for service-to-service communication

#### 4. **Audience Confusion**
- **Risk**: JWT intended for one service used on another
- **Mitigation**:
  - Strict audience validation in middleware
  - Service-specific audiences (e.g., `https://orders.gftd.ai`)
  - Regular security audits

#### 5. **Permission Escalation**
- **Risk**: Users gaining unauthorized permissions
- **Mitigation**:
  - Permission validation on every request
  - Centralized permission management
  - Regular permission audits

### 🚨 Security Best Practices

#### For API Gateway (@100_api):
```typescript
// Always validate user permissions before creating internal tokens
const userPermissions = await getUserPermissions(userId)
if (!userPermissions.includes('required:permission')) {
  throw new Error('Insufficient permissions')
}
```

#### For Microservices:
```typescript
// Implement rate limiting
const rateLimit = createRateLimiter({ windowMs: 60000, max: 100 })
app.use(rateLimit)

// Log security events
if (authResult.status !== 200) {
  console.warn(`Authentication failed: ${request.url} from ${request.ip}`)
}
```

#### Environment Security:
```bash
# Use encrypted environment variables
# Rotate keys every 90 days
# Use different keys for development/production
# Store keys in secure vaults, not in code
```

### 🔍 Security Monitoring

Implement comprehensive logging for:
- Failed authentication attempts
- Permission violations
- JWT validation errors
- Unusual request patterns
- Key usage statistics

### 🛡️ Recommended Security Headers

```typescript
// Add security headers to all responses
response.headers.set('X-Content-Type-Options', 'nosniff')
response.headers.set('X-Frame-Options', 'DENY')
response.headers.set('X-XSS-Protection', '1; mode=block')
response.headers.set('Strict-Transport-Security', 'max-age=31536000; includeSubDomains')
```

### 📞 Security Incident Response

1. **Detection**: Monitor logs for suspicious activity
2. **Containment**: Rotate JWT keys immediately
3. **Investigation**: Analyze access patterns
4. **Recovery**: Restore from secure backups
5. **Lessons Learned**: Update security policies

## Support

For security issues, please email security@gftd.ai instead of creating public issues.

For general questions, please open an issue on GitHub.