Game Authentication
Authenticate users with your game using the Intraverse authentication service.
Overview
The Intraverse authentication service provides a secure way to authenticate users with your game. Instead of implementing your own authentication system, you can redirect users to the Intraverse authentication service and receive authentication data through a custom protocol URL.
Authentication Flow
- Generate Authentication Hash: Your game generates a UUID v4 hash
- Redirect to Auth Service: Redirect users to
https://play.intraverse.io/ - User Authentication: Users authenticate through the Intraverse service
- Callback Protocol: After successful authentication, the service opens a custom protocol URL with authentication data
Implementation
Step 1: Generate Authentication Hash
Generate a UUID v4 hash that will be used to identify the authentication session:
import { v4 as uuidv4 } from "uuid";
const authHash = uuidv4(); // e.g., "12345678-1234-1234-1234-123456789012"
Step 2: Redirect to Authentication Service
Redirect users to the Intraverse authentication service with your client key and generated hash:
const clientKey = "your-client-key";
const authHash = uuidv4();
const authUrl = `https://play.intraverse.io/magic-login?hash=${authHash}&game=${clientKey}`;
// Redirect user to authentication service
window.location.href = authUrl;
// or for mobile apps: open URL in browser
Step 3: Handle Authentication Callback
After successful authentication, the service will open a custom protocol URL with the authentication data. Your game should register a custom protocol handler to receive this data.
Custom Protocol URL Structure
The authentication service will open a URL with the following structure:
{game.magicLinkProtocol}/callback/{idToken}/{refreshToken}/{userId}
Protocol URL Parameters
| Parameter | Type | Description |
|---|---|---|
idToken | string | Firebase ID token containing user authentication data |
refreshToken | string | Firebase refresh token for token renewal |
userId | string | User ID from Intraverse |
Example Protocol URL
game/callback/eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c/eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c/user-123
Protocol Handler Registration
Desktop Applications
Register your custom protocol in your application:
// Example for Electron
app.setAsDefaultProtocolClient("game");
// Handle protocol activation
app.on("open-url", (event, url) => {
const urlObj = new URL(url);
if (urlObj.protocol === "game:" && urlObj.pathname.startsWith("//callback/")) {
const pathParts = urlObj.pathname.split("/");
const idToken = pathParts[3]; // /callback/idToken/refreshToken/userId
const refreshToken = pathParts[4];
const userId = pathParts[5];
// Handle authentication data
handleAuthentication(idToken, refreshToken, userId);
}
});
Mobile Applications
For mobile apps, register the custom protocol in your app configuration:
iOS (Info.plist)
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLName</key>
<string>com.yourgame.auth</string>
<key>CFBundleURLSchemes</key>
<array>
<string>game</string>
</array>
</dict>
</array>
Android (AndroidManifest.xml)
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="game" />
</intent-filter>
</activity>
Unity (All Platforms)
For Unity projects, the Universal Deep Linking package simplifies deep link handling across all supported platforms (iOS, Android, desktop, etc.).
Install the package from the Unity Asset Store: Universal Deep Linking - Asset Store
Step 1: Redirect Users to Intraverse Login
When you want to connect users to their Intraverse account, open the following URL in the user's browser:
https://play.intraverse.io/magic-login?game={your-game-client-key}
Replace {your-game-client-key} with the client key assigned to your game.
Step 2: Handle the Deep Link Callback
After the user authenticates, Intraverse will trigger a deep link back into your game with the following structure:
{magicLinkProtocol}/callback/{idToken}/{refreshToken}/{userId}
For example, if your game's magic link protocol is intraversekarting://kartinggame, the callback URL would look like:
intraversekarting://kartinggame/callback/eyJhbGciOi.../dHlwIjoiSl.../user-abc-123
With the Universal Deep Linking package integrated, your Unity client will receive this URL automatically. Parse it to extract:
idToken— JWT token for authenticating API requestsrefreshToken— token used to renew theidTokenwhen it expiresuserId— the user's Intraverse ID
Step 3: Call Authenticated APIs
To call user-authenticated Intraverse APIs, pass the idToken in the Authorization header:
Authorization: Bearer {idToken}
For example, you can fetch the user's Intraverse profile to display which account they are logged in with during a tournament.
Step 4: Refresh the Token (Optional)
If you need to revalidate or refresh an expired idToken, use the Google Identity Toolkit API with the googleApiKey provided to you:
string refreshTokenUrl = $"https://securetoken.googleapis.com/v1/token?key={googleApiKey}";
In most cases this is not necessary — fetching the userId once during login is sufficient for typical game integrations.
Security Considerations
- Hash Expiration: Generated hashes should expire after a reasonable time (e.g., 10 minutes)
- Token Validation: Always validate the JWT token on your server
- Protocol Security: Ensure your custom protocol handler validates the hash matches the one you generated
- HTTPS Only: Always use HTTPS for the authentication service URL
Example Implementation
class IntraverseAuth {
constructor(clientKey) {
this.clientKey = clientKey;
this.pendingAuths = new Map();
}
async authenticate() {
// Generate authentication hash
const authHash = uuidv4();
// Store pending authentication
this.pendingAuths.set(authHash, {
timestamp: Date.now(),
resolved: false,
});
// Redirect to authentication service
const authUrl = `https://play.intraverse.io/magic-login?hash=${authHash}&game=${this.clientKey}`;
window.location.href = authUrl;
// Return promise that resolves when authentication completes
return new Promise((resolve, reject) => {
this.pendingAuths.get(authHash).resolve = resolve;
this.pendingAuths.get(authHash).reject = reject;
// Set timeout for authentication
setTimeout(() => {
if (!this.pendingAuths.get(authHash).resolved) {
this.pendingAuths.delete(authHash);
reject(new Error("Authentication timeout"));
}
}, 600000); // 10 minutes
});
}
handleAuthCallback(url) {
const urlObj = new URL(url);
if (urlObj.protocol === "game:" && urlObj.pathname === "//auth") {
const params = new URLSearchParams(urlObj.search);
const hash = params.get("hash");
const token = params.get("token");
const user = params.get("user");
const expires = params.get("expires");
const pendingAuth = this.pendingAuths.get(hash);
if (pendingAuth && !pendingAuth.resolved) {
pendingAuth.resolved = true;
this.pendingAuths.delete(hash);
pendingAuth.resolve({ token, user, expires });
}
}
}
}
Getting an API Key
- Contact our team at hello@intraverse.com
- Receive your API key and documentation
Security Best Practices
🔑 API Key Security
- Never expose server API keys in client-side code
- Use environment variables to store sensitive credentials
- Rotate API keys regularly (recommended: every 90 days)
- Use different keys for different environments (dev, staging, production)
- Monitor API key usage for suspicious activity
🎮 Client Key Security
- Client keys are safe to include in client applications
- Client keys are public identifiers for your game
- Never use client keys for server-only operations
- Keep client keys consistent across your game versions
🔐 JWT Token Security
- Validate JWT tokens on your server
- Check token expiration before using
- Never store tokens in insecure storage
- Implement proper session management
- Log out users when tokens expire
🌐 Network Security
- Use HTTPS for all API communications
- Validate SSL certificates in production
- Implement certificate pinning for mobile apps
- Use secure WebSocket connections if applicable
🔍 Authentication Flow Security
- Validate authentication hashes match your generated hash
- Set appropriate hash expiration times (recommended: 10 minutes)
- Implement timeout handling for authentication flows
- Log authentication attempts for security monitoring
- Handle authentication errors gracefully
📱 Client Application Security
- Never store sensitive data in client storage
- Use secure communication for all API calls
- Implement proper error handling
- Validate all user inputs before sending to API
- Use secure random generation for authentication hashes
Next Steps
- Learn about API Reference
- Check the Security Guide