1

System Overview

BlueDesk connects employees to all internal tools through a single Microsoft login. Three user roles interact with the system through a Next.js frontend backed by a Go API server, a PostgreSQL database, and Microsoft Entra ID for authentication.

👤
Regular User
View & launch assigned apps
👥
Application Admin
Elevated features in specific apps
🔒
IT Admin
Full system control
Browser requests
Next.js Frontend
Port 3000 · TypeScript · Tailwind CSS · SSR
API calls (JSON)
Microsoft Entra ID
OAuth 2.0 + Graph API
OAuth / Graph
Go Backend
Port 8080 · Chi Router · JWT signing
Launch JWT
💻
Integrated Apps
Consume launch JWTs
SQL queries
🗃
PostgreSQL
Port 5432 · blue_desk_admin · 4 tables
2

Three Domains

BlueDesk is organized into three bounded domains with a strict dependency chain. Each domain has clear responsibilities and defined interfaces.

1

Authentication

Foundational domain. Establishes user identity via Microsoft Entra ID.

  • OAuth 2.0 flow with Microsoft Entra ID
  • Session JWT issuance and validation
  • Token refresh lifecycle
  • Login / logout handling
  • Cookie security and session expiry (1h)
  • CSRF state validation (oauth_state cookie)
  • HTTP-only cookie management (session_token, refresh_token, user_info)
2

User & Access Management

Administrative domain. Manages who can access what.

  • User directory (Microsoft Graph API sync)
  • Application registry (register, configure, deactivate)
  • Per-user, per-app permission assignment
  • Granular roles: View, Edit, Admin, Configure
  • User activation / deactivation (soft delete)
3

App Launcher

Employee-facing domain. The portal that users interact with daily.

  • Launcher page with app tiles
  • Per-app launch JWT generation
  • User redirect to target applications
  • Shows only apps assigned to user
  • IT Admins get App Admin in all apps

Dependency Chain

Authentication
User & Access Management
App Launcher

Each domain depends on the one before it. Authentication is foundational.

3

Authentication Flow

The complete OAuth 2.0 authorization code flow with Microsoft Entra ID, from the user clicking "Sign In" through to landing on their dashboard.

sequenceDiagram
    autonumber
    actor User
    participant FE as Next.js Frontend
(Port 3000) participant BE as Go Backend
(Port 8080) participant MS as Microsoft Entra ID participant DB as PostgreSQL User->>FE: Click "Sign In with Microsoft" FE->>BE: GET /api/v1/auth/login BE->>BE: Generate CSRF state + oauth_state cookie BE-->>FE: auth_url + Set-Cookie: oauth_state FE->>MS: Redirect to auth_url User->>MS: Enter credentials (+ 2FA) MS->>BE: GET /api/v1/auth/callback?code=...&state=... BE->>BE: Validate CSRF (cookie vs query param) BE->>MS: Exchange auth code for access token MS-->>BE: Access token + user info BE->>DB: Find or create user record DB-->>BE: User data BE->>FE: Set-Cookie: session_token, refresh_token, user_info FE->>BE: GET /api/v1/user/me (verify role) alt IT Admin FE->>User: Show Admin Dashboard else Regular / App Admin FE->>User: Show App Launcher end Note over User,DB: First-time users are auto-created with no app access.
IT admin must assign applications.
4

App Launch Flow

When a user clicks on an application tile, BlueDesk generates a per-app JWT containing the user's identity and permissions, then redirects to the target app.

sequenceDiagram
    autonumber
    actor User
    participant FE as Next.js Frontend
    participant BE as Go Backend
    participant DB as PostgreSQL
    participant App as Target Application

    User->>FE: Click app tile in launcher
    FE->>BE: POST /api/v1/launcher/apps/{id}
    BE->>DB: Check user_app_permissions
    DB-->>BE: Permission record (role, can_view, can_edit, ...)

    alt No permission found
        BE-->>FE: 403 Forbidden
        FE-->>User: "Access denied" message
    else Has permission
        BE->>BE: Generate launch JWT with
user identity + app permissions BE-->>FE: Launch JWT + app URL FE->>App: Redirect with JWT App->>App: Validate JWT signature App-->>User: Auto-logged in, permissions applied end Note over BE,App: The launch JWT is distinct from the session JWT.
It is scoped to a single application.
5

Database Schema

Four tables in the blue_desk_admin database. The junction table user_app_permissions connects users to applications with granular role-based access.

apps
ColumnTypeKey
iduuidPK
namestring
display_namestring
access_typestring
app_urlstring
public_urlstring
is_activeboolean
users
ColumnTypeKey
iduuidPK
emailstring
microsoft_idstring
is_it_adminboolean
is_activeboolean
security_levelstring
session_timeoutint
user_app_permissions
ColumnTypeKey
iduuidPK
user_iduuidFK → users
app_iduuidFK → apps
app_rolestring
can_viewboolean
can_editboolean
can_adminboolean
can_configureboolean
user_sessions
ColumnTypeKey
iduuidPK
user_iduuidFK → users
token_idstring
expires_attimestamp
is_activeboolean

Relationships

users 1 ——< N user_app_permissions One user, many permission grants
apps 1 ——< N user_app_permissions One app, many permission grants
users 1 ——< N user_sessions One user, many sessions
6

Application Integration Types

BlueDesk supports two integration models for internal applications, depending on whether the app has a public-facing interface or is admin-only.

Admin-Only

Admin-Only Apps

Accessible only through BlueDesk by authenticated administrators. No public URL exists.

  1. Admin signs into BlueDesk via Microsoft SSO
  2. Admin sees app tile in launcher
  3. BlueDesk generates launch JWT with admin permissions
  4. Admin is redirected to the app's admin panel URL
  5. App validates JWT and grants access

Examples: Internal reporting tools, configuration dashboards, system monitors

Dual-Access

Dual-Access Apps

Two entry points: a public interface with PIN auth, and an admin panel via BlueDesk JWT.

  1. Public path: Regular users access app at public URL with PIN auth
  2. Admin path: Admin signs into BlueDesk via Microsoft SSO
  3. BlueDesk generates launch JWT with admin permissions
  4. Admin is redirected to the app's admin panel URL
  5. App validates JWT and grants elevated access

Examples: Vehicle tracking (users log vehicles with PIN, admins configure via BlueDesk), queue management systems

7

JWT Token Structure

BlueDesk uses two distinct JWT tokens. Understanding the difference is critical: the session JWT is about who you are; the launch token is about what you can do in a specific app.

Session JWT

Authentication Domain

Proves the user is authenticated with BlueDesk. Issued after successful Microsoft OAuth login. Expires after 1 hour.

Used for: Authenticating API requests to the BlueDesk backend. Stored in an HTTP-only session_token cookie (not localStorage).

Contains: User identity, admin status, session metadata.

Consumed by: BlueDesk backend only.

Launch Token

App Launcher Domain

Proves the user is authorized for a specific application. Generated on-demand when the user clicks an app tile.

Used for: Authenticating the user at the target application. Passed during redirect.

Payload:

{
  "user_id": "uuid",
  "email": "user@example.com",
  "is_it_admin": false,
  "app_role": "user",
  "can_view": true,
  "can_edit": false,
  "can_admin": false,
  "can_configure": false,
  "app_id": "uuid",
  "app_name": "app-slug",
  "exp": 1234567890
}

Consumed by: The target integrated application.

8

Permission Matrix

Permissions are assigned per-user, per-application. Each permission grant specifies a role and four boolean capabilities. Roles are presets; individual flags can be customized.

Role View Edit Admin Configure Typical Use
User View data only
User (Edit) Data entry
App Admin Full control
Note: IT Admins automatically receive App Admin permissions in ALL applications they access, regardless of explicit permission grants. This is enforced at the backend level during launch token generation.
9

Design System

Brand guidelines, typography, color palette, localization strategy, and shared UI components used across the BlueDesk admin portal frontend.

Typography

BLUE Display — titles and headings (font-blue-display). Custom font with 90% size-adjust fallback.

Host Grotesk — body text (default sans). Variable weight font supporting weights 100–900.

Brand Colors

Color Hex Usage
Dark Blue #00143B Sidebar background, primary dark surfaces
Bright Blue #1B56FD Accent color, buttons, active states
Light Blue #C3DCFF Hover states, subtle highlights
White #F8F8F8 Page background, card surfaces
Warm White #EDEDED Secondary backgrounds, borders
Lava #FD6112 Warning accents, attention indicators

Localization

Icelandic (is) — all UI strings are translated. Application names and company names remain in English.

Components

BlueLogo — SVG component at components/ui/blue-logo.tsx. Renders the BLUE wordmark with configurable className and fill props.