@epicdm/flowstate-auth-core
v1.0.0
Published
Core authentication business logic and interfaces for FlowState
Maintainers
Readme
@epic-flow/flowstate-auth-core
Core authentication business logic and interfaces for FlowState.
Features
- JWT Token Management: RS256-based access and refresh tokens
- API Token Generation: Secure service account tokens with bcrypt hashing
- Key Management: RS256 key pair generation and import utilities
- Storage Adapters: RxDB storage adapter for authentication data
- TypeScript: Full type safety with comprehensive type definitions
Installation
yarn add @epic-flow/flowstate-auth-coreQuick Start
JWT Token Management
import { TokenManager, generateKeyPair } from '@epic-flow/flowstate-auth-core'
// Generate RS256 key pair
const keys = await generateKeyPair()
// Initialize TokenManager
const manager = await TokenManager.create({
privateKey: keys.privateKey,
publicKey: keys.publicKey,
accessTokenTTL: 900, // 15 minutes
refreshTokenTTL: 2592000 // 30 days
})
// Create access token
const accessToken = await manager.createAccessToken({
userId: 'user-123',
email: '[email protected]',
domainId: 'domain-1',
orgId: 'org-1',
scopes: ['read', 'write']
})
// Verify access token
const payload = await manager.verifyAccessToken(accessToken)
console.log(payload.userId) // 'user-123'
// Create refresh token
const refreshToken = await manager.createRefreshToken({
userId: 'user-123',
sessionId: 'session-abc',
domainId: 'domain-1'
})
// Verify refresh token
const refreshPayload = await manager.verifyRefreshToken(refreshToken)API Token Management
import { generateAPIToken, hashAPIToken, verifyAPIToken } from '@epic-flow/flowstate-auth-core'
// Generate API token
const token = generateAPIToken('live') // Format: epic_live_{32_chars}
// or for test environment
const testToken = generateAPIToken('test') // Format: epic_test_{32_chars}
// Hash token for storage (bcrypt with 10 rounds)
const hash = await hashAPIToken(token)
// Store hash in database, return token to user (one-time display)
// Later: verify token against hash
const isValid = await verifyAPIToken(token, hash)
if (isValid) {
// Authenticate request
}API Reference
Key Management
generateKeyPair(): Promise<{ privateKey: string, publicKey: string }>
Generates an RS256 key pair for JWT signing.
Returns: Promise resolving to PEM-formatted private and public keys.
Example:
const { privateKey, publicKey } = await generateKeyPair()importKeys(config: JWTConfig): Promise<{ privateKeyObject: KeyLike, publicKeyObject: KeyLike, config: JWTConfig }>
Imports and validates PEM-formatted keys.
Parameters:
config: JWT configuration with private/public keys and TTL settings
Returns: Promise resolving to imported key objects and validated config.
Throws: Error if keys are invalid or malformed.
loadKeysFromEnv(): JWTConfig
Loads JWT configuration from environment variables.
Environment Variables:
JWT_PRIVATE_KEY: PEM-formatted RS256 private keyJWT_PUBLIC_KEY: PEM-formatted RS256 public keyJWT_ACCESS_TOKEN_TTL: Access token TTL in seconds (default: 900)JWT_REFRESH_TOKEN_TTL: Refresh token TTL in seconds (default: 2592000)
Returns: JWT configuration object.
Throws: Error if required environment variables are missing.
TokenManager
TokenManager.create(config: JWTConfig): Promise<TokenManager>
Factory method to create a new TokenManager instance.
Parameters:
config: JWT configuration with keys and TTL settings
Returns: Promise resolving to initialized TokenManager instance.
createAccessToken(payload: AccessTokenPayload): Promise<string>
Creates a signed JWT access token.
Parameters:
payload: Access token payload with userId, email, domainId, orgId, and optional scopes
Returns: Promise resolving to JWT token string.
verifyAccessToken(token: string): Promise<AccessTokenPayload>
Verifies and decodes a JWT access token.
Parameters:
token: JWT token string to verify
Returns: Promise resolving to decoded access token payload.
Throws: Error if token is invalid, expired, or signature verification fails.
createRefreshToken(payload: RefreshTokenPayload): Promise<string>
Creates a signed JWT refresh token.
Parameters:
payload: Refresh token payload with userId, sessionId, and domainId
Returns: Promise resolving to JWT token string.
verifyRefreshToken(token: string): Promise<RefreshTokenPayload>
Verifies and decodes a JWT refresh token.
Parameters:
token: JWT token string to verify
Returns: Promise resolving to decoded refresh token payload.
Throws: Error if token is invalid, expired, or signature verification fails.
API Token Functions
generateAPIToken(environment: 'live' | 'test'): string
Generates a secure API token with environment-specific prefix.
Parameters:
environment: Token environment ('live' or 'test')
Returns: API token string in format epic_{env}_{32_random_chars}.
hashAPIToken(token: string): Promise<string>
Hashes an API token using bcrypt with 10 rounds.
Parameters:
token: API token string to hash
Returns: Promise resolving to bcrypt hash string.
verifyAPIToken(token: string, hash: string): Promise<boolean>
Verifies an API token against its stored hash.
Parameters:
token: API token string to verifyhash: Stored bcrypt hash
Returns: Promise resolving to true if token matches hash, false otherwise.
Configuration
JWT Configuration
interface JWTConfig {
privateKey: string // PEM-formatted RS256 private key
publicKey: string // PEM-formatted RS256 public key
accessTokenTTL: number // Access token TTL in seconds (default: 900)
refreshTokenTTL: number // Refresh token TTL in seconds (default: 2592000)
previousPublicKeys?: string[] // Optional: previous public keys for key rotation
}Token Payloads
interface AccessTokenPayload {
userId: string
email: string
domainId: string
orgId: string
scopes?: string[]
}
interface RefreshTokenPayload {
userId: string
sessionId: string
domainId: string
}Security Best Practices
Key Management
- Generate strong keys: Use
generateKeyPair()to generate cryptographically secure RS256 keys - Store keys securely: Use environment variables or secure vaults (1Password, AWS Secrets Manager)
- Never commit keys: Add keys to
.gitignoreand use environment-specific configuration - Rotate keys regularly: Implement key rotation using
previousPublicKeysfor zero-downtime rotation
Token Management
- Short-lived access tokens: Use default 15-minute TTL for access tokens
- One-time refresh tokens: Implement token rotation to prevent replay attacks
- Secure token storage: Store refresh tokens in httpOnly cookies or secure storage
- Validate all claims: Always verify userId, domainId, and orgId match expected values
API Tokens
- Display once: Show API tokens to users only once during generation
- Hash before storage: Always use
hashAPIToken()before storing in database - Use environment prefixes: Distinguish live and test tokens with
epic_live_andepic_test_prefixes - Implement rate limiting: Add rate limiting to API endpoints using API tokens
Generate Keys for Development
Use the included script to generate RS256 keys:
yarn generate-keysThis will output a private and public key that you can add to your .env file:
JWT_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----"
JWT_PUBLIC_KEY="-----BEGIN PUBLIC KEY-----\n...\n-----END PUBLIC KEY-----"
JWT_ACCESS_TOKEN_TTL=900
JWT_REFRESH_TOKEN_TTL=2592000Testing
# Run all tests
yarn test
# Run tests in watch mode
yarn test:watch
# Run tests with coverage
yarn test --coverageDevelopment
# Build the package
yarn build
# Build in watch mode
yarn dev
# Type checking
yarn typecheck
# Linting
yarn lintLicense
MIT
