Skip to main content
Glama
orneryd

M.I.M.I.R - Multi-agent Intelligent Memory & Insight Repository

by orneryd
PASSPORT_QUICK_START.md10.8 kB
# Passport.js Quick Start Guide **Version**: 1.0.0 **Date**: 2025-11-21 **Purpose**: Get authentication working in 15 minutes --- ## 🎯 Goal Implement authentication with Passport.js that: - ✅ Works locally with username/password (development) - ✅ Works in production with OAuth (Okta/Auth0/Google) - ✅ Requires minimal configuration - ✅ Easy to test --- ## ⚡ Quick Start (15 minutes) ### Step 1: Install Dependencies (2 minutes) ```bash npm install passport passport-local passport-oauth2 express-session connect-redis ``` ### Step 2: Create Passport Config (5 minutes) Create **`src/config/passport.ts`**: ```typescript import passport from 'passport'; import { Strategy as LocalStrategy } from 'passport-local'; import { Strategy as OAuth2Strategy } from 'passport-oauth2'; // Development: Local username/password if (process.env.MIMIR_ENABLE_SECURITY === 'true' && process.env.NODE_ENV === 'development') { passport.use(new LocalStrategy((username, password, done) => { // Simple dev credentials (change these!) if (username === 'admin' && password === 'admin') { return done(null, { id: '1', email: 'admin@localhost', role: 'admin' }); } return done(null, false, { message: 'Invalid credentials' }); })); } // Production: OAuth if (process.env.MIMIR_ENABLE_SECURITY === 'true' && process.env.MIMIR_AUTH_PROVIDER) { passport.use('oauth', new OAuth2Strategy({ authorizationURL: `${process.env.MIMIR_OAUTH_ISSUER}/oauth2/v1/authorize`, tokenURL: `${process.env.MIMIR_OAUTH_ISSUER}/oauth2/v1/token`, clientID: process.env.MIMIR_OAUTH_CLIENT_ID!, clientSecret: process.env.MIMIR_OAUTH_CLIENT_SECRET!, callbackURL: process.env.MIMIR_OAUTH_CALLBACK_URL!, }, async (accessToken, refreshToken, profile, done) => { return done(null, { id: profile.id, email: profile.email, role: 'user' }); })); } // Serialize user to session passport.serializeUser((user: any, done) => done(null, user)); passport.deserializeUser((user: any, done) => done(null, user)); export default passport; ``` ### Step 3: Add Auth Endpoints (5 minutes) Create **`src/api/auth-api.ts`**: ```typescript import { Router } from 'express'; import passport from '../config/passport.js'; const router = Router(); // Development: Login with username/password router.post('/auth/login', passport.authenticate('local', { successRedirect: '/', failureRedirect: '/login', failureFlash: false }) ); // Production: OAuth login router.get('/auth/oauth/login', passport.authenticate('oauth') ); router.get('/auth/oauth/callback', passport.authenticate('oauth', { successRedirect: '/', failureRedirect: '/login' }) ); // Logout (both dev and prod) router.post('/auth/logout', (req, res) => { req.logout(() => { res.json({ success: true }); }); }); // Check auth status router.get('/auth/status', (req, res) => { res.json({ authenticated: req.isAuthenticated(), user: req.user || null }); }); export default router; ``` ### Step 4: Initialize in HTTP Server (3 minutes) Modify **`src/http-server.ts`**: ```typescript import session from 'express-session'; import passport from './config/passport.js'; import authRouter from './api/auth-api.js'; // ... existing code ... // Add session middleware (only if security enabled) if (process.env.MIMIR_ENABLE_SECURITY === 'true') { app.use(session({ secret: process.env.MIMIR_JWT_SECRET || 'dev-secret-change-me', resave: false, saveUninitialized: false, cookie: { secure: process.env.NODE_ENV === 'production', httpOnly: true, maxAge: 24 * 60 * 60 * 1000 // 24 hours } })); app.use(passport.initialize()); app.use(passport.session()); // Auth routes app.use(authRouter); } // ... existing routes ... // Protect API routes (only if security enabled) if (process.env.MIMIR_ENABLE_SECURITY === 'true') { app.use('/api/*', (req, res, next) => { // Skip auth check for health endpoint if (req.path === '/api/health') return next(); // Check authentication if (req.isAuthenticated()) return next(); res.status(401).json({ error: 'Unauthorized' }); }); } // ... rest of existing code ... ``` --- ## 🧪 Local Testing ### Option 1: Development Mode (Simplest) **1. Configure `.env`**: ```bash # Enable security with local auth MIMIR_ENABLE_SECURITY=true NODE_ENV=development MIMIR_JWT_SECRET=dev-secret-change-in-production ``` **2. Start Mimir**: ```bash npm run build npm start ``` **3. Test with curl**: ```bash # Login curl -X POST http://localhost:9042/auth/login \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "username=admin&password=admin" \ -c cookies.txt \ -L # Check auth status curl http://localhost:9042/auth/status \ -b cookies.txt # Access protected API curl http://localhost:9042/api/nodes/query \ -b cookies.txt # Logout curl -X POST http://localhost:9042/auth/logout \ -b cookies.txt ``` **4. Test with browser**: 1. Create simple login page at `http://localhost:9042/login` 2. Enter username: `admin`, password: `admin` 3. Access `http://localhost:9042/api/nodes/query` 4. Should work! ### Option 2: Test with Google OAuth (5 minutes setup) **Why Google?** Free, easy setup, no waiting for approval **1. Get Google OAuth Credentials**: - Go to https://console.cloud.google.com - Create new project (or select existing) - Go to "APIs & Services" → "Credentials" - Click "Create Credentials" → "OAuth 2.0 Client ID" - Application type: "Web application" - Authorized redirect URIs: `http://localhost:9042/auth/oauth/callback` - Copy Client ID and Client Secret **2. Configure `.env`**: ```bash MIMIR_ENABLE_SECURITY=true NODE_ENV=production # Google OAuth MIMIR_AUTH_PROVIDER=google MIMIR_OAUTH_CLIENT_ID=your-google-client-id.apps.googleusercontent.com MIMIR_OAUTH_CLIENT_SECRET=your-google-client-secret MIMIR_OAUTH_CALLBACK_URL=http://localhost:9042/auth/oauth/callback MIMIR_OAUTH_ISSUER=https://accounts.google.com MIMIR_OAUTH_USERINFO_URL=https://accounts.google.com/oauth2/v1/userinfo # Optional # Session MIMIR_JWT_SECRET=generate-with-openssl-rand-base64-32 ``` **3. Start Mimir**: ```bash npm run build npm start ``` **4. Test**: 1. Open browser: `http://localhost:9042/auth/oauth/login` 2. Login with your Google account 3. Redirected back to Mimir (authenticated!) 4. Access APIs: `http://localhost:9042/api/nodes/query` --- ## 🎨 Simple Login UI (Optional) Create **`frontend/src/components/Login.tsx`**: ```tsx import { useState } from 'react'; export function Login() { const [username, setUsername] = useState(''); const [password, setPassword] = useState(''); const isDev = import.meta.env.MODE === 'development'; const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); const formData = new URLSearchParams(); formData.append('username', username); formData.append('password', password); const response = await fetch('/auth/login', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: formData, credentials: 'include' }); if (response.ok) { window.location.href = '/'; } else { alert('Invalid credentials'); } }; if (isDev) { // Development: Username/password form return ( <div className="login-container"> <h2>Login (Development Mode)</h2> <form onSubmit={handleSubmit}> <input type="text" placeholder="Username (admin)" value={username} onChange={(e) => setUsername(e.target.value)} /> <input type="password" placeholder="Password (admin)" value={password} onChange={(e) => setPassword(e.target.value)} /> <button type="submit">Login</button> </form> </div> ); } // Production: OAuth button return ( <div className="login-container"> <h2>Login</h2> <a href="/auth/oauth/login"> <button>Login with OAuth</button> </a> </div> ); } ``` --- ## 📋 Environment Variables Summary ### Development (3 variables) ```bash MIMIR_ENABLE_SECURITY=true NODE_ENV=development MIMIR_JWT_SECRET=dev-secret ``` ### Production with OAuth (7 variables) ```bash MIMIR_ENABLE_SECURITY=true NODE_ENV=production MIMIR_AUTH_PROVIDER=google # or okta, auth0, azure MIMIR_OAUTH_CLIENT_ID=your-client-id MIMIR_OAUTH_CLIENT_SECRET=your-client-secret MIMIR_OAUTH_CALLBACK_URL=https://mimir.yourcompany.com/auth/callback MIMIR_OAUTH_ISSUER=https://accounts.google.com MIMIR_JWT_SECRET=your-secure-secret ``` --- ## 🔒 Security Notes ### Development - ⚠️ **Never use dev credentials in production!** - ⚠️ Change default username/password in `passport.ts` - ⚠️ Use HTTPS in production (required for OAuth) ### Production - ✅ Generate secure session secret: `openssl rand -base64 32` - ✅ Set `cookie.secure: true` (requires HTTPS) - ✅ Use Redis for session storage (not memory) - ✅ Set appropriate session timeout - ✅ Enable CORS properly for your domain --- ## 🐛 Troubleshooting ### Issue: "Unauthorized" even after login **Solution**: Check cookies are being sent ```bash # Verify session cookie is set curl -v http://localhost:9042/auth/login \ -d "username=admin&password=admin" \ -c cookies.txt # Check cookie file cat cookies.txt ``` ### Issue: OAuth redirect fails **Solution**: Verify callback URL matches exactly ```bash # In OAuth provider settings http://localhost:9042/auth/oauth/callback # In .env MIMIR_OAUTH_CALLBACK_URL=http://localhost:9042/auth/oauth/callback ``` ### Issue: Session not persisting **Solution**: Check session middleware is before routes ```typescript // Correct order: app.use(session({...})); app.use(passport.initialize()); app.use(passport.session()); app.use(authRouter); // Then routes ``` --- ## ✅ Checklist - [ ] Install Passport.js dependencies - [ ] Create `src/config/passport.ts` - [ ] Create `src/api/auth-api.ts` - [ ] Modify `src/http-server.ts` - [ ] Configure `.env` for development - [ ] Test login with curl - [ ] Test protected API access - [ ] (Optional) Set up OAuth provider - [ ] (Optional) Create login UI - [ ] Update session secret for production --- **Total Time**: 15 minutes **Lines of Code**: ~150 lines **Complexity**: Low **Next Steps**: See [AUTHENTICATION_PROVIDER_INTEGRATION.md](./AUTHENTICATION_PROVIDER_INTEGRATION.md) for production OAuth setup. --- **Document Version**: 1.0.0 **Last Updated**: 2025-11-21 **Maintainer**: Security Team **Status**: Quick Start Guide

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/orneryd/Mimir'

If you have feedback or need assistance with the MCP directory API, please join our Discord server