10. Dealing with Django CSRF Protection in Frontend Apps#

Status#

Accepted

Context#

For background, please see:

Frontend apps need a way to obtain a CSRF token when making POST, PUT, and DELETE requests to backend API services implemented as Django applications with CSRF protection enabled. Each backend service is generally deployed with a CSRF token cookie scoped to the domain of the given service (ecommerce.edx.org) and named accordingly (ecommerce_csrftoken). Each backend service uses a unique SECRET_KEY to produce the CSRF token, so a CSRF token created by one service will not be valid for another service. Therefore, frontend apps served by different subdomains will not have access to these CSRF token cookies.

Decisions#

  1. CSRF Token API Endpoint We will implement an API view that constructs a valid CSRF token and returns it in a JSON response. This API view will be added to the edx-drf-extensions python library under a new “csrf” Django app which will be added to INSTALLED_APPS in each backend service as we encounter frontend apps that need to make POST, PUT, and DELETE API requests to a given backend service. The CSRF token API endpoint will be protected from cross-domain XHR requests using our standard CORS protections (only requests originating from pages loaded from one of the domains listed in the CORS_ORIGIN_WHITELIST setting will be allowed).

  2. Shared HTTP Client CSRF Token Management Code We will add code to the @edx/frontend-auth npm package that applies a request interceptor to the Axios HTTP client which will ensure that any POST, PUT, and DELETE requests are made with the appropriate CSRF token header. This code will make use of the the CSRF token API Endpoint described above to obtain a valid CSRF token for the given backend service for which a request is being made.

Rejected Alternatives#

Shared SECRET_KEY Across Backend Services#

One alternative to the solution outlined above would be to share the configured SECRET_KEY setting value across all backend services and change the CSRF_COOKIE_DOMAIN value to a wildcard off of the second-level domain of the Open edX installation (e.g. .edx.org). This would allow frontend apps to read the CSRF token from the cookie that is set when a user logs via the authentication service (currently LMS). Since the SECRET_KEY value would be shared across all backend services, the frontend would be able to use the same CSRF token to make POST, PUT, and DELETE API requests to each of these services.

We rejected this alternative due to the fact that it seems more secure to limit the exposure of the SECRET_KEY value to a single service.

References#