Set request.user in process_request in JwtAuthCookieMiddleware


There are two problems that may be related:

  1. One problem is that request.user is not set for process_request for all middleware registered after our authentication middleware when using our JWT Cookie method of authentication. This is a problem because request.user is used by many existing middleware in edx-platform in process_request, and some in other IDAs like ecommerce.

  2. When the initial fix (described below) was added to fix a problem in ecommerce, it ended up causing a problem in edx-platform. has not been solved, but a toggle was added to avoid this issue in edx-platform.

A partial fix was added to JwtAuthCookieMiddleware to set request.user before process_view, but this happens after all calls to request_user, and does not fully address the above issue. It only works for legacy middleware that can have their process_request logic moved to process_view with no consequences.

At one time, JwtAuthCookieMiddleware had used process_request, but the implementation of JwtRedirectToLoginIfUnauthenticatedMiddleware required process_view, and also needs to run before JwtAuthCookieMiddleware, so this required JwtAuthCookieMiddleware to move to process_view.

Proposed Solution:

JwtRedirectToLoginIfUnauthenticatedMiddleware actually does 2 things.

  1. It sets up the view to redirect to login if unauthenticated and the view is using the permission class LoginRedirectIfUnauthenticated, and

  2. It force adds USE_JWT_COOKIE_HEADER, stating that it is safe to use JWT cookies.

    • It is this forcing of USE_JWT_COOKIE_HEADER that requires that this middleware runs before JwtAuthCookieMiddleware.

    • The forcing of USE_JWT_COOKIE_HEADER is only required for endpoints that may be called from places where we can't add the header, like email. This was the case for the Ecommerce BasketAddItemsView (Add Product).

A possible solution would be to add a Django setting named LOGIN_REDIRECT_IF_UNAUTHENTICATED_VIEWS to register views that should use the JWT Cookie whether or not the header was set. This Django setting would be available during process_request, and thus JwtAuthCookieMiddleware could know early enough whether to use the cookies and set request.user.

  • This special registry of views would only be required for the hopefully rare views where the callers can't add the header.

  • The process_view phase of JwtRedirectToLoginIfUnauthenticatedMiddleware could ensure that an IsAuthenticated permission class was added to the view.

Rejected Alternatives:

Tried to use decorator_from_middleware to enable JwtRedirectToLoginIfUnauthenticatedMiddleware for specific views only. The problem with this approach is that it runs process_request of JwtRedirectToLoginIfUnauthenticatedMiddleware after that of JwtAuthCookieMiddleware, which is too late for solving the problem as stated.

Other Notes:

In ecommerce, the middleware that uses request.user is part of django-oscar, so it is not an option to move the code from process_view to process_request.

Epic Link

Story Points





Robert Raposa