OAuth Provider Setup
This guide walks you through creating OAuth applications for each platform. Lumio requires two separate sets of credentials:
- Login Credentials (ID App) — used for user authentication via OAuth login
- Channel Credentials (Channel Connections) — used for platform API access per account
These are separate OAuth applications. Never use login credentials for channel API calls.
Twitch
Developer Console
Login Credentials (ID App)
- Go to Applications → Register Your Application
- Set Name to something like
Lumio Login - Set OAuth Redirect URL to:
{ID_APP_URL}/api/auth/callback/twitch- Local:
http://localhost:4002/api/auth/callback/twitch
- Local:
- Set Category to
Website Integration - Copy Client ID and generate a Client Secret
- Add to
apps/id/.env:AUTH_TWITCH_ID=your_client_idAUTH_TWITCH_SECRET=your_client_secret
Login Scopes (requested automatically):
| Scope | Purpose |
|---|---|
openid | OpenID Connect authentication |
user:read:email | Read user email |
user:read:emotes | Read user emotes |
chat:read | Read chat messages |
chat:edit | Send chat messages |
user:write:chat | Write chat messages |
user:read:subscriptions | Read user subscriptions |
moderator:read:chatters | Read chatter list |
moderator:manage:chat_messages | Delete chat messages |
moderator:manage:banned_users | Ban/unban users |
Channel Credentials
- Create a separate application in the Twitch Developer Console
- Set OAuth Redirect URL to:
{WEB_URL}/api/connections/channel/twitch/callback- Local:
http://localhost:4000/api/connections/channel/twitch/callback
- Local:
- Users enter their own Client ID + Secret in Dashboard > Connections
Channel Scopes (27 scopes, requested automatically):
| Scope | Purpose |
|---|---|
channel:read:subscriptions | Read subscriber list and events |
channel:read:redemptions | Read channel point redemptions |
channel:manage:redemptions | Manage channel point redemptions |
channel:read:hype_train | Read hype train events |
channel:read:polls | Read poll data |
channel:manage:polls | Create and manage polls |
channel:read:predictions | Read prediction data |
channel:manage:predictions | Create and manage predictions |
channel:read:goals | Read channel goals |
bits:read | Read cheer/bits events |
moderator:read:followers | Read follower list |
moderator:read:suspicious_users | Read suspicious user flags |
moderator:manage:suspicious_users | Update suspicious user treatment |
moderator:manage:banned_users | Ban and unban users |
channel:bot | Send chat messages as the channel bot |
user:read:chat | Read chat messages |
channel:read:ads | Read ad schedule |
channel:manage:raids | Start and cancel raids |
channel:moderate | Moderate chat |
moderator:read:blocked_terms | Read blocked terms |
moderator:read:chat_settings | Read chat settings |
moderator:read:unban_requests | Read unban requests |
moderator:read:banned_users | Read banned users list |
moderator:read:chat_messages | Read chat messages as moderator |
moderator:read:warnings | Read user warnings |
moderator:read:moderators | Read moderator list |
moderator:read:vips | Read VIP list |
YouTube / Google
Developer Console
https://console.cloud.google.com/apis/credentials
Prerequisites
- Create a Google Cloud project (or use an existing one)
- Enable YouTube Data API v3 under APIs & Services > Library
- Configure OAuth consent screen under APIs & Services > OAuth consent screen
- User Type: External (or Internal for Google Workspace)
- Add the scopes listed below
- Add test users if app is in "Testing" status
Login Credentials (ID App)
- Go to APIs & Services > Credentials → Create Credentials → OAuth 2.0 Client ID
- Application type: Web application
- Set Authorized redirect URI to:
{ID_APP_URL}/api/auth/callback/google- Local:
http://localhost:4002/api/auth/callback/google
- Local:
- Copy Client ID and Client Secret
- Add to
apps/id/.env:AUTH_GOOGLE_ID=your_client_idAUTH_GOOGLE_SECRET=your_client_secret
Login Scopes:
| Scope | Purpose |
|---|---|
openid | OpenID Connect authentication |
email | User email address |
profile | User name and profile picture |
youtube.readonly | Read YouTube channel data — also used at login to fetch snippet.customUrl for the username |
youtube.force-ssl | YouTube Data API access (live chat) |
Username resolution. Right after the OAuth handshake the ID App calls youtube/v3/channels?part=snippet&mine=true with the user's fresh access token and stores snippet.customUrl (e.g. cruex_de) as the login connection's username. Without this lookup Google's OIDC profile only exposes email (typically a …@pages.plusgoogle.com pseudo-email), which would never match the YouTube display name a viewer actually @-mentions in chat. If the YouTube call fails (no channel attached to the Google account, scope revoked) we fall back to email. The handle drives both the multichat @-mention highlighter and the broadcaster-status fallback that unlocks moderation buttons before the broadcaster's first chat message.
Channel Credentials
- Create a separate OAuth 2.0 Client ID in the same Google Cloud project
- Set Authorized redirect URI to:
{WEB_URL}/api/connections/channel/google/callback- Local:
http://localhost:4000/api/connections/channel/google/callback
- Local:
- Users enter their own Client ID + Secret in Dashboard > Connections
Channel Scopes (2 scopes):
| Scope | Purpose |
|---|---|
youtube.readonly | Read channel, video, and live chat data |
youtube.force-ssl | Full YouTube Data API access (chat, comments) |
Both login and channel credentials request access_type=offline and prompt=consent to ensure refresh tokens are always issued.
Discord
Developer Console
https://discord.com/developers/applications
Login Credentials Only
Discord is login-only — there are no channel connections for Discord.
- Go to Applications → New Application
- Under OAuth2, copy Client ID and Client Secret
- Add Redirect URL:
{ID_APP_URL}/api/auth/callback/discord- Local:
http://localhost:4002/api/auth/callback/discord
- Local:
- Add to
apps/id/.env:AUTH_DISCORD_ID=your_client_idAUTH_DISCORD_SECRET=your_client_secret
Login Scopes:
| Scope | Purpose |
|---|---|
identify | Read user identity |
email | Read user email |
guilds | Read server list |
messages.read | Read messages |
Kick
Developer Console
https://kick.com/settings/developer
Login Credentials (ID App)
- Create a new application in the Kick Developer settings
- Set Redirect URL to:
{ID_APP_URL}/api/auth/callback/kick- Local:
http://localhost:4002/api/auth/callback/kick
- Local:
- Copy Client ID and Client Secret
- Add to
apps/id/.env:AUTH_KICK_ID=your_client_idAUTH_KICK_SECRET=your_client_secret
Login Scopes:
| Scope | Purpose |
|---|---|
user:read | Read user profile |
chat:write | Send chat messages |
Channel Credentials
- Create a separate application
- Set Redirect URL to:
{WEB_URL}/api/connections/channel/kick/callback- Local:
http://localhost:4000/api/connections/channel/kick/callback
- Local:
- Users enter their own Client ID + Secret in Dashboard > Connections
Channel Scopes (6 scopes):
| Scope | Purpose |
|---|---|
user:read | Read user profile information |
channel:read | Read channel information |
events:read | Read channel events |
events:subscribe | Subscribe to real-time events |
chat:write | Send chat messages |
moderation:chat_message:manage | Delete chat messages |
Trovo
Developer Console
https://developer.trovo.live/myconsole
Login Credentials (ID App)
- Create a new application in the Trovo Developer Console
- Set Redirect URL to:
{ID_APP_URL}/api/auth/callback/trovo- Local:
http://localhost:4002/api/auth/callback/trovo
- Local:
- Copy Client ID and Client Secret
- Add to
apps/id/.env:AUTH_TROVO_ID=your_client_idAUTH_TROVO_SECRET=your_client_secret
Login Scopes:
| Scope | Purpose |
|---|---|
user_details_self | Read own user details |
chat_send_self | Send chat messages |
Channel Credentials
- Create a separate application
- Set Redirect URL to:
{WEB_URL}/api/connections/channel/trovo/callback- Local:
http://localhost:4000/api/connections/channel/trovo/callback
- Local:
- Users enter their own Client ID + Secret in Dashboard > Connections
Channel Scopes (2 scopes):
| Scope | Purpose |
|---|---|
channel_details_self | Read own channel details |
channel_subscriptions | Read subscriber data |
Spotify
Developer Console
https://developer.spotify.com/dashboard
Channel Credentials Only
Spotify is channel connection only — there is no Spotify login.
- Go to Dashboard → Create App
- Set Redirect URI to:
{WEB_URL}/api/connections/channel/spotify/callback- Local:
http://localhost:4000/api/connections/channel/spotify/callback
- Local:
- Select Web API as the API
- Users enter their own Client ID + Secret in Dashboard > Connections
Channel Scopes (7 scopes):
| Scope | Purpose |
|---|---|
user-read-playback-state | Read current playback state |
user-modify-playback-state | Control playback (play, pause, skip) |
user-read-currently-playing | Read currently playing track |
playlist-read-private | Read private playlists |
playlist-read-collaborative | Read collaborative playlists |
playlist-modify-public | Modify public playlists |
playlist-modify-private | Modify private playlists |
Spotify uses Authorization: Basic base64(client_id:client_secret) for token refresh, unlike other platforms which send credentials in the POST body.
Where to Configure
Login credentials must be set in two places — the ID App .env and the API config/local.toml. The API needs them for login token refresh and Twitch chat API calls.
1. ID App (apps/id/.env)
Used by NextAuth for the OAuth login flow:
# NextAuth
AUTH_SECRET=generate-a-random-secret-here
AUTH_URL=http://localhost:4002
# Twitch
AUTH_TWITCH_ID=
AUTH_TWITCH_SECRET=
# Discord
AUTH_DISCORD_ID=
AUTH_DISCORD_SECRET=
# Google / YouTube
AUTH_GOOGLE_ID=
AUTH_GOOGLE_SECRET=
# Kick
AUTH_KICK_ID=
AUTH_KICK_SECRET=
# Trovo
AUTH_TROVO_ID=
AUTH_TROVO_SECRET=
2. API Server (config/local.toml)
Used by the API for login token refresh and Twitch chat operations. Must match the same credentials as the ID App:
[auth]
# Same credentials as AUTH_TWITCH_ID / AUTH_TWITCH_SECRET in ID App
twitch_client_id = "..."
twitch_client_secret = "..."
# Same credentials as AUTH_GOOGLE_ID / AUTH_GOOGLE_SECRET in ID App
google_client_id = "..."
google_client_secret = "..."
# Same credentials as AUTH_KICK_ID / AUTH_KICK_SECRET in ID App
kick_client_id = "..."
kick_client_secret = "..."
# Same credentials as AUTH_TROVO_ID / AUTH_TROVO_SECRET in ID App
trovo_client_id = "..."
trovo_client_secret = "..."
# Encryption key for tokens stored in the database
token_encryption_key = "generate-a-random-32-byte-key"
The credentials in config/local.toml must be identical to those in apps/id/.env. The API uses them to refresh login tokens — if they don't match, token refresh will fail silently and users will be logged out.
3. Channel Credentials (Database)
Channel connection credentials are not configured in files. Users enter their own Client ID + Secret via Dashboard > Connections, which are stored encrypted (AES-256-GCM) in the app_credentials database table.
See Also
- OAuth Credentials Architecture — Dual-credential design, encryption, token refresh
- Channel Connections & Scopes — Scope details, connection flow, storage
- Token Refresh — Automatic token refresh worker