Skip to content
Moeijiro
← All projects

Case study · OAuth2 dashboard · gateway bot

Discord Automation Platform

Dashboard and bot that automate a Discord server: verification, welcome messages, roles and an audit log.

Sign in with Discord; every change re-checks permissions with Discord before it runs.

Discord SystemsAutomation
Type
Personal open-source project
Automated tests
49 (pytest)
Built with
Python · FastAPI · discord.py
Live demo
Runs locally — not hosted
Server dashboard with bot status and permission state per server

Overview

What it does

A production-shaped platform for Discord server automation: sign in with Discord, configure verification, welcome messages and role automation for a server you administrate, and read back an audit trail of everything the automation did. The interesting part is the boundaries — OAuth2 tokens that never reach the browser, a permission gate that re-checks Discord, and automations that refuse to run when Discord would reject them anyway.

Problem

Server dashboards often trust a stale permission cache, hand OAuth tokens to the browser, and let role changes fail silently when the bot sits below the target role.

Solution

The OAuth2 code flow runs server-side with tokens encrypted at rest. Every write checks both sides — the caller's Manage Server permission and the bot's own permissions and role position — before calling Discord. The API and the gateway bot share one automation service, so a join event and a dashboard click behave identically.

Screenshots

From the running application

  • Server dashboard with bot status and permission state per server
    Server dashboard with bot status and permission state per server
  • Per-server automation settings: verification, welcome message and roles
    Per-server automation settings: verification, welcome message and roles
  • Filterable audit log of automation events
    Filterable audit log of automation events
  • Sign in with Discord
    Sign in with Discord

Captured from the app running locally with its seeded demo data. Select an image to open it full size.

Architecture

How the pieces fit

DashboardReact · session cookieDiscord gatewaymember_joinFastAPIOAuth2 · permission chainGateway botdiscord.pyAutomation serviceshared by API + botDiscord OAuth2Discord RESTDatabase
  • Dashboard → FastAPI
  • Discord gateway → Gateway bot
  • FastAPI → Discord OAuth2
  • FastAPI → Automation service
  • Gateway bot → Automation service
  • Automation service → Discord REST
  • Automation service → Database
  • Core service
  • External system
  • Storage / entry point

Core features

What's in it

  • Discord login

    OAuth2 authorisation-code flow (identify, guilds); access and refresh tokens are Fernet-encrypted and never serialised into a response.

  • Verification & roles

    Verified-role flow, role add/remove with the hierarchy and integration-managed roles respected, and an optional join autorole.

  • Welcome automation

    Channel and message template with {user}, {server} and {member_count} placeholders, posted by the bot on join.

  • Audit trail

    Every event — including automation_failed — stored with actor, target, guild and metadata, on a filterable, paged page.

  • Signed webhooks

    POST /api/webhooks/custom accepts HMAC-SHA256-signed events, validated strictly and optionally announced in a channel.

  • Demo mode

    A mock Discord client implementing the same interface; the demo never invents activity, and production refuses to boot with it on.

Technical decisions

Interesting problems, and how they're solved

  1. 01

    Separate keys from one secret

    Session signing and token encryption keys are derived from SESSION_SECRET through HKDF with different labels.

  2. 02

    CSRF on the OAuth round trip

    A random state per attempt, stored in a short-lived HttpOnly cookie scoped to /api/auth and compared in constant time.

  3. 03

    Permissions are re-checked, not remembered

    Guild membership and permission bitfields are re-read from Discord on login; ADMINISTRATOR implies everything, exactly as Discord treats it.

  4. 04

    Two processes, one service

    uvicorn serves the API and python -m app.bot holds the gateway; both import the same automation service.

backend/app/core/security.py · L97–107View on GitHub ↗
def sign_payload(body: bytes, secret: str | None = None) -> str:
    """Return the ``sha256=<hex>`` signature expected in ``X-Signature``."""
    key = (secret or settings.webhook_secret).encode()
    digest = hmac.new(key, body, hashlib.sha256).hexdigest()
    return f"sha256={digest}"


def verify_signature(body: bytes, header_value: str | None) -> bool:
    if not header_value:
        return False
    return hmac.compare_digest(sign_payload(body), header_value.strip())

Stack & skills

Built with

Technology

  • Python
  • FastAPI
  • discord.py
  • Discord OAuth2
  • SQLAlchemy
  • PyJWT
  • cryptography
  • React
  • TypeScript
  • Vite

What this project demonstrates

  • Discord OAuth2
  • Discord REST & gateway
  • Permission modelling
  • Token security
  • Audit logging

Repository & demo

Run it yourself

DEMO_MODE=true (the default) swaps in a mock Discord client with three servers and a demo sign-in.

No public live demo is hosted. Everything below runs locally with Python 3.12+ and Node 20+.

$ git clone https://github.com/Moeijiro/discord-automation-platform.git
$ cd discord-automation-platform
$ make install
$ make api   # FastAPI on :8000
$ make web   # dashboard
$ make bot   # optional, needs a bot token

Have a project in mind?

I build APIs, automation systems, Discord integrations and full-stack applications. Tell me what it should do and I'll tell you how I'd build it.