Skip to content

[LTI Provider] iframe-embedded problem submissions fail with CSRF 403 under Django cookie defaults #38441

@ayub02

Description

@ayub02

Summary

When Open edX is used as an LTI 1.1 tool provider and content is launched inside an iframe on the consumer LMS (verified with Canvas), the initial launch renders correctly, but any subsequent interactive POST (e.g. submitting a problem) is rejected by Django's CSRF middleware with:

Forbidden (CSRF cookie not set.): /courses/.../xblock/.../handler/xmodule_handler/problem_check

The same content works if launched in a new tab / top-level window.

Steps to reproduce

  1. Configure an Open edX instance as an LTI 1.1 provider (default settings, no changes to SESSION_COOKIE_SAMESITE / CSRF_COOKIE_SAMESITE).
  2. In Canvas, add an external tool pointing to a problem component or subsection in the Open edX course.
  3. Launch the tool inside Canvas (iframe, default behavior).
  4. Attempt to submit an answer.

Expected

The problem submission succeeds and (if the component is graded) the score is passed back to Canvas.

Actual

POST to the xblock handler returns HTTP 403. LMS logs:

WARNING django.security.csrf ... Forbidden (CSRF cookie not set.): /event
WARNING django.security.csrf ... Forbidden (CSRF cookie not set.): /courses/<course>/xblock/<block>/handler/xmodule_handler/problem_check
[pid: 30] POST /event => 403
[pid: 31] POST /courses/<course>/xblock/<block>/handler/xmodule_handler/problem_check => 403

Root cause

  • lti_launch (lms/djangoapps/lti_provider/views.py) is @csrf_exempt, so the initial launch POST from Canvas works.
  • Subsequent XBlock handler POSTs are standard CSRF-protected views.
  • Django defaults are SESSION_COOKIE_SAMESITE = 'Lax' and CSRF_COOKIE_SAMESITE = 'Lax' (lms/envs/common.py does not override them; it only defines DCS_SESSION_COOKIE_SAMESITE).
  • Browsers do not send Lax cookies on cross-site POSTs from the Canvas iframe, so the CSRF cookie is absent and Django rejects the request.

Environment

  • Open edX master sandbox
  • LTI version: 1.1
  • Consumer LMS: Canvas
  • Browser: Firefox 149 (macOS 10.15)

Related code

  • lms/djangoapps/lti_provider/views.py (lti_launch view, @csrf_exempt + @add_p3p_header)
  • lms/envs/common.py (DCS_SESSION_COOKIE_SAMESITE exists, but SESSION_COOKIE_SAMESITE / CSRF_COOKIE_SAMESITE do not)
  • lms/djangoapps/lti_provider/users.py (require_user_account enforcement)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    Projects

    Status

    Backlog

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions