137 lines
3.6 KiB
JavaScript
137 lines
3.6 KiB
JavaScript
/**
|
|
* Create a mock JWT token with custom payload
|
|
* @param {object} payload - JWT payload data
|
|
* @param {object} options - Token options
|
|
* @returns {string} Mock JWT token
|
|
*/
|
|
export function createMockJwt(payload = {}, options = {}) {
|
|
const { expiresIn = 3600 } = options // Default 1 hour
|
|
|
|
const now = Math.floor(Date.now() / 1000)
|
|
|
|
const defaultPayload = {
|
|
sub: '12345',
|
|
email: 'test@example.com',
|
|
iat: now,
|
|
exp: now + expiresIn,
|
|
user: {
|
|
id: '12345',
|
|
email: 'test@example.com',
|
|
name: 'Test User'
|
|
},
|
|
...payload
|
|
}
|
|
|
|
const header = { alg: 'HS256', typ: 'JWT' }
|
|
|
|
// Create base64url encoded parts
|
|
const encodedHeader = base64UrlEncode(JSON.stringify(header))
|
|
const encodedPayload = base64UrlEncode(JSON.stringify(defaultPayload))
|
|
|
|
// Mock signature (not cryptographically valid, but structurally correct)
|
|
const mockSignature = base64UrlEncode('mock-signature-for-testing')
|
|
|
|
return `${encodedHeader}.${encodedPayload}.${mockSignature}`
|
|
}
|
|
|
|
/**
|
|
* Create an expired JWT token
|
|
* @param {object} payload - Additional payload data
|
|
* @returns {string} Expired JWT token
|
|
*/
|
|
export function createExpiredJwt(payload = {}) {
|
|
const pastTime = Math.floor(Date.now() / 1000) - 3600 // 1 hour ago
|
|
|
|
return createMockJwt({
|
|
...payload,
|
|
iat: pastTime - 3600,
|
|
exp: pastTime
|
|
}, { expiresIn: -3600 })
|
|
}
|
|
|
|
/**
|
|
* Create an invalid JWT token (malformed)
|
|
* @param {string} type - Type of invalid token
|
|
* @returns {string} Invalid JWT token
|
|
*/
|
|
export function createInvalidJwt(type = 'malformed') {
|
|
switch (type) {
|
|
case 'malformed':
|
|
return 'not-a-valid-jwt'
|
|
case 'missing-parts':
|
|
return 'header.payload'
|
|
case 'invalid-base64':
|
|
return 'invalid!!!.base64!!!.content!!!'
|
|
case 'invalid-json':
|
|
return `${base64UrlEncode('not-json')}.${base64UrlEncode('not-json')}.signature`
|
|
case 'empty':
|
|
return ''
|
|
default:
|
|
return 'invalid'
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Create a JWT token with specific user data
|
|
* @param {object} user - User data to include
|
|
* @param {object} options - Token options
|
|
* @returns {string} JWT token with user data
|
|
*/
|
|
export function createUserJwt(user, options = {}) {
|
|
return createMockJwt({
|
|
sub: user.id || '12345',
|
|
email: user.email || 'user@example.com',
|
|
user: {
|
|
id: user.id || '12345',
|
|
email: user.email || 'user@example.com',
|
|
name: user.name || 'Test User',
|
|
...user
|
|
}
|
|
}, options)
|
|
}
|
|
|
|
/**
|
|
* Decode a JWT token payload (for test verification)
|
|
* @param {string} token - JWT token
|
|
* @returns {object|null} Decoded payload or null
|
|
*/
|
|
export function decodeTestJwt(token) {
|
|
try {
|
|
if (!token || typeof token !== 'string') return null
|
|
const parts = token.split('.')
|
|
if (parts.length !== 3) return null
|
|
|
|
const payload = parts[1]
|
|
const decoded = JSON.parse(base64UrlDecode(payload))
|
|
return decoded
|
|
} catch {
|
|
return null
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Check if a JWT token is expired
|
|
* @param {string} token - JWT token
|
|
* @returns {boolean} True if expired
|
|
*/
|
|
export function isTestJwtExpired(token) {
|
|
const payload = decodeTestJwt(token)
|
|
if (!payload || typeof payload.exp !== 'number') return true
|
|
return Math.floor(Date.now() / 1000) >= payload.exp
|
|
}
|
|
|
|
// Helper functions for base64url encoding/decoding
|
|
function base64UrlEncode(str) {
|
|
const base64 = btoa(unescape(encodeURIComponent(str)))
|
|
return base64.replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '')
|
|
}
|
|
|
|
function base64UrlDecode(str) {
|
|
let base64 = str.replace(/-/g, '+').replace(/_/g, '/')
|
|
const pad = base64.length % 4
|
|
if (pad) {
|
|
base64 += '='.repeat(4 - pad)
|
|
}
|
|
return decodeURIComponent(escape(atob(base64)))
|
|
}
|