Expand description
Twitch OAuth Token Library
This library provides a comprehensive solution for Twitch OAuth 2.0 authentication, supporting both app authentication and user authentication flows with built-in CSRF protection, connection pooling, and type safety.
§Core Concepts
§Authentication Flows
App Authentication (TwitchOauth<AppAuth>)
- For server-to-server API calls that don’t require user context
- Access public data (streams, games, public user info)
- No user interaction or redirect URI required
- Use
TwitchOauth::app_access_token()to get tokens
User Authentication (TwitchOauth<UserAuth>)
- For applications that need to act on behalf of users
- Access user-specific data (follows, subscriptions, chat)
- Requires redirect URI and user consent flow
- Use
TwitchOauth::authorization_url()andTwitchOauth::exchange_code()
§Type Safety
The library uses Rust’s type system to prevent common OAuth mistakes:
TwitchOauth<AppAuth>only allows app authentication operationsTwitchOauth<UserAuth>only allows user authentication operations- No way to accidentally call user methods without a redirect URI
§Examples
§App Authentication Flow
use twitch_oauth_token::TwitchOauth;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let oauth = TwitchOauth::new("client_id", "client_secret");
let token = oauth.app_access_token().await?;
println!("App token: {}", token.access_token.secret());
println!("Expires in: {} seconds", token.expires_in);
Ok(())
}§User Authentication Flow
use std::str::FromStr;
use twitch_oauth_token::{
scope::{ChannelScopes, ChatScopes},
AuthCallback,
RedirectUrl, TwitchOauth,
};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Setup OAuth client with redirect URI
let oauth = TwitchOauth::new("your_client_id", "your_client_secret")
.with_redirect_uri(RedirectUrl::from_str("http://localhost:3000/auth/callback")?);
// Create authorization URL with specific scopes
let mut auth_request = oauth.authorization_url();
auth_request.scopes_mut()
.send_chat_message()
.get_channel_emotes()
.modify_channel_info();
let auth_url = auth_request.url();
println!("Visit: {}", auth_url);
// In your callback handler:
// let callback: AuthCallback = /* parse from URL */;
// let token = oauth.exchange_code(callback.code, callback.state).await?;
Ok(())
}§Handling OAuth Callbacks
When the user grants access, Twitch redirects them back to your redirect URL with the authorization result.
§Raw HTTP Format
If you’re not using a web framework, the callback arrives as a raw HTTP request:
GET /?code=...&scope=...&state=... HTTP/1.1The query parameters contain:
code: Authorization code to exchange for tokensstate: CSRF protection token (must match what you sent)scope: Space-separated scopes that were actually granted
§Processing the Callback
Regardless of how you extract the parameters, the token exchange process is the same.
The library provides AuthCallback to parse OAuth callback parameters.
Use it to extract the authorization code and state
use twitch_oauth_token::{AuthCallback, TwitchOauth, UserAuth};
async fn handle_oauth_callback(
oauth: &TwitchOauth<UserAuth>,
query_params: AuthCallback,
) -> Result<(), twitch_oauth_token::Error> {
let token = oauth
.exchange_code(query_params.code, query_params.state)
.await?;
// Store the tokens securely for future API calls
// store_user_tokens(user_id, &token).await?;
Ok(())
}§Working with Scopes
The library provides type-safe scope builders organized by API category:
use twitch_oauth_token::scope::{
ChannelScopes, ChatScopes, ModerationScopes,
SubscriptionScopes, UserScopes
};
let mut auth_request = oauth.authorization_url();
// Chat-related scopes
auth_request.scopes_mut()
.send_chat_message() // Send chat messages
.get_user_emotes() // Read user's emotes
.get_chatters() // Read chatters list
.send_chat_announcement(); // Send announcements
// Channel management scopes
auth_request.scopes_mut()
.modify_channel_info() // Update channel info
.get_channel_followers() // Read followers
.channel_ban_unban(); // Ban/unban users
// Moderation scopes
auth_request.scopes_mut()
.ban_user() // Ban users
.delete_chat_messages() // Delete messages
.update_automod_settings(); // Manage AutoMod
// Or add entire API categories at once
auth_request.scopes_mut()
.chat_api() // All chat-related scopes
.moderation_api() // All moderation scopes
.users_api(); // All user-related scopes§Token Management
§Refresh
Returns UserToken.
let new_token = oauth.refresh_access_token(refresh_token).await?;§Validation
Returns TokenInfo.
let token_info = oauth.validate_access_token(&access_token).await?;§Revocation
oauth.revoke_access_token(&access_token).await?;§Security Features
§CSRF Protection
The library automatically generates and validates CSRF tokens using HMAC-SHA256:
- Tokens are cryptographically signed with a random secret key
- Automatic validation prevents CSRF attacks
- Configurable expiration and clock skew tolerance
- Self-contained validation without database storage
Important for multi-server deployments:
- By default, each
TwitchOauthinstance generates a random secret key - For load-balanced or clustered environments, use
TwitchOauth<UserAuth>::with_secret_keyto share the same secret across all instances - Without a shared secret key, tokens generated on one server will fail validation on another
§CSRF Configuration
You can customize CSRF token validation behavior:
use twitch_oauth_token::{csrf::CsrfConfig, TwitchOauth};
// Default: 30 minutes expiry, no clock skew tolerance
let oauth = TwitchOauth::new("client_id", "client_secret");
// Custom: 10 minutes expiry, 60 seconds clock skew tolerance
let oauth = TwitchOauth::new("client_id", "client_secret")
.with_csrf_config(CsrfConfig::new(60, 600));
// Strict: 5 minutes expiry, no clock skew tolerance
let oauth = TwitchOauth::new("client_id", "client_secret")
.with_csrf_config(CsrfConfig::default().with_max_age(300));When to customize:
- High-security apps: Shorter expiry times (300-900 seconds)
- Mobile apps: Clock skew tolerance (30-60 seconds) for device time differences
- Server clusters: Clock skew tolerance for distributed systems and shared secret key via
TwitchOauth<UserAuth>::with_secret_key
§Secure Defaults
- HTTPS enforcement (HTTP requests are blocked)
- Secure HTTP headers (no-cache, strict security)
- TLS 1.2+ minimum with certificate validation
- HTTP/2 required (no HTTP/1.1 fallback)
- Connection pooling with idle timeouts
§Error Handling
The library provides comprehensive error types:
match oauth.app_access_token().await {
Ok(response) => { /* success */ }
Err(e) => {
// Network/HTTP errors (connection issues, timeouts, DNS failures)
if e.is_request_error() {
eprintln!("Network error: {}", e);
// Common causes:
// - No internet connection
// - Twitch API is down
// - Firewall blocking requests
// - DNS resolution failure
// OAuth-specific errors (invalid credentials, CSRF mismatch)
} else if e.is_oauth_error() {
eprintln!("OAuth error: {}", e);
// Common causes:
// - Invalid client_id or client_secret
// - CSRF token validation failed
// - Authorization code expired or invalid
// - Redirect URI mismatch
// JSON deserialization errors (response doesn't match expected structure)
} else if e.is_decode() {
eprintln!("Deserialization error: {}", e);
if let Some(raw) = e.raw() {
eprintln!("Raw response body: {}", raw);
}
// Common causes:
// - Twitch API response schema changed
// - Missing or unexpected fields in JSON
// - Type mismatch (expected number, got string)
// - Invalid data format
}
}
}§Development Server
For local development, use the built-in oneshot server to handle OAuth callbacks:
use std::{str::FromStr, time::Duration};
use twitch_oauth_token::{oneshot, scope::ChatScopes, AuthCallback, RedirectUrl, TwitchOauth};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let oauth = TwitchOauth::new("client_id", "client_secret")
.with_redirect_uri(RedirectUrl::from_str("http://localhost:3000")?);
let mut auth_request = oauth.authorization_url();
auth_request.scopes_mut().chat_api();
println!("Visit this URL to authorize:");
println!("{}", auth_request.url());
println!("Waiting for callback...");
let config = oneshot::Config::new()
.with_port(3000)
.with_duration(Duration::from_secs(120));
// Wait up to 2 minutes for the user to complete OAuth flow
match oneshot::listen::<AuthCallback>(config).await {
Ok(callback) => {
let token = oauth
.exchange_code(callback.code, callback.state)
.await?;
println!("Successfully got user token!");
}
Err(e) => {
eprintln!("OAuth flow failed: {}", e);
}
}
Ok(())
}§HTTP Client Configuration
The default HTTP client works for most applications.
For custom configuration, see client.
§Testing
For local testing with Twitch Mock API, see test_oauth (requires test feature).
Re-exports§
pub use scope::Scope;
Modules§
- client
- Global HTTP Client Management for Oauth Request
- csrf
- oneshot
oneshot - Oneshot OAuth callback server for development and testing.
- scope
- test_
oauth test - Testing with Mock API
Structs§
- Access
Token - AppAuth
- App Authentication (Client Credentials Flow)
- AppToken
- https://dev.twitch.tv/docs/authentication/getting-tokens-oauth/#client-credentials-grant-flow
- Auth
Callback - AuthUrl
- Authorization
Code - Authrozation
Request - https://dev.twitch.tv/docs/authentication/getting-tokens-oauth/#authorization-code-grant-flow
- Client
Id - Client
Secret - Error
- Redirect
Url - Refresh
Token - Revocation
Url - Token
Info - https://dev.twitch.tv/docs/authentication/validate-tokens/
- Token
Url - Twitch
Oauth - OAuth client for Twitch API authentication
- User
Auth - User Authentication (Authorization Code Flow)
- User
Token - Validate
Url