Secure OAuth 2.0 for CLI applications - Written in Rust, works everywhere π¦
OAuth authentication made simple for command-line tools. No more copying tokens or managing credentials manually!
π Multiple OAuth Flows
- Device Code Flow (perfect for CLI!)
- Authorization Code Flow with PKCE
- Automatic browser handling
π Secure by Default
- OS credential manager integration (Keychain/Credential Manager)
- Cross-process token refresh locking
- Automatic token refresh
β‘ Developer Friendly
- Provider presets (GitHub, Google, Microsoft, GitLab, Tuist)
- One-line configuration
- Automatic expiration handling
π Cross-Platform
- Linux, macOS, Windows
- x86_64 and ARM64
Rust:
[dependencies]
schlussel = "0.1"Swift Package Manager:
.binaryTarget(
name: "Schlussel",
url: "https://github.com/tuist/schlussel/releases/download/0.5.0/Schlussel.xcframework.zip",
checksum: "36c002746caa5c1af8c6edea751ad971c5b67940775dba398308207dc981e253"
)use schlussel::prelude::*;
use std::sync::Arc;
let storage = Arc::new(SecureStorage::new("my-app").unwrap());
let config = OAuthConfig::github("your-client-id", Some("repo user"));
let client = OAuthClient::new(config, storage);
// That's it! Opens browser, handles OAuth, returns token
let token = client.authorize_device().unwrap();π Full Documentation
Quick links:
- π Quick Start Guide
- π Provider Presets - GitHub, Google, Microsoft, etc.
- πΎ Storage Options - Secure, File, or Memory
- π Token Refresh - Automatic refresh strategies
- π± Swift/iOS Integration - XCFramework usage
// 50+ lines of boilerplate
// Manual token expiration checking
// Race conditions with multiple processes
// Plaintext tokens in files
// Complex OAuth flow management// 3 lines total
let storage = Arc::new(SecureStorage::new("app").unwrap());
let config = OAuthConfig::github("client-id", Some("repo"));
let token = OAuthClient::new(config, storage).authorize_device().unwrap();β
CLI tools that need GitHub/GitLab API access
β
Build tools that integrate with cloud services
β
Developer tools with OAuth authentication
β
Cross-platform desktop applications
β
CI/CD tools with secure credential management
βββββββββββββββββββ
β Your CLI App β
ββββββββββ¬βββββββββ
β
ββββββΌββββββ
β Schlusselβ
ββββββ¬ββββββ
β
ββββββΌβββββββββββββββββββββββββ
β Storage Backend β
βββββββββββββββββββββββββββββββ€
β SecureStorage (OS Keyring) β β Recommended
β FileStorage (JSON files) β
β MemoryStorage (In-memory) β
βββββββββββββββββββββββββββββββ
Tokens stored in OS credential manager (Keychain on macOS, Credential Manager on Windows, libsecret on Linux)
OAuthConfig::github("id", Some("repo")) // GitHub
OAuthConfig::google("id", Some("email")) // Google
OAuthConfig::microsoft("id", "common", None) // Microsoft
OAuthConfig::gitlab("id", None, None) // GitLab
OAuthConfig::tuist("id", None, None) // Tuistlet refresher = TokenRefresher::new(client);
let token = refresher.get_valid_token("key").unwrap();
// Auto-refreshes if expired!Multiple processes can safely refresh the same token without race conditions
Check out examples/ for working code:
- π GitHub Device Flow
- π GitHub with Callback
- π Token Refresh
- β‘ Automatic Refresh
- π Secure Storage
- π Cross-Process Refresh
Contributions welcome! Please ensure:
- β
Tests pass:
cargo test - β
Code formatted:
cargo fmt - β
Clippy clean:
cargo clippy
See LICENSE for details.
- π Documentation
- π Issues
- π Changelog
- π API Docs
Made with π by the Tuist team