DiSkyOAuth
The DiSkyOAuth module allows your DiSky bots to authenticate Discord users through OAuth2, providing access to user information like email, premium status, mutual servers, and more. It also enables advanced features like automatic joining to servers and token refreshing.
This module implements a complete Discord OAuth2 flow with a built-in web server to handle redirects and process authorization codes.
- User Authentication: Allow users to authorize your bot to access their Discord account data
 - Data Access: Get user's email, premium status, guilds, and more
 - Server Management: Make authenticated users join servers with specific roles and settings
 - Token Refreshing: Automatically refresh OAuth tokens when they expire
 - Comprehensive Events: Handle OAuth requests and token refresh events
 
Installation
- Download the DiSkyOAuth module from DiSky Resources
 - Place the JAR file in your 
plugins/DiSky/modulesfolder - Restart your server
 - Configure the module in 
plugins/DiSky/modules/DiSkyOAuth/config.yml 
Configuration
# The port where the redirect web server will be used
port: 16334
# The URL to redirect in case someone accesses the root of the server
redirect-url: "https://disky.me/"
# The full, accessible URL to the server, including port
# This must be added to the OAuth2 redirect URIs in your Discord application
server-url: "http://your-server-address:16334"
# Enable debug mode for detailed logs
debug: false
Important
You must set up a valid, publicly accessible URL in the server-url field. This URL must be added to your Discord application's OAuth2 redirect URIs.
Setup Discord Application
Before using the module, you need to create and configure a Discord application:
- Go to the Discord Developer Portal
 - Create a new application
 - Navigate to the OAuth2 tab
 - Add your server URL (from config) to the "Redirect URIs"
 - Copy your Client ID and Client Secret for use in DiSky
 - Set up the desired OAuth2 scopes (identify, email, guilds, etc.)
 
Usage Examples
Registering an OAuth Client
# In your define bot structure:
on ready:
    # Register the OAuth client with Discord credentials
    register oauth client named "test" with id "YOUR_CLIENT_ID" with secret "YOUR_CLIENT_SECRET" with scopes "identify", "email", "guilds" using event-bot
Creating an Authorization Flow
slash command oauth:
    bot: disky
    guilds: YOUR_GUILD_ID  # Optional: makes command only available in specific guild
    description: "Authorize with Discord"
    trigger:
        # Get OAuth URL for the registered client
        set {_url} to oauth url of client "test"
        # Create a button that links to the authorization URL
        set {_btn} to a new button:
            url: {_url}
            label: "Authorize"
            style: link
            emote: reaction "🔗"
        # Send the button to the user
        reply with hidden rich components {_btn} and store it in {_msg}
        # Store some data for later
        set {OAUTH::%discord id of event-user%::MS} to now
        set {OAUTH::%discord id of event-user%::MESSAGE} to {_msg}
Handling OAuth Requests
on oauth request received:
    # Get stored message and timestamp
    set {_msg} to {OAUTH::%discord id of oauth user%::MESSAGE}
    set {_ms} to {OAUTH::%discord id of oauth user%::MS}
    # Store the tokens
    set {TOKENS::%discord id of event-user%::ACCESS} to oauth access token
    set {TOKENS::%discord id of event-user%::REFRESH} to oauth refresh token
    set {TOKENS::%discord id of event-user%::EXPIRE} to oauth expires in
    # Display information
    add "User: %oauth user%" to {_m::*}
    add "" to {_m::*}
    add "Gathered Guilds [`%size of oauth user's guilds%`]:" to {_m::*}
    loop guilds of oauth user:
        add "- %discord name of loop-value%" to {_m::*}
    add "User Premium Type: %premium type of oauth user%" to {_m::*}
    add "User Email: ||%email of oauth user%||" to {_m::*}
    add "" to {_m::*}
    add "> **You took %difference between now and {_ms}% to authorize :>**" to {_m::*}
    # Update the message with the results
    edit {_msg} to show (join {_m::*} with nl)
Refreshing OAuth Tokens
# Refresh tokens when they expire
slash command refresh_oauth [<boolean="force">]:
    bot: disky
    description: "Refresh your OAuth Token"
    trigger:
        # Check if a token exists
        if {TOKENS::%discord id of event-user%::REFRESH} is not set:
            reply with "You didn't authorize the bot yet! Use `/oauth` first."
            stop
        # Refresh the token
        set {_refresh} to {TOKENS::%discord id of event-user%::REFRESH}
        refresh oauth token {_refresh} for event-user with client "test"
# Handle the token refresh event
on oauth token refresh:
    set {_msg} to {REFRESH::%discord id of event-user%::MESSAGE}
    # Check if the refresh failed
    if refresh failed:
        edit {_msg} to show "Failed to refresh your token! Use /oauth to authorize again."
        stop
    # Store the new tokens
    set {TOKENS::%discord id of event-user%::ACCESS} to oauth access token
    set {TOKENS::%discord id of event-user%::REFRESH} to oauth refresh token
    set {TOKENS::%discord id of event-user%::EXPIRE} to oauth expires in
    # Confirm successful refresh
    edit {_msg} to show "Token refreshed successfully!"
Make User Join a Server
# In the OAuth request event
on oauth request received:
    # Make the user join a server with specific roles
    make oauth user join server with id "YOUR_SERVER_ID" with nickname "New Member" with roles "ROLE_ID_1", "ROLE_ID_2"
Reference Guide
Events
| Event | Description | 
|---|---|
on oauth request received | 
Triggered when a user completes the OAuth2 flow | 
on oauth token refresh | 
Triggered when a token refresh is attempted | 
Expressions
| Expression | Return Type | Description | 
|---|---|---|
oauth user | 
OAuthUser | The authenticated Discord user in OAuth events | 
oauth access token | 
String | The access token provided by Discord | 
oauth refresh token | 
String | The refresh token for renewing access | 
oauth expires in | 
Timespan | How long until the access token expires | 
oauth url of client %string% | 
String | Get the authorization URL for a client | 
user's guilds | 
Guild | Get mutual guilds for the authenticated user | 
user's email | 
String | Get the email address of the authenticated user | 
user's premium type | 
String | Get the premium status of the authenticated user | 
Effects
| Effect | Description | 
|---|---|
register oauth client named %string% with id %string% with secret %string% with scopes %strings% using the bot %bot% | 
Register an OAuth client with DiSky | 
refresh oauth token %string% for %user% with client %string% | 
Refresh an OAuth token | 
make oauth user join server with id %string% [with nickname %string%] [with roles %strings%] [(muted\|deafened\|muted and deafened)] | 
Make a user join a server via OAuth | 
Conditions
| Condition | Description | 
|---|---|
refresh failed | 
Check if a token refresh attempt failed | 
Tips and Best Practices
- Security: Always keep client secrets secure and never expose them in client-side code
 - Error Handling: Always check for errors when refreshing tokens
 - Scopes: Only request the OAuth scopes you actually need
 - Storage: Store tokens securely and clear them when no longer needed
 - Expiration: Always honor token expiration times and refresh as needed
 
Requesting Minimal Scopes
Only request the scopes you need. For example, if you only need basic user information:
Troubleshooting
- Make sure your server is publicly accessible: The 
server-urlin config must be reachable from Discord's servers - Check redirect URIs: Ensure the redirect URI in your Discord application matches the 
server-urlin config - Port forwarding: If hosting on a local network, ensure the port is properly forwarded
 - Debug mode: Enable debug mode in config for detailed logs
 - Scope issues: If not receiving certain data, check if you requested the appropriate scopes