Skip to content

Meteor authentik#385

Open
Dharp02 wants to merge 13 commits into
meteor-is-backfrom
meteor-authentik
Open

Meteor authentik#385
Dharp02 wants to merge 13 commits into
meteor-is-backfrom
meteor-authentik

Conversation

@Dharp02

@Dharp02 Dharp02 commented Jun 22, 2026

Copy link
Copy Markdown
Collaborator

feat: Migrate Auth to Meteor Accounts + Authentik Proxy Support

Summary

This PR migrates the authentication layer from a custom JWT bridge system to Meteor's built-in Accounts system, adds support for Authentik SSO via the os.mieweb.org forward auth proxy, and fixes the database configuration mismatch between Fastify and Meteor backends.


What Changed

1. Auth Bridge Migration (meteor-backend/server/auth-bridge.js)

Before:

  • Custom connectionIdentity Map tracking DDP sessions manually
  • Custom auth.bridge Meteor method called by frontend on every connect
  • Manual JWT re-bridging before expiry
  • requireIdentity() only checked JWT/PAT tokens

After:

  • Accounts.registerLoginHandler('oidc') — handles GitHub/Google/Apple JWTs from Fastify
  • Accounts.registerLoginHandler('pat') — handles Personal Access Tokens
  • Accounts.registerLoginHandler('proxy') — handles Authentik proxy JWTs
  • requireIdentity() restored to handle both DDP (this.userId) and REST/MCP (currentBearerToken()) paths
  • findOrCreateUser() syncs Fastify user collection with Meteor users collection using same _id
  • signProxyJwt() / verifyProxyJwt() for Authentik proxy JWT signing

2. Authentik Proxy Auth (meteor-backend/server/main.js)

Added new HTTP endpoint:

GET /api/whoami
  • Reads X-Email, X-User-First-Name, X-User-Last-Name headers injected by os.mieweb.org proxy
  • Signs a short-lived JWT (60s) using PROXY_JWT_SECRET
  • Returns { token } to frontend
  • Gated by TRUST_PROXY_HEADERS=true env var

3. All 14 Method Files Updated

Updated all Meteor method files to use requireIdentity(this) instead of this.userId directly, enabling both DDP and REST/MCP auth paths:

  • clock.js
  • tickets.js
  • organizations.js
  • teams.js
  • channels.js
  • tokens.js
  • activity.js
  • users.js
  • messages.js
  • enterprises.js
  • notifications.js
  • timers.js
  • attachments.js
  • presence.js

4. Frontend DDP Client (src/lib/ddp.ts)

Before:

  • Called auth.bridge(token) manually
  • Re-bridged before JWT expiry using reauthTimer
  • No resume token support

After:

  • Calls login({ oidcJwt: token }) via Meteor Accounts protocol
  • Calls login({ proxyJwt: token }) for Authentik users
  • Calls login({ resume: token }) for reconnects (automatic)
  • Stores meteor_resume_token in localStorage
  • tryResumeLogin() handles reconnects automatically
  • loginWithProxy() calls /api/whoami for Authentik flow
  • Removed reauthTimer — Meteor resume tokens handle this natively

5. Infrastructure Fixes

Database:

  • Fixed Meteor pointing to wrong database (timehuddletimeharbor)
  • Both Fastify and Meteor now use timeharbor database

Nginx (/etc/nginx/sites-available/timehuddle on timecore-dev):

  • Fixed /websocket route from port 4000 (Fastify) to port 3100 (Meteor)
  • DDP WebSocket connections now correctly reach Meteor

PM2 (backend/ecosystem.config.cjs):

  • Added TRUST_PROXY_HEADERS=true to Meteor env
  • Added PROXY_JWT_SECRET to Meteor env
  • Updated MONGO_URL to point to timeharbor

6. Social Providers Cleanup (src/lib/socialProviders.ts)

  • Removed authentik from the social provider registry
  • Authentik is now handled automatically via proxy headers, not a button click
  • Social buttons: GitHub, Google, Apple remain

New Environment Variables Required

meteor-backend (timecore-dev server):

TRUST_PROXY_HEADERS=true
PROXY_JWT_SECRET=<generate with: openssl rand -base64 32>
AUTH_JWKS_URL=http://localhost:4000/api/auth/jwks
MONGO_URL=mongodb://localhost:27017/timeharbor?directConnection=true&replicaSet=rs0

Auth Flow Diagrams

GitHub/Google/Apple Login

User clicks "Continue with Google"
      ↓
Fastify handles OAuth → issues JWT
      ↓
Frontend calls: login({ oidcJwt: token })
      ↓
Meteor verifies JWT via JWKS
findOrCreateUser() syncs user to Meteor 'users' collection
      ↓
this.userId set on DDP connection ✅
meteor_resume_token stored in localStorage ✅

Authentik Login (os.mieweb.org proxy)

User visits timehuddledev.os.mieweb.org
      ↓
os.mieweb.org proxy injects X-Email headers
      ↓
Frontend calls GET /api/whoami (Meteor HTTP)
      ↓
Meteor reads X-Email, signs proxy JWT (60s TTL)
      ↓
Frontend calls: login({ proxyJwt: token })
      ↓
Meteor verifies proxy JWT signature
findOrCreateUser() syncs user
      ↓
this.userId set on DDP connection ✅

Reconnect (all users)

Page refresh / network drop
      ↓
tryResumeLogin() reads meteor_resume_token
      ↓
login({ resume: token })
      ↓
Session restored automatically ✅
No re-authentication needed ✅

Testing

Tested ✅

  • Email/password login for existing users
  • Google OAuth login
  • GitHub OAuth login
  • Authentik SSO via os.mieweb.org proxy (incognito window)
  • Resume token reconnect on page refresh
  • DDP subscriptions (tickets, clock) working after login
  • REST/MCP calls via wormhole working after login

Known Issues / Next Steps

  • Apple Sign-in needs .well-known/apple-developer-domain-association.txt deployed
  • New user signup still relies on Fastify for /v1/me session
  • 403 on Fastify /v1/* routes for new users not yet in Fastify session
  • accounts-google and accounts-github packages not yet added to Meteor (Phase 2)

Phase 2 Plan (Next PR)

⬜ Add accounts-google to Meteor
⬜ Add accounts-github to Meteor
⬜ Add accounts-apple to Meteor
⬜ Remove Google/GitHub/Apple from Fastify
⬜ Simplify requireIdentity() to just this.userId
⬜ Remove JWKS dependency from Meteor
⬜ Eventually eliminate Fastify auth completely

Related Issues

@Dharp02 Dharp02 self-assigned this Jun 22, 2026
Dharp02 and others added 9 commits June 22, 2026 17:06
Keep /api/whoami endpoint and add / and /health endpoints from meteor-is-back branch
Resolved conflict in meteor-backend/server/teams.js by keeping meteor-authentik version that correctly removes targetUserId when removing team members.
- Remove backend/nginx-apple-proxy.conf (machine-specific nginx config)
- Remove meteor-backend/start-rosetta.sh (machine-specific dev script)
- Add both to .gitignore to prevent future commits
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant