Files

Mode2Svelte - Advanced SvelteKit Auth Testing Suite

An enhanced SvelteKit-based testing environment for advanced authentication workflows with Microsoft Azure MSAL and PocketBase. This is an extended implementation of Mode1Svelte with additional testing capabilities.

Tech Stack

  • Framework: SvelteKit 2.x with TypeScript
  • Backend: Node.js Adapter (production-ready)
  • Styling: Tailwind CSS 4
  • Authentication:
    • Azure MSAL Node (@azure/msal-node) - Microsoft Graph token management
    • PocketBase - User OAuth2 and token validation
  • Build Tool: Vite (integrated with SvelteKit)
  • Runtime: Node.js 18+

Features

Frontend Authentication (PocketBase)

  • OAuth2 login initialization with Microsoft
  • Auth state management and retrieval
  • Token refresh and validation
  • Session persistence
  • Automatic logout on invalid tokens

Backend Token Management (Microsoft Graph)

  • App-only token acquisition via MSAL
  • Automatic token caching with 60-second expiration buffer
  • Token refresh on demand
  • JWT payload inspection

Token Validation & Comparison

  • PocketBase user token validation
  • User record retrieval from tokens
  • Side-by-side token comparison (Graph vs PocketBase)
  • Token payload analysis

Interactive Testing Dashboard

  • Real-time authentication status
  • Visual token testing interface
  • API endpoint testing
  • Response inspection

Project Structure

Mode1Svelte/
├── src/
│   ├── lib/
│   │   └── auth/
│   │       ├── types.ts           # TypeScript interfaces
│   │       ├── backend.ts         # Backend auth classes (MSAL, PocketBase)
│   │       └── frontend.ts        # Frontend PocketBase auth class
│   ├── routes/
│   │   ├── +layout.svelte        # App layout
│   │   ├── +page.svelte          # Main dashboard
│   │   └── api/
│   │       └── auth/
│   │           ├── config/        # GET /api/auth/config
│   │           ├── graph/         # GET /api/auth/graph/token
│   │           ├── validate-pb-token/  # POST /api/auth/validate-pb-token
│   │           ├── refresh-graph/ # POST /api/auth/refresh-graph
│   │           └── compare-tokens/    # POST /api/auth/compare-tokens
│   └── app.css                   # Tailwind directives
├── static/                        # Static assets
├── package.json                  # Dependencies
├── svelte.config.js              # SvelteKit config (Node adapter)
├── tailwind.config.js            # Tailwind CSS config
├── vite.config.ts                # Vite config
└── tsconfig.json                 # TypeScript config

Installation

cd Mode1Svelte
npm install

Environment Setup

Ensure your .env file or environment variables are set:

export CLIENT_ID="<Azure Client ID>"
export TENANT_ID="<Azure Tenant ID>"
export CLIENT_SECRET="<Azure Client Secret>"
export PB_URL="<PocketBase URL>"
export PB_DB="<PocketBase Database URL>"
export PORT=5173

For development, create /home/admin/secrets/.env:

CLIENT_ID=your_client_id
TENANT_ID=your_tenant_id
CLIENT_SECRET=your_client_secret
PB_URL=https://pocketbase.example.com
PB_DB=https://pocketbase.example.com

Running the Application

Development Mode

npm run dev

Starts the dev server at http://localhost:5173 with hot reloading.

Production Build

npm run build
npm start

Builds the application and runs the Node.js server.

Type Checking

npm run check

Run TypeScript type checking across the project.

API Endpoints

GET /api/auth/config

Returns frontend-safe configuration for PocketBase OAuth setup.

Response:

{
  "pbUrl": "https://pocketbase.example.com",
  "provider": "microsoft",
  "collection": "Users"
}

GET /api/auth/graph/token

Fetches a Microsoft Graph token for backend API access.

Response:

{
  "success": true,
  "token": "eyJ0eXAiOiJKV1Q...",
  "fullToken": "eyJ0eXAiOiJKV1QiLCJhbGc...",
  "expiresOn": "2026-01-23T02:15:00.000Z",
  "isValid": true,
  "tokenDetails": {
    "aud": "https://graph.microsoft.com",
    "iss": "https://sts.windows.net/tenant-id",
    "scp": "..." 
  }
}

POST /api/auth/validate-pb-token

Validates a PocketBase user token and retrieves user information.

Request:

{
  "pbToken": "user_token_string"
}

Response:

{
  "valid": true,
  "user": {
    "id": "user_id",
    "email": "user@example.com",
    "name": "User Name"
  }
}

POST /api/auth/refresh-graph

Clears the cached Graph token and acquires a new one.

Response:

{
  "success": true,
  "refreshed": true,
  "expiresOn": "2026-01-23T02:15:00.000Z"
}

POST /api/auth/compare-tokens

Compares Graph token (backend) and PocketBase token (user) to demonstrate their differences.

Request:

{
  "pbToken": "user_token_string"
}

Response:

{
  "success": true,
  "comparison": {
    "graph_token": {
      "issuer": "https://sts.windows.net/tenant",
      "audience": "https://graph.microsoft.com",
      "app": "App Name",
      "scopes": "...",
      "issued_at": "2026-01-23T01:15:00.000Z",
      "expires_at": "2026-01-23T02:15:00.000Z",
      "type": "Microsoft Graph Token (Backend/App-only)",
      "source": "@azure/msal-node",
      "purpose": "Backend API calls to Microsoft Graph"
    },
    "pocketbase_token": {
      "type": "PocketBase User Token (Frontend/User)",
      "source": "PocketBase OAuth2 flow",
      "authenticated_user": "user@example.com"
    },
    "are_different": true
  }
}

Authentication Flow

Frontend (Browser)

  1. User clicks "Login with Microsoft"
  2. PocketBase initiates OAuth2 flow with Microsoft provider
  3. Microsoft redirects back with authorization code
  4. PocketBase exchanges code for user token
  5. Token stored in PocketBase auth store
  6. User dashboard updates with authenticated state

Backend (Server)

  1. Application starts with MSAL configuration
  2. On first API request, acquires Graph token using client credentials
  3. Token cached for 55 minutes (60-minute lifetime - 5-minute buffer)
  4. Subsequent requests use cached token
  5. Token automatically refreshed when expired

Development Notes

  • CORS: Configured for localhost:5173 and production URLs
  • Token Caching: Graph tokens cached in memory; refresh on demand with /api/auth/refresh-graph
  • Error Handling: Comprehensive error messages with specific failure reasons
  • Type Safety: Full TypeScript support throughout frontend and backend
  • SvelteKit Routing: File-based routing with +page.svelte and +server.ts files

Comparison with Mode1 (Hono/Bun)

Feature Mode1Svelte Mode1
Framework SvelteKit 2 SvelteKit 4 (old)
Backend Node.js Adapter Hono + Bun
Frontend Svelte Components HTML + Vanilla JS
Styling Tailwind CSS CSS (custom)
Build Tool Vite Vite
API Routes /routes/api/ /routes/api/
Auth Module /lib/auth/ /routes/api/
Type Safety Full TypeScript TypeScript (partial)
Production Ready Yes ⚠️ Experimental

Troubleshooting

Token Acquisition Fails

  • Verify CLIENT_ID, TENANT_ID, and CLIENT_SECRET are correct
  • Ensure the Azure application is configured for client credentials flow
  • Check that the application has Graph API permissions

PocketBase Token Validation Fails

  • Verify PB_URL and PB_DB are correct
  • Ensure the user is properly logged in via OAuth
  • Check that PocketBase is running and accessible

Login Button Not Appearing

  • Ensure JavaScript is enabled
  • Check browser console for errors
  • Verify that loginBtn HTML element ID matches configuration

License

Private - Job Info Testing Suite

Developing

Once you've created a project and installed dependencies with npm install (or pnpm install or yarn), start a development server:

npm run dev

# or start the server and open the app in a new browser tab
npm run dev -- --open

Building

To create a production version of your app:

npm run build

You can preview the production build with npm run preview.

To deploy your app, you may need to install an adapter for your target environment.