Authentication and Security
Relevant source files
The following files were used as context for generating this wiki page:- frontend/src/pages/login/oidc-redirect.tsx
- frontend/src/components/authentication/UserSignIn.tsx
- frontend/src/pages/class/[classId]/session/[sessionId]/join.tsx
- e2e/authentication-helpers.ts
- frontend/src/hooks/useHandleStudentAuthenticationRequest.ts
- frontend/src/components/authentication/AuthenticationBarrier.tsx
- backend/prisma/migrations/20250415121343_support_fully_anonymous_users/migration.sql
- frontend/src/pages/_app.tsx
- frontend/src/contexts/AuthenticationContext.ts
The Collimator application employs a sophisticated authentication and security model designed to handle different user roles with varying levels of access and privacy requirements. It integrates with external OpenID Connect (OIDC) providers for primary identity verification of administrative users (Teachers and Admins) and implements a custom, privacy-preserving cryptographic mechanism for student authentication within a session.
This system ensures that while Teachers and Admins are authenticated via a standard, robust identity provider, student participation is managed in a way that minimizes data exposure. A strong cryptographic layer, featuring long-term keys for teachers and ephemeral keys for students, underpins the entire security architecture, particularly in how student identities are managed and pseudonymized within a class.
User Roles and Authorization
The system defines three primary user roles, each with distinct permissions and authentication flows.
| Role | Description |
|---|---|
ADMIN | Administrative user with full access to the system, including user, class, and task management. Authenticates via OIDC and a local password. |
TEACHER | A user who can create and manage classes and sessions. Authenticates via OIDC and a local password. |
STUDENT | A participant in a session. Can be authenticated via OIDC or join anonymously. Their identity is protected through cryptographic pseudonymization. |
Sources: frontend/src/types/user/user-role.ts, e2e/tests/users/user-management.spec.ts:13
Route Protection
Access to different parts of the application is controlled by the AuthenticationBarrier component. It evaluates the user's authentication status and role to determine if they are permitted to view a given page.
- Public Routes: A whitelist of routes are accessible to unauthenticated users, including login pages (
/login,/login/oidc-redirect), the student join page (/class/[classId]/session/[sessionId]/join), and error pages. - Student Routes: A specific set of routes, like the task solving page, are designated for students.
- Authenticated Routes: All other routes require an authenticated user. Admins and Teachers have broad access, while Students are restricted to their designated pages.
If an unauthenticated user attempts to access a protected route, they are redirected to the login page.
Sources: frontend/src/components/authentication/AuthenticationBarrier.tsx:9-22, 40-52
Authentication Flows
The authentication process differs significantly between Teacher/Admin users and Student users.
Teacher and Admin Authentication
Teacher and Admin authentication is a two-step process involving OIDC and local key decryption.
- OIDC Handshake: The user initiates login, which redirects them to an OIDC provider (e.g., Microsoft).
- Callback and Backend Authentication: After successful OIDC login, the user is redirected to
/login/oidc-redirect. This page receives anidTokenfrom the OIDC provider and sends it to the Collimator backend's/api/v0/authentication/loginendpoint. - Key Pair Handling: The backend responds with an
AuthenticationResponseDto, which includes user details and, crucially, an encryptedkeyPairif one exists. - Local Sign-In: The user is then presented with the
UserSignIncomponent.- First-Time Login: If
keyPairisnull, the user must provide a primary and a backup password. A newTeacherLongTermKeyPairis generated, and its private key is encrypted separately with keys derived from each password. The public key and encrypted private keys are then sent to the backend to be stored. - Subsequent Logins: If an encrypted
keyPairexists, the user provides a password. The frontend attempts to decrypt the private key using the provided password.
- First-Time Login: If
- State Finalization: Upon successful key decryption or creation, the full authentication context, including the active
TeacherLongTermKeyPairobject, is stored in the application's state, and the user is redirected to their destination.
The following diagram illustrates the Teacher/Admin login sequence.
Student Authentication
Student authentication is designed for privacy and is brokered by the teacher's client via WebSockets. It can be either identified or anonymous.
- Initiation: The student navigates to a session join link, e.g.,
/class/.../session/.../join?key=<teacher_key_fingerprint>. - Mode Determination: The frontend checks if the session is anonymous.
- Identified Session: The student is redirected to the OIDC provider. After OIDC login, they return to the
joinpage with anidTokenstored locally. - Anonymous Session: The student proceeds without OIDC, and the backend is called to get an anonymous authentication token.
- Identified Session: The student is redirected to the OIDC provider. After OIDC login, they return to the
- Cryptographic Handshake (Identified Session):
- The student's browser generates an ephemeral
StudentKeyPair. - It fetches the teacher's public key using the fingerprint from the URL.
- It derives a shared secret with the teacher's public key (ECDH).
- It emits a
requestTeacherToSignInStudentWebSocket event. This message contains the student's ephemeral public key and the student'sidToken(encrypted with the shared secret).
- The student's browser generates an ephemeral
- Teacher-Side Processing:
- The teacher's client receives the WebSocket event.
- It derives the same shared secret using the student's ephemeral public key and its own private key.
- It decrypts the
idToken, verifies it, and extracts the student's identity. - It creates a persistent pseudonym for the student within the class by encrypting a long-term identifier from the
idToken. - It calls the backend's
/api/v0/authentication/studentendpoint with the pseudonym to get a session-specificauthenticationTokenfor the student.
- Token Exchange:
- The teacher's client encrypts the student's new
authenticationTokenwith the shared secret. - It sends this back to the student via a
studentAuthenticationTokenWebSocket event.
- The teacher's client encrypts the student's new
- Authentication Completion: The student's browser decrypts the
authenticationToken, stores it in the authentication context, and is now fully authenticated for the session.
This diagram shows the identified student authentication flow.
Cryptography and State Persistence
Key Management
TeacherLongTermKeyPair: AnECDSAkey pair on theP-256curve used for signing and deriving shared secrets. The private key is stored in the database, encrypted with a key derived from the teacher's password using PBKDF2. A backup password allows for a second encrypted copy, providing a recovery mechanism.
Sources: frontend/src/components/authentication/UserSignIn.tsx:78-128, e2e/authentication-helpers.ts:24-37StudentKeyPair: An ephemeralECDSAkey pair generated in the student's browser for each session. It is used to perform an Elliptic-Curve Diffie-Hellman (ECDH) key exchange with the teacher's public key to establish a secure communication channel over WebSockets.
Sources: frontend/src/pages/class/[classId]/session/[sessionId]/join.tsx:169-170
Authentication Context
The frontend manages authentication state via React's Context API.
AuthenticationContext: Provides the current authentication state to the component tree.UpdateAuthenticationContext: Provides a function to update the state.
The state object contains the user's role, tokens, ID, and, if applicable, the cryptographic key pair object. This state is persisted in the browser's localStorage under the key authenticationState. The serializeAuthenticationContext and deserializeAuthenticationContext functions handle the complex process of converting the in-memory state (including CryptoKey objects) to and from a storable JSON format.
Sources: frontend/src/pages/_app.tsx:28-50, 70-87, frontend/src/contexts/AuthenticationContext.ts
Database Schema
The database schema supports both authenticated and anonymous students, linking them to classes and sessions respectively.
This ER diagram shows the key tables related to student identity.
- A
Studentis a base entity. - An
AuthenticatedStudentis linked to aClassand has apseudonym. The pseudonym is an encrypted identifier, ensuring privacy. - An
AnonymousStudentis only linked to a specificSession.
Sources: backend/prisma/migrations/20250415121343_support_fully_anonymous_users/migration.sql:2-22
Conclusion
The authentication and security architecture of Collimator is a multi-faceted system that balances standard, robust authentication for trusted users with a privacy-centric approach for students. By leveraging OIDC, end-to-end encryption over WebSockets, and a carefully designed cryptographic key management system, it provides strong security guarantees while protecting student identities through pseudonymization. The clear separation of roles and authentication flows ensures that each user type interacts with the system in a manner appropriate to their level of trust and required privacy.