You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

7.6 KiB

Phase 3: Authentication (Cidaas OAuth2/OIDC)

Status: Done Progress: 18/18 tasks (100%) Started: 2025-10-30 Completed: 2025-10-30 Assigned to: Claude Code


Overview

Implement complete Cidaas OAuth2/OIDC authentication with custom UI: login, registration, logout, session management, JWT validation, and rate limiting.

Goal: Fully functional authentication system with custom experimenta-branded login/registration UI.


Dependencies

  • Phase 1: Foundation must be completed
  • Phase 2: Database must be completed (users table needed)
  • ⚠️ Required: Cidaas credentials (CLIENT_ID, CLIENT_SECRET, BASE_URL)

Tasks

Dependencies Installation

  • Install nuxt-auth-utils + jose

    pnpm add nuxt-auth-utils jose
    
  • Configure Cidaas environment variables in .env

    CIDAAS_BASE_URL=https://experimenta.cidaas.de
    CIDAAS_CLIENT_ID=xxx
    CIDAAS_CLIENT_SECRET=xxx
    CIDAAS_REDIRECT_URI=http://localhost:3000/api/auth/callback
    
  • Add Cidaas config to nuxt.config.ts runtimeConfig

    runtimeConfig: {
      cidaas: {
        baseUrl: process.env.CIDAAS_BASE_URL,
        clientId: process.env.CIDAAS_CLIENT_ID,
        clientSecret: process.env.CIDAAS_CLIENT_SECRET,
        redirectUri: process.env.CIDAAS_REDIRECT_URI,
      },
    }
    

Server Utilities

  • Create PKCE generator utility

    • File: server/utils/pkce.ts
    • Functions: generatePKCE() → returns { verifier, challenge }
    • Implementation: See CIDAAS_INTEGRATION.md
  • Create Cidaas API client utility

    • File: server/utils/cidaas.ts
    • Functions:
      • exchangeCodeForToken(code, verifier) → tokens
      • fetchUserInfo(accessToken) → user data
      • registerUser(userData) → registration result
    • See: CIDAAS_INTEGRATION.md
  • Create JWT validation utility

Auth API Endpoints

  • Create /api/auth/login.post.ts endpoint

    • Generates PKCE challenge & state
    • Stores in HTTP-only cookies (5min TTL)
    • Returns Cidaas authorization URL
    • See: CLAUDE.md: OAuth2 Login Flow
  • Create /api/auth/callback.get.ts endpoint

    • Validates state (CSRF protection)
    • Exchanges code for tokens (with PKCE)
    • Validates ID token (JWT)
    • Fetches user info from Cidaas
    • Creates/updates user in local DB
    • Creates encrypted session (nuxt-auth-utils)
    • Redirects to homepage
    • See: CLAUDE.md: OAuth2 Callback
  • Create /api/auth/register.post.ts endpoint

  • Create /api/auth/logout.post.ts endpoint

    • Clears session via clearUserSession()
    • Optional: Single Sign-Out at Cidaas
    • Returns success
  • Create /api/auth/me.get.ts endpoint

    • Protected endpoint (requires session)
    • Returns current user data
    • Uses: requireUserSession()

Client-Side Composables

  • Create useAuth composable
    • File: composables/useAuth.ts
    • Functions:
      • login(email) → redirects to Cidaas
      • logout() → clears session, redirects
      • register(data) → calls registration API
    • Uses: useUserSession from nuxt-auth-utils
    • Returns: { user, loggedIn, login, logout, register }
    • See: CLAUDE.md: OAuth2 Login Flow

UI Components

  • Create LoginForm component

  • Create RegisterForm component

    • File: components/Auth/RegisterForm.vue
    • Fields: Email, Password, Confirm Password, First Name, Last Name
    • Validation: VeeValidate + Zod
    • Calls: register(data) from useAuth
    • See: CIDAAS_INTEGRATION.md: UI Components
  • Create auth page with tabs

Middleware

  • Create auth middleware

  • Create rate-limit middleware

    • File: server/middleware/rate-limit.ts
    • Limits:
      • /api/auth/login: 5 attempts / 15min per IP
      • /api/auth/register: 3 attempts / 1hour per IP
    • Returns 429 on exceed
    • See: CLAUDE.md: Rate Limiting

Testing

  • Test OAuth2 flow end-to-end

    • Start at /auth page
    • Click "Login"
    • Redirect to Cidaas (if credentials configured)
    • Complete login
    • Verify callback works
    • Verify user created in DB
    • Verify session works
  • Test session management

    • Verify session persists across page reloads
    • Verify session expires after 30 days (or config)
    • Test logout clears session
  • Document authentication flow

    • Add detailed flow diagram to docs/CIDAAS_INTEGRATION.md (already exists)
    • Document any deviations from plan
    • Document Cidaas-specific quirks encountered

Acceptance Criteria

  • nuxt-auth-utils and jose are installed
  • All utilities (PKCE, Cidaas client, JWT) are implemented
  • All 5 auth endpoints work correctly
  • useAuth composable is functional
  • LoginForm and RegisterForm components are styled and functional
  • /auth page shows tabs with both forms
  • auth middleware protects routes correctly
  • rate-limit middleware works and returns 429 when exceeded
  • OAuth2 flow works end-to-end (login → callback → session)
  • Session management works (persist, expire, clear)
  • User is created/updated in local DB on first login
  • JWT tokens are validated correctly
  • PKCE flow prevents authorization code interception
  • State parameter prevents CSRF attacks
  • Authentication is fully documented

Notes

  • Cidaas Credentials: You'll need to request CLIENT_ID and CLIENT_SECRET from experimenta admin
  • Redirect URI: Must be registered in Cidaas Admin Panel: http://localhost:3000/api/auth/callback (dev), https://my.experimenta.science/api/auth/callback (prod)
  • Session Duration: Configured to 30 days (can be adjusted in nuxt-auth-utils config)
  • Custom UI: We're NOT using Cidaas hosted pages - fully custom experimenta-branded UI

Blockers

  • ⚠️ Cidaas Credentials Missing: Cannot test OAuth2 flow without CLIENT_ID/SECRET
  • Workaround: Implement everything, test with mock/manual verification until credentials available