7d8fd9f251
- Created Mode2Svelte as a copy of Mode1Svelte - Updated branding (title, description) to distinguish from Mode1Svelte - Added Mode2Svelte support to orchestrator - Configured orchestrator to spawn Mode2Svelte with Node.js adapter - Set Mode2Svelte as active mode in activeMode.txt - Built production bundle for Mode2Svelte - Both Mode1Svelte and Mode2Svelte now managed by orchestrator on port 3005 - Orchestrator controls which mode runs via activeMode.txt configuration
314 lines
8.5 KiB
Markdown
314 lines
8.5 KiB
Markdown
# 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
|
|
|
|
```bash
|
|
cd Mode1Svelte
|
|
npm install
|
|
```
|
|
|
|
## Environment Setup
|
|
|
|
Ensure your `.env` file or environment variables are set:
|
|
|
|
```bash
|
|
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
|
|
```bash
|
|
npm run dev
|
|
```
|
|
Starts the dev server at `http://localhost:5173` with hot reloading.
|
|
|
|
### Production Build
|
|
```bash
|
|
npm run build
|
|
npm start
|
|
```
|
|
Builds the application and runs the Node.js server.
|
|
|
|
### Type Checking
|
|
```bash
|
|
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:**
|
|
```json
|
|
{
|
|
"pbUrl": "https://pocketbase.example.com",
|
|
"provider": "microsoft",
|
|
"collection": "Users"
|
|
}
|
|
```
|
|
|
|
### GET `/api/auth/graph/token`
|
|
Fetches a Microsoft Graph token for backend API access.
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"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:**
|
|
```json
|
|
{
|
|
"pbToken": "user_token_string"
|
|
}
|
|
```
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"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:**
|
|
```json
|
|
{
|
|
"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:**
|
|
```json
|
|
{
|
|
"pbToken": "user_token_string"
|
|
}
|
|
```
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"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
|
|
|
|
## Links
|
|
|
|
- [SvelteKit Documentation](https://svelte.dev/docs/kit)
|
|
- [Azure MSAL Node](https://github.com/AzureAD/microsoft-authentication-library-for-js)
|
|
- [PocketBase Documentation](https://pocketbase.io/docs/)
|
|
- [Tailwind CSS](https://tailwindcss.com/)
|
|
|
|
## 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:
|
|
|
|
```sh
|
|
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:
|
|
|
|
```sh
|
|
npm run build
|
|
```
|
|
|
|
You can preview the production build with `npm run preview`.
|
|
|
|
> To deploy your app, you may need to install an [adapter](https://svelte.dev/docs/kit/adapters) for your target environment.
|