Video upload and Range streaming
Why two requests
A <video src> element cannot add an Authorization header. The stream path is therefore public at the HTTP layer and protected by the token, which proves enrolment in the lesson's course and nothing else. The mint call is a normal authenticated request, so it runs the full checks.
Token details
- HS256 JWT with claims
lessonId,sub(the participant) andexp. - Signed with a dedicated secret that never leaves the server. If no secret is configured, the mint call fails with a 500 rather than issue a token nobody can verify.
- Valid for 6 hours by default.
- Verification checks, in order: a secret is configured, the token has three parts, the signature matches (constant-time compare), it has not expired, and its
lessonIdequals the lesson being streamed. Any failure is 403. - The token is in the URL, so it can appear in access logs. The 6 hour lifetime limits what a leaked URL is worth.
Recordings
Recordings use the same mechanism: GET /api/v1/lms/recordings/{id}/stream-token, then GET /api/v1/lms/recordings/{id}/stream?token=.... The enrolment check is against the recording's course.
Sources: services/lms-service/src/main/java/com/rtih/startupos/lms/{resource/LessonResource,resource/RecordingResource,service/LmsStreamTokenService,service/LessonService}.java, services/lms-service/src/main/resources/application.yml.