@starasia/sso-api
v0.0.2
Published
SSO integration package for Node.js backend applications
Readme
@starasia/sso-api
NPM package untuk mempermudah integrasi SSO (Single Sign-On) internal dengan sistem backend Node.js menggunakan Express.js framework.
Features
- 🔐 JWT verification dengan RS256 algorithm
- 🚀 Easy Express.js middleware integration
- ✅ TypeScript support dengan full type definitions
- 📦 Redis caching untuk token validation (optional)
- 🔄 Automatic public key caching dan refresh
- 🛡️ Comprehensive error handling
- 🎯 Multiple token types support (AUTH, ACCESS, REFRESH)
Installation
npm install @starasia/sso-apiatau dengan yarn:
yarn add @starasia/sso-apiatau dengan pnpm:
pnpm add @starasia/sso-apiQuick Start
import express from 'express'
import { config, auth, AUTH_TYPE, RequestWithAccessToken } from '@starasia/sso-api'
const app = express()
app.use(express.json())
// Initialize SSO
const ssoRouter = config({
clientId: process.env.SSO_CLIENT_ID!,
clientSecret: process.env.SSO_CLIENT_SECRET!,
baseUrl: process.env.SSO_BASE_URL!,
redisUrl: process.env.REDIS_URL, // optional
})
// Mount SSO routes
app.use('/auth', ssoRouter)
// Protected route example
app.get('/api/profile',
auth(AUTH_TYPE.ACCESS),
(req, res) => {
const { tokenPayload } = req as RequestWithAccessToken
res.json({ user: tokenPayload })
}
)
app.listen(3000, () => {
console.log('Server running on port 3000')
})Authentication Flow
- Login: User mengirim email dan password ke
POST /auth/login- Response:
authTokendanredirectUri
- Response:
- Callback: Kirim
authTokenkePOST /auth/callback- Response:
idToken,authToken,accessToken,refreshToken
- Response:
- Use Access Token: Gunakan
accessTokenuntuk mengakses protected endpoints - Refresh: Gunakan
refreshTokenuntuk mendapatkanaccessTokenbaru ketika expired
API Reference
Configuration
config(options: SSOConfig): Router
Inisialisasi SSO configuration dan return Express Router dengan SSO routes.
Parameters:
| Name | Type | Required | Default | Description |
|------|------|----------|---------|-------------|
| clientId | string | Yes | - | SSO client ID |
| clientSecret | string | Yes | - | SSO client secret |
| baseUrl | string | Yes | - | SSO server base URL |
| issuer | string | No | baseUrl | JWT issuer untuk validation |
| redisUrl | string | No | undefined | Redis connection URL (optional) |
| publicKeyUrl | string | No | ${baseUrl}/auth/public-key | Public key endpoint URL |
| publicKeyCacheTTL | number | No | 3600 | Public key cache TTL in seconds |
Example:
const ssoRouter = config({
clientId: 'your-client-id',
clientSecret: 'your-client-secret',
baseUrl: 'https://sso.example.com',
issuer: 'https://sso.example.com',
redisUrl: 'redis://localhost:6379',
publicKeyCacheTTL: 7200,
})
app.use('/auth', ssoRouter)Middleware
auth(type: AUTH_TYPE): RequestHandler
Authentication middleware untuk protect routes dengan JWT verification.
Token Types:
AUTH_TYPE.AUTH- Authentication tokenAUTH_TYPE.ACCESS- Access token (default)AUTH_TYPE.REFRESH- Refresh token
Example:
import { auth, AUTH_TYPE, RequestWithAccessToken } from '@starasia/sso-api'
// Protect with ACCESS token (default)
app.get('/api/protected',
auth(AUTH_TYPE.ACCESS),
(req, res) => {
const { tokenPayload } = req as RequestWithAccessToken
res.json({ user: tokenPayload })
}
)
// Protect with AUTH token
app.post('/api/admin',
auth(AUTH_TYPE.AUTH),
(req, res) => {
// Only accessible with AUTH token
res.json({ message: 'Admin access granted' })
}
)Routes
Package ini otomatis menyediakan authentication endpoints:
POST /auth/login
Login dengan email dan password. Mengembalikan authToken dan redirectUri.
Request Body:
{
"email": "[email protected]",
"password": "password123"
}Response:
{
"success": true,
"data": {
"authToken": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
"redirectUri": "https://app.example.com/callback"
},
"message": "Login successful"
}POST /auth/callback
Handle callback dan exchange authToken untuk mendapatkan semua tokens (idToken, authToken, accessToken, refreshToken).
Request Body:
{
"authToken": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."
}Response:
{
"success": true,
"data": {
"idToken": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
"authToken": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
"accessToken": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
"refreshToken": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
"expiresIn": 3600
},
"message": "Callback processed successfully"
}POST /auth/refresh
Refresh access token menggunakan refresh token.
Request Body:
{
"refreshToken": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."
}Response:
{
"success": true,
"data": {
"accessToken": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
"refreshToken": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
"expiresIn": 3600
}
}POST /auth/logout
Logout dan revoke tokens (requires ACCESS token).
Headers:
Authorization: Bearer <access_token>Response:
{
"success": true,
"data": null,
"message": "Logout successful"
}GET /auth/userinfo
Get current user information (requires ACCESS token).
Headers:
Authorization: Bearer <access_token>Response:
{
"success": true,
"data": {
"sub": "user-id-123",
"email": "[email protected]",
"name": "John Doe"
}
}GET /auth/verify
Verify token validity (requires ACCESS token).
Headers:
Authorization: Bearer <access_token>Response:
{
"success": true,
"data": {
"valid": true,
"payload": {
"sub": "user-id-123",
"email": "[email protected]",
"type": "ACCESS",
"iat": 1234567890,
"exp": 1234571490
}
}
}GET /auth/health
Health check endpoint.
Response:
{
"success": true,
"data": {
"status": "healthy",
"timestamp": "2025-01-01T00:00:00.000Z"
}
}TypeScript Support
Package ini fully typed dengan TypeScript:
import {
config,
auth,
AUTH_TYPE,
SSOConfig,
RequestWithAccessToken,
PayloadAccessToken
} from '@starasia/sso-api'
// Configuration types
const ssoConfig: SSOConfig = {
clientId: 'client-id',
clientSecret: 'client-secret',
baseUrl: 'https://sso.example.com',
}
// Extended Request types
app.get('/profile', auth(AUTH_TYPE.ACCESS), (req, res) => {
const { tokenPayload } = req as RequestWithAccessToken
// tokenPayload is fully typed as PayloadAccessToken
console.log(tokenPayload.sub, tokenPayload.email)
})Error Handling
Package ini menggunakan standardized error responses:
{
"success": false,
"error": {
"message": "Invalid or expired token",
"statusCode": 401
}
}Error Codes:
| Status Code | Error Message | Description | |-------------|---------------|-------------| | 400 | Invalid SSO configuration | Configuration tidak valid | | 400 | Authorization token is required | Token tidak ditemukan | | 400 | Invalid token format | Format token salah | | 401 | Invalid or expired token | Token invalid atau expired | | 401 | Token has expired | Token sudah expired | | 403 | Wrong token type | Token type tidak sesuai endpoint | | 403 | Token has been revoked | Token sudah di-revoke | | 500 | Failed to connect to SSO server | Koneksi ke SSO server gagal | | 500 | Failed to fetch public key | Gagal fetch public key |
Advanced Usage
Custom Error Handler
import { errorHandler, notFoundHandler } from '@starasia/sso-api'
// Use custom error handler
app.use(errorHandler)
app.use(notFoundHandler)Using Utilities
import {
generateChallengeCode,
successResponse,
errorResponse
} from '@starasia/sso-api'
// Generate challenge code for OAuth flows
const challenge = generateChallengeCode(32)
// Use response helpers
app.get('/custom', (req, res) => {
return successResponse(res, { data: 'value' }, 'Success message')
})Multiple Token Type Protection
import { auth, AUTH_TYPE } from '@starasia/sso-api'
// Different protection levels
app.get('/public', (req, res) => {
res.json({ message: 'Public endpoint' })
})
app.get('/user', auth(AUTH_TYPE.ACCESS), (req, res) => {
res.json({ message: 'User endpoint' })
})
app.get('/admin', auth(AUTH_TYPE.AUTH), (req, res) => {
res.json({ message: 'Admin endpoint' })
})Environment Variables
Example .env file:
SSO_CLIENT_ID=your-client-id
SSO_CLIENT_SECRET=your-client-secret
SSO_BASE_URL=https://sso.example.com
REDIS_URL=redis://localhost:6379Requirements
- Node.js >= 18.0.0
- Express.js >= 4.18.0
Dependencies
axios- HTTP client untuk SSO server communicationjsonwebtoken- JWT verification dengan RS256ioredis- Redis client untuk token caching (optional)
Contributing
Contributions are welcome! Please follow these guidelines:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
Development Setup
# Clone repository
git clone https://github.com/starasia/sso-api.git
cd sso-api
# Install dependencies
npm install
# Run development mode
npm run dev
# Run tests
npm test
# Build package
npm run build
# Lint code
npm run lint
# Format code
npm run formatLicense
MIT © Starasia
Examples
Lihat folder examples/ untuk contoh penggunaan lengkap:
examples/basic-usage.ts- Contoh implementasi basic dengan Express.jsexamples/authentication-flow.md- Dokumentasi lengkap authentication flow dengan curl examples dan frontend integration
Support
For issues and questions, please open an issue on GitHub.
