Package Exports
- @gftdcojp/auth
- @gftdcojp/auth/client
- @gftdcojp/auth/middleware
- @gftdcojp/auth/server
Readme
@gftdcojp/auth
🚀 Zero-config authentication package for Next.js applications with Firebase integration.
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
npm install @gftdcojp/auth
# or
yarn add @gftdcojp/auth
# or
pnpm add @gftdcojp/authPrerequisites
Make sure you have the following environment variables configured:
# 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:
# 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
// 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
// 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
// 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
// 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.
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
// 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
// middleware.ts
import { createAuthMiddleware, createServerAuthConfig } from '@gftdcojp/auth'
const authConfig = createServerAuthConfig()
const middleware = createAuthMiddleware({
authConfig,
publicPaths: ['/', '/signin', '/api/auth/login']
})
export default middlewareFirebase Configuration
The package requires the following Firebase environment variables:
FIREBASE_PROJECT_ID- Your Firebase project IDFIREBASE_CLIENT_EMAIL- Firebase service account emailFIREBASE_PRIVATE_KEY- Firebase service account private key
Getting Firebase Credentials
- Go to Firebase Console
- Select your project
- Go to Project Settings → Service Accounts
- Generate a new private key
- Download the JSON file
- 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/jwksThis 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:
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:
// 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 contextThis 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:
// 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:
// 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:
// 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
// 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.
# 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
// 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):
// 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:
// 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:
# 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
// 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
- Detection: Monitor logs for suspicious activity
- Containment: Rotate JWT keys immediately
- Investigation: Analyze access patterns
- Recovery: Restore from secure backups
- 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.