UC-1 Student authenticates and enrols
| Primary actor | Student |
| Supporting actors | Campus IdP |
| Priority | Must |
| Satisfies | FR-A1, FR-A2, FR-A3, FR-A4, FR-C1 |
| Precondition | A published challenge exists for the student's campus. |
| Trigger | The student opens the app and taps "Sign in with campus SSO". |
Main success scenario
- The app redirects the student to the campus IdP.
- The student authenticates at the IdP.
- The IdP posts an assertion carrying the opaque subject, affiliation and groups.
- The system resolves the campus from the assertion's issuer, creates or loads the student row (subject and affiliation only, no name, no PHI), resolves the role, and sets a session cookie.
- The student taps "Join the challenge"; an enrolment is created, idempotently.
Extensions
- 3a. Assertion invalid. No session and no student row; the student is returned to the landing page with a retry prompt. A security event records the reason.
- 4a. Not a current student. The session exists but
isCurrentStudentis false; the student sees the eligibility card and cannot enrol or check in. - 4b. Affiliation or group mapped to a staff role. The session carries the admin role; the admin console becomes reachable and student routes still work.
- First visit. The student row is created on the fly.
Acceptance criteria (Gherkin)
| Feature file | Test module |
|---|---|
role_based_access_control.feature |
test_role_based_access_control_bdd.py |
sign_in_desktop_two_pane.feature |
test_sign_in_desktop_two_pane_bdd.py |
state_card_treatment.feature and frontend/state_card_treatment.feature |
test_state_card_treatment_bdd.py |
Plain pytest: test_auth.py, test_enrollment.py, test_saml_assertion_validation.py, test_student_identity_key.py, test_staff_role_mapping.py.
Views
- Process: UC-1 SSO sign-in and enrolment
- Logical: the
AuthProviderseam in system components;StudentandEnrollmentin the domain model - Physical: the SAML round trip terminates at the API tier in production
Code: backend/app/routers/auth.py, backend/app/auth/, backend/app/services/students.py, frontend/src/auth/.
The real-IdP integration (Entra, SP key custody, the identity key) is recorded in ADRs 0003 and 0004 and under docs/saml/.