Security & Data Integrity
How Euler Stream OAuth protects user sessions with envelope encryption and zero-knowledge architecture.
Security is at the core of the Euler Stream OAuth system. This document explains our security architecture, why your users' TikTok sessions are protected even in worst-case scenarios, and what this means for your integration.
Zero-Knowledge Session Storage
When a user authenticates via QR code, their TikTok session credentials are never stored in plaintext—not in our database, not in logs, not anywhere. Here's why this matters:
The Problem with Traditional Storage
In a typical OAuth system, session credentials are stored in a database, possibly encrypted with a master key. If an attacker gains database access and the master key, they can decrypt all user sessions.
Our Solution: Envelope Encryption
Euler Stream uses envelope encryption where the decryption key is derived from the tokens themselves:
┌─────────────────────────────────────────────────────────────────┐
│ Session Encryption │
├─────────────────────────────────────────────────────────────────┤
│ │
│ User's TikTok Session ID (sensitive) │
│ │ │
│ ▼ │
│ ┌─────────────────┐ │
│ │ Encrypt │◄──── Encryption Key derived from: │
│ └────────┬────────┘ • Access Token │
│ │ • Refresh Token │
│ ▼ │
│ Encrypted Session Blob (stored in database) │
│ │
│ To decrypt, you MUST have: │
│ • The encrypted blob (database) │
│ • The access token (client only) │
│ • The refresh token (client only) │
│ │
└─────────────────────────────────────────────────────────────────┘What This Means
-
Database breach = useless data: If an attacker compromises our database, they get encrypted blobs that cannot be decrypted without the corresponding tokens (which are only held by your application).
-
The developer has no access: Even we, the developers of Euler Stream, cannot decrypt user sessions. We do not have access to the tokens stored in your application.
-
Decryption only in memory: The session ID only exists in decrypted form in RAM during active API requests. It is never written to disk, logs, or persistent storage in plaintext.
-
Per-session isolation: Each user's session has a unique encryption key. Compromising one doesn't affect others.
Security Implications for Your Application
Because of this architecture, you are responsible for secure token storage:
Token Security Best Practices
// ❌ BAD: Storing tokens in plaintext
await db.users.update({
id: userId,
tiktokAccessToken: tokens.access_token,
tiktokRefreshToken: tokens.refresh_token,
});
// ✅ GOOD: Encrypt tokens at rest
import { createCipheriv, createDecipheriv, randomBytes } from 'crypto';
const ENCRYPTION_KEY = process.env.TOKEN_ENCRYPTION_KEY!; // 32 bytes
function encryptToken(token: string): string {
const iv = randomBytes(16);
const cipher = createCipheriv('aes-256-gcm', Buffer.from(ENCRYPTION_KEY, 'hex'), iv);
let encrypted = cipher.update(token, 'utf8', 'hex');
encrypted += cipher.final('hex');
const authTag = cipher.getAuthTag();
return `${iv.toString('hex')}:${authTag.toString('hex')}:${encrypted}`;
}
function decryptToken(encryptedData: string): string {
const [ivHex, authTagHex, encrypted] = encryptedData.split(':');
const decipher = createDecipheriv(
'aes-256-gcm',
Buffer.from(ENCRYPTION_KEY, 'hex'),
Buffer.from(ivHex, 'hex')
);
decipher.setAuthTag(Buffer.from(authTagHex, 'hex'));
let decrypted = decipher.update(encrypted, 'hex', 'utf8');
decrypted += decipher.final('utf8');
return decrypted;
}
// Store encrypted
await db.users.update({
id: userId,
tiktokAccessToken: encryptToken(tokens.access_token),
tiktokRefreshToken: encryptToken(tokens.refresh_token),
});Additional Security Measures
- Use environment variables for client secrets, never commit them
- Implement rate limiting on your OAuth callback endpoint
- Validate the
stateparameter to prevent CSRF attacks - Use HTTPS everywhere (required for redirect URIs except localhost)
- Rotate your client secret periodically via the dashboard
- Audit access logs to detect suspicious activity
What Happens If...
Your Database Is Breached
If your application's database is compromised and tokens are stolen:
- The attacker can use the tokens to make API requests as your users
- Immediately regenerate your client secret in the Euler Stream dashboard
- All existing tokens become invalid
- Users will need to re-authorize
Euler Stream's Database Is Breached
If Euler Stream's database is compromised:
- Attackers get encrypted session blobs
- These cannot be decrypted without your users' tokens
- No user sessions are compromised
- No action required from you (but we'd notify you anyway)
A User's Tokens Are Leaked
If a specific user's tokens are leaked:
- Revoke those tokens immediately:
- The user must re-authorize
- Other users are unaffected
Token Transmission Security
HTTPS Requirement
All OAuth endpoints use HTTPS. Redirect URIs must also use HTTPS in production (localhost is exempt for development convenience).
Logging and Debugging
What We Log
- Request metadata (timestamp, endpoint, response code)
- Client ID (to identify your application)
- Error messages (without sensitive data)
What We Never Log
- Access tokens
- Refresh tokens
- Session IDs (encrypted or plaintext)
- QR code contents
- User credentials
Your Logging
Ensure your application doesn't accidentally log tokens:
// ❌ BAD: Logging the full response
console.log('Token response:', tokenResponse);
// ✅ GOOD: Log only safe data
console.log('Token exchange successful', {
expiresIn: tokenResponse.expires_in,
scopes: tokenResponse.scope,
});Security Summary
| Layer | Protection |
|---|---|
| Session Storage | Envelope encryption with per-session keys |
| Database Breach (Euler Stream) | Sessions unrecoverable without client tokens |
| Database Breach (Your App) | Depends on your encryption implementation |
| Developer Access | Zero-knowledge: we cannot access user sessions |
| Memory | Sessions decrypted only in RAM during requests |
Compliance Considerations
GDPR / Data Privacy
- User sessions are encrypted and cannot be accessed without tokens
- Tokens can be revoked at any time, making data irrecoverable
- Right to deletion: revoke tokens and delete from your database
Security Audits
If your organization requires security documentation:
- Our OAuth implementation follows RFC 6749 (OAuth 2.0)
- Envelope encryption provides defense-in-depth
- Zero-knowledge architecture limits blast radius of breaches
Reporting Security Issues
If you discover a security vulnerability:
- Do not disclose it publicly
- Email security concerns to the development team
- Include steps to reproduce
- We'll respond within 48 hours
Key Takeaways
- We can't see your users' sessions - envelope encryption ensures this
- Database breaches don't expose sessions - encrypted data is useless without tokens
- You must secure your tokens - they're the keys to the kingdom
- Revocation is immediate and permanent - when tokens are revoked, sessions become unrecoverable