openedx.core.djangoapps.cors_csrf package#

Submodules#

openedx.core.djangoapps.cors_csrf.authentication module#

Django Rest Framework Authentication classes for cross-domain end-points.

class openedx.core.djangoapps.cors_csrf.authentication.SessionAuthenticationCrossDomainCsrf#

Bases: SessionAuthentication

Session authentication that skips the referer check over secure connections.

Django Rest Framework’s SessionAuthentication class calls Django’s CSRF middleware implementation directly, which bypasses the middleware stack.

This version of SessionAuthentication performs the same workaround as CorsCSRFMiddleware to skip the referer check for whitelisted domains over a secure connection. See cors_csrf.middleware for more information.

Since this subclass overrides only the enforce_csrf() method, it can be mixed in with other SessionAuthentication subclasses.

enforce_csrf(request)#

Skip the referer check if the cross-domain request is allowed.

openedx.core.djangoapps.cors_csrf.decorators module#

Decorators for cross-domain CSRF.

View decorator for sending a cross-domain CSRF cookie.

This works like Django’s @ensure_csrf_cookie, but will also set an additional CSRF cookie for use cross-domain.

Parameters:

func (function) – The view function to decorate.

openedx.core.djangoapps.cors_csrf.helpers module#

Helper methods for CORS and CSRF checks.

openedx.core.djangoapps.cors_csrf.helpers.is_cross_domain_request_allowed(request)#

Check whether we should allow the cross-domain request.

We allow a cross-domain request only if:

  1. The request is made securely and the referer has “https://” as the protocol.

  2. The referer domain has been whitelisted.

Parameters:

request (HttpRequest)

Returns:

bool

openedx.core.djangoapps.cors_csrf.helpers.skip_cross_domain_referer_check(request)#

Skip the cross-domain CSRF referer check.

Django’s CSRF middleware performs the referer check only when the request is made over a secure connection. To skip the check, we patch request.is_secure() to False.

openedx.core.djangoapps.cors_csrf.middleware module#

Middleware for handling CSRF checks with CORS requests

CSRF and referrer domain checks#

When processing HTTPS requests, the default CSRF middleware checks that the referer domain and protocol is the same as the request’s domain and protocol. This is meant to avoid a type of attack for sites which serve their content with both HTTP and HTTPS, with a man in the middle on the HTTP requests.

django/django

This doesn’t work well with CORS requests, which aren’t vulnerable to this attack when the server from which the request is coming uses HTTPS too, as it prevents the man in the middle attack vector.

We thus do the CSRF check of requests coming from an authorized CORS host separately in this middleware, applying the same protections as the default CSRF middleware, but without the referrer check, when both the request and the referer use HTTPS.

class openedx.core.djangoapps.cors_csrf.middleware.CorsCSRFMiddleware(*args, **kwargs)#

Bases: CsrfViewMiddleware, MiddlewareMixin

Middleware for handling CSRF checks with CORS requests

process_view(request, callback, callback_args, callback_kwargs)#

Skip the usual CSRF referer check if this is an allowed cross-domain request.

class openedx.core.djangoapps.cors_csrf.middleware.CsrfCrossDomainCookieMiddleware(*args, **kwargs)#

Bases: MiddlewareMixin

Set an additional “cross-domain” CSRF cookie.

Usage:

  1. Decorate a view with @ensure_csrf_cookie_cross_domain.

  2. Set CROSS_DOMAIN_CSRF_COOKIE_NAME and CROSS_DOMAIN_CSRF_COOKIE_DOMAIN

    in settings.

  3. Add the domain to CORS_ORIGIN_WHITELIST

  4. Enable FEATURES[‘ENABLE_CROSS_DOMAIN_CSRF_COOKIE’]

For testing, it is often easier to relax the security checks by setting:
  • CORS_ALLOW_INSECURE = True

  • CORS_ORIGIN_ALLOW_ALL = True

process_response(request, response)#

Set the cross-domain CSRF cookie.

openedx.core.djangoapps.cors_csrf.models module#

Models for cross-domain configuration.

class openedx.core.djangoapps.cors_csrf.models.XDomainProxyConfiguration(*args, **kwargs)#

Bases: ConfigurationModel

Cross-domain proxy configuration.

See openedx.core.djangoapps.cors_csrf.views.xdomain_proxy for an explanation of how this works.

exception DoesNotExist#

Bases: ObjectDoesNotExist

exception MultipleObjectsReturned#

Bases: MultipleObjectsReturned

change_date#

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

changed_by#

Accessor to the related object on the forward side of a many-to-one or one-to-one (via ForwardOneToOneDescriptor subclass) relation.

In the example:

class Child(Model):
    parent = ForeignKey(Parent, related_name='children')

Child.parent is a ForwardManyToOneDescriptor instance.

changed_by_id#
enabled#

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

get_next_by_change_date(*, field=<django.db.models.fields.DateTimeField: change_date>, is_next=True, **kwargs)#
get_previous_by_change_date(*, field=<django.db.models.fields.DateTimeField: change_date>, is_next=False, **kwargs)#
id#

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

whitelist#

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

openedx.core.djangoapps.cors_csrf.views module#

Views for enabling cross-domain requests.

openedx.core.djangoapps.cors_csrf.views.xdomain_proxy(request)#

Serve the xdomain proxy page.

Internet Explorer 9 does not send cookie information with CORS, which means we can’t make cross-domain POST requests that require authentication (for example, from the course details page on the marketing site to the enrollment API to auto-enroll a user in an “honor” track).

The XDomain library [jpillora/xdomain] provides an alternative to using CORS.

The library works as follows:

  1. A static HTML file (“xdomain_proxy.html”) is served from courses.edx.org. The file includes JavaScript and a domain whitelist.

  2. The course details page (on edx.org) creates an invisible iframe that loads the proxy HTML file.

  3. A JS shim library on the course details page intercepts AJAX requests and communicates with JavaScript on the iframed page. The iframed page then proxies the request to the LMS. Since the iframed page is served from courses.edx.org, this is a same-domain request, so all cookies for the domain are sent along with the request.

You can enable this feature and configure the domain whitelist using Django admin.

Module contents#