ein freies Lehrmittel auf der Basis von eduskript

Authentication

NextAuth.js with context-aware sign-in flows.

Account Types

TypeSign-in methodsCreated when
TeacherOAuth or credentialsSign up on main site
StudentOAuth onlySign in on teacher's page

Students don't have passwords. They're identified by a pseudonymized hash, not email.

Context Detection

Location determines the sign-in experience:

ContextURLDefault for new OAuth
Main site/auth/signinTeacher account
Teacher's page/auth/signin?from=[pageSlug]Student account

The from param is preserved through OAuth via a cookie (oauth_from_teacher_page).

Sign-In Flow

User clicks "Sign in"
    ↓
/auth/signin?from=teacherslug  (or no param for main site)
    ↓
Set cookie if from teacher page
    ↓
OAuth redirect → Provider → Return
    ↓
auth.ts checks cookie:
  - Has cookie → create student account
  - No cookie → create teacher account
    ↓
Clear cookie

Key Rules

  • Existing accounts take precedence (teacher stays teacher regardless of context)
  • Credentials = always teacher (students don't have passwords)
  • New OAuth on main site → teacher
  • New OAuth on teacher page → student (pseudonymized)

Key Files

FilePurpose
src/lib/auth.tsNextAuth config, account type detection
src/lib/privacy-adapter.tsCreates student accounts with pseudonyms
src/components/auth/signin-form.tsxContext-aware sign-in UI
src/app/auth/signin/page.tsxSign-in page router

Session Data

// Available in session.user
interface SessionUser {
  id: string
  email?: string        // Null for students
  name?: string
  isAdmin: boolean
  accountType: 'teacher' | 'student'
  pageSlug?: string     // Teacher's public page URL
}

Checking Auth in API Routes

import { getServerSession } from 'next-auth'
import { authOptions } from '@/lib/auth'

export async function GET() {
  const session = await getServerSession(authOptions)

  if (!session?.user?.id) {
    return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
  }

  // session.user.id, session.user.accountType, etc.
}