DragonFire Developer Portal

RWT Tokens Contents

Related Documentation

DragonStream: Rotational Web Tokens (RWT)

Version 2.3.1

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 and expiresAt 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

  1. Signup: Server stores only { username, passwordHash, UserKey }
  2. Issue RWT: Generate a token with RWT.generate(UserKey, { releaseAt, expiresAt, meta })
  3. Client Request: Attach Authorization: RWT <token> header or connect via rwt:// protocol
  4. Server Validation: Verify with RWT.verify(token, UserKey)
RWT Architecture
RWT Authentication Flow

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 signup
  • options (object, required):
    • releaseAt (number, required): Timestamp when token becomes valid
    • expiresAt (number, required): Timestamp when token expires
    • meta (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 verify
  • userKey (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:

  1. Server-side: Store hashed/encrypted in your user database
  2. 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

  1. 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) });
  2. 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();
    });
  3. 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