DragonStream: Rotational Web Tokens (RWT)
Introduction
DragonStream's Rotational Web Tokens (RWT) provide a revolutionary approach to authentication and authorization, replacing traditional JWT/cookie patterns with time-bound, self-verifying tokens that eliminate the need for SSL/TLS handshakes and certificate authorities.
Key Benefits
Domain | Traditional Approach | RWT Advantage |
---|---|---|
Security | Static tokens vulnerable to replay attacks | Time-bound tokens with automatic expiration |
Performance | Heavy SSL handshakes on each connection | Lightweight mathematical verification |
Reliability | Depends on CA infrastructure | Self-signing with no external dependencies |
Scalability | Requires session state or token validation | Stateless verification with pure mathematics |
Privacy | Certificates expose connection metadata | Ephemeral tokens leave no trace |
Simplicity | Complex SSL/TLS + Authorization layers | Single integrated security mechanism |
Core Concepts
What Is an RWT?
A Rotational Web Token is:
- Self-Signing: Derived from a per-user UserKey (the only stored secret)
- Time-Bound: Each RWT has explicit
releaseAt
andexpiresAt
timestamps (to microsecond precision) - Statelessly Verifiable: No external CA required—verification is pure mathematics (φ/√6 harmonics)
- Ephemeral: Once expired, tokens cannot be replayed or reverse-engineered
- Protocol-Agnostic: Works over HTTP, WebSockets, DragonNet or GeoNet semantic ports
Basic Structure
Similar to JWT, an RWT consists of three parts separated by dots:
header.payload.signature
However, unlike JWT, the signature is derived from a time-based rotation of the UserKey, making it:
- Impossible to forge without knowing the UserKey
- Only valid during its specified time window
- Resistant to quantum computing attacks due to its time-bound nature
How It Works
- Signup: Server stores only
{ username, passwordHash, UserKey }
- Issue RWT: Generate a token with
RWT.generate(UserKey, { releaseAt, expiresAt, meta })
- Client Request: Attach
Authorization: RWT <token>
header or connect viarwt://
protocol - Server Validation: Verify with
RWT.verify(token, UserKey)
API Reference
RWT.generate()
Creates a new Rotational Web Token.
import { RWT } from 'dragonstream-sdk';
const token = RWT.generate(userKey, {
releaseAt: Date.now(), // When token becomes valid
expiresAt: Date.now() + 3600000, // When token expires (1 hour later)
meta: { // Optional metadata
userId: 'user123',
permissions: ['read', 'write']
}
});
Parameters
userKey
(string, required): The user's secret key stored during signupoptions
(object, required):releaseAt
(number, required): Timestamp when token becomes validexpiresAt
(number, required): Timestamp when token expiresmeta
(object, optional): Additional data to include in the token
Returns
string
: The generated RWT token
RWT.verify()
Verifies a Rotational Web Token.
import { RWT } from 'dragonstream-sdk';
const isValid = RWT.verify(token, userKey);
if (isValid) {
// Token is valid, grant access
} else {
// Token is invalid or expired
}
Parameters
token
(string, required): The RWT token to verifyuserKey
(string, required): The user's secret key
Returns
boolean
: true
if the token is valid, false
otherwise
RWT.decode()
Decodes a Rotational Web Token without verifying it.
import { RWT } from 'dragonstream-sdk';
const decoded = RWT.decode(token);
console.log(decoded);
// {
// header: { alg: 'RWT256', typ: 'RWT' },
// payload: {
// releaseAt: 1680000000000,
// expiresAt: 1680003600000,
// meta: { userId: 'user123', permissions: ['read', 'write'] }
// }
// }
Parameters
token
(string, required): The RWT token to decode
Returns
object
: The decoded token contents without verification
RWT.getTimeWindow()
Returns the valid time window for a token.
import { RWT } from 'dragonstream-sdk';
const timeWindow = RWT.getTimeWindow(token);
console.log(timeWindow);
// {
// releaseAt: 1680000000000, // Date when token becomes valid
// expiresAt: 1680003600000, // Date when token expires
// isActive: true, // Whether token is currently valid
// timeRemaining: 1800000 // Milliseconds until expiration
// }
Parameters
token
(string, required): The RWT token to analyze
Returns
object
: Object containing time window information
Authentication Patterns
Express Middleware
import { RWT } from 'dragonstream-sdk';
import express from 'express';
const app = express();
// RWT authentication middleware
function rwtAuth(req, res, next) {
const authHeader = req.headers.authorization;
if (!authHeader || !authHeader.startsWith('RWT ')) {
return res.status(401).json({ error: 'Missing or invalid authorization header' });
}
const token = authHeader.split(' ')[1];
const userKey = getUserKeyFromDatabase(req.params.userId); // Your function to get UserKey
if (!RWT.verify(token, userKey)) {
return res.status(401).json({ error: 'Invalid or expired token' });
}
// Set decoded token information for route handlers
req.rwt = RWT.decode(token);
next();
}
// Protected route
app.get('/api/protected', rwtAuth, (req, res) => {
res.json({ data: 'Protected data', user: req.rwt.payload.meta.userId });
});
React Client Integration
// api.js
import { RWT } from 'dragonstream-sdk';
// Stored securely in localStorage or a more secure alternative
const userKey = localStorage.getItem('userKey');
export async function fetchProtectedData() {
// Generate a new token valid for the next 15 minutes
const token = RWT.generate(userKey, {
releaseAt: Date.now(),
expiresAt: Date.now() + (15 * 60 * 1000),
meta: { userId: localStorage.getItem('userId') }
});
const response = await fetch('https://api.example.com/protected', {
headers: {
'Authorization': `RWT ${token}`
}
});
return response.json();
}
Advanced Use Cases
Time-Locked Product Drop
Create tokens that only become valid at a specific future time, perfect for product launches, NFT drops, or timed content releases.
import { RWT } from 'dragonstream-sdk';
// Admin creates tokens for future product drop
function createProductDropTokens(userIds, dropTime) {
const dropTokens = {};
userIds.forEach(userId => {
const userKey = getUserKey(userId);
dropTokens[userId] = RWT.generate(userKey, {
releaseAt: dropTime,
expiresAt: dropTime + (24 * 60 * 60 * 1000), // Valid for 24 hours after drop
meta: {
userId,
productId: 'limited-edition-001'
}
});
});
return dropTokens;
}
// Frontend uses token to access product at launch time
async function purchaseProduct(token) {
const response = await fetch('/api/purchase', {
method: 'POST',
headers: {
'Authorization': `RWT ${token}`
},
body: JSON.stringify({
productId: 'limited-edition-001'
})
});
return response.json();
}
Secure File Access with Automatic Expiry
Create download links that automatically expire after a set period, without requiring server-side validation on each download.
import { RWT } from 'dragonstream-sdk';
// Generate a secure download link valid for 24 hours
function generateSecureDownloadLink(fileId, userId) {
const userKey = getUserKey(userId);
const token = RWT.generate(userKey, {
releaseAt: Date.now(),
expiresAt: Date.now() + (24 * 60 * 60 * 1000),
meta: {
fileId,
userId
}
});
return `https://files.example.com/download/${fileId}?token=${token}`;
}
// Server-side handler validates token before serving file
function handleFileDownload(req, res) {
const { fileId } = req.params;
const { token } = req.query;
const userId = extractUserIdFromToken(token); // Your function
const userKey = getUserKey(userId);
if (!RWT.verify(token, userKey)) {
return res.status(401).send('Download link expired or invalid');
}
// Token valid, serve the file
serveFile(res, fileId);
}
Event Ticket Validation
Create secure, time-limited tickets that can't be forged or reused after the event.
import { RWT } from 'dragonstream-sdk';
// Generate an event ticket valid only during event hours
function generateEventTicket(userId, eventId, eventStart, eventEnd) {
const userKey = getUserKey(userId);
// Valid from 1 hour before until the end of the event
const ticketToken = RWT.generate(userKey, {
releaseAt: eventStart - (60 * 60 * 1000), // 1 hour before event
expiresAt: eventEnd,
meta: {
userId,
eventId,
ticketType: 'standard'
}
});
return ticketToken;
}
// Verify ticket at event entrance
function verifyTicket(token, userId) {
const userKey = getUserKey(userId);
if (RWT.verify(token, userKey)) {
const decoded = RWT.decode(token);
return {
valid: true,
attendee: {
userId: decoded.payload.meta.userId,
ticketType: decoded.payload.meta.ticketType
}
};
}
return { valid: false };
}
Network Protocols
DragonNet Protocol
DragonNet is a lightweight alternative to HTTP/HTTPS that uses RWT authentication directly in the transport layer.
import { RWT } from 'dragonstream-sdk';
// Connect to a DragonNet server
const dragonnet = new RWT.DragonNet('dragon.example.com:9001', {
userKey: getUserKey(),
meta: { userId: 'user123' }
});
// Send and receive messages
dragonnet.on('open', () => {
console.log('Connected to DragonNet server');
dragonnet.send({ type: 'greeting', message: 'Hello, server!' });
});
dragonnet.on('message', (data) => {
console.log('Received:', data);
});
dragonnet.on('error', (error) => {
console.error('Connection error:', error);
});
dragonnet.on('close', () => {
console.log('Connection closed');
});
GeoNet Protocol
GeoNet extends DragonNet with geographic routing capabilities, automatically connecting to the nearest available server.
import { RWT } from 'dragonstream-sdk';
// Connect to the nearest GeoNet server
const geonet = new RWT.GeoNet('geo.example.com', {
userKey: getUserKey(),
region: 'auto', // Automatically detect closest region
meta: { userId: 'user123' }
});
// Or specify a region
const asiaGeonet = new RWT.GeoNet('geo.example.com', {
userKey: getUserKey(),
region: 'asia-southeast',
meta: { userId: 'user123' }
});
// GeoNet has the same API as DragonNet
geonet.on('open', () => {
console.log('Connected to nearest GeoNet server');
geonet.send({ type: 'ping' });
});
Security Considerations
UserKey Storage
The UserKey is the foundation of RWT security. Best practices for storing it:
- Server-side: Store hashed/encrypted in your user database
- Client-side: Use secure storage mechanisms:
- Mobile: Keychain (iOS) or Keystore (Android)
- Web: Use a combination of memory and encrypted localStorage
Token Lifespan
Choosing appropriate token lifespans is critical:
- Short-lived tokens (minutes to hours): For active user sessions
- Medium-lived tokens (hours to days): For background processes or extended access
- Long-lived tokens (days to weeks): Only for scheduled future access with appropriate safeguards
RWT vs. JWT
Feature | JWT | RWT |
---|---|---|
Verification | Requires shared secret or public/private key | Self-verifying with UserKey |
Time Sensitivity | Can include expiry but not "not before" enforcement | Built-in releaseAt/expiresAt enforced by the token itself |
Revocation | Requires blacklist/database check | Time-based automatic expiration |
Quantum Resistance | Vulnerable to future quantum computing attacks | Time-limited exposure provides quantum resistance |
Migration Guide
Migrating from JWT
-
Add UserKeys to your user database:
// During user creation or migration const userKey = RWT.generateUserKey(); // Generate a secure random key await db.users.update({ id: userId }, { userKey: encryptForStorage(userKey) });
-
Update your authentication middleware:
// Before: JWT middleware app.use(jwt({ secret: process.env.JWT_SECRET })); // After: RWT middleware app.use(async (req, res, next) => { // Extract token const token = req.headers.authorization?.split(' ')[1]; if (!token) return res.status(401).send('Unauthorized'); // Get user info from token without verification const decoded = RWT.decode(token); const userId = decoded.payload.meta.userId; // Get UserKey from database const userKey = await getUserKey(userId); // Verify token if (!RWT.verify(token, userKey)) { return res.status(401).send('Unauthorized'); } // Add decoded payload to request req.user = decoded.payload.meta; next(); });
-
Update client authentication:
// Before: JWT const token = jwt.sign({ userId }, process.env.JWT_SECRET, { expiresIn: '1h' }); // After: RWT const token = RWT.generate(userKey, { releaseAt: Date.now(), expiresAt: Date.now() + (60 * 60 * 1000), // 1 hour meta: { userId } });
Troubleshooting
Common Issues
Issue | Possible Causes | Solution |
---|---|---|
"Invalid token" error | 1. Token expired 2. Token not yet valid 3. Wrong UserKey |
Check token time window with RWT.getTimeWindow(token) |
Time synchronization issues | Server and client clocks not synchronized | Add small time buffer to releaseAt and expiresAt |
Performance concerns | Generating too many tokens | Use token caching for high-frequency operations |
Debugging Tools
// Debug token information
console.log(RWT.debug(token));
// Outputs detailed token information including timing, verification status, etc.
// Time window analysis
console.log(RWT.getTimeWindow(token));
// Shows when token becomes valid and expires