{"id":9719,"library":"edx-drf-extensions","title":"edX DRF Extensions","description":"edX DRF Extensions provides a collection of utility classes, authenticators, permissions, and exception handlers designed to extend Django REST Framework for use within the Open edX ecosystem. It is currently at version 10.6.0, with a frequent release cadence tied to Django and Python version compatibility and Open edX platform development.","status":"active","version":"10.6.0","language":"en","source_language":"en","source_url":"https://github.com/openedx/edx-drf-extensions","tags":["django","drf","rest-framework","authentication","permissions","edx","openedx","jwt"],"install":[{"cmd":"pip install edx-drf-extensions","lang":"bash","label":"Install latest version"}],"dependencies":[{"reason":"Core framework dependency for any Django application.","package":"Django","optional":false},{"reason":"The library extends Django REST Framework; it is a fundamental dependency.","package":"djangorestframework","optional":false}],"imports":[{"symbol":"JwtCookieAuthentication","correct":"from edx_drf_extensions.auth.jwt.authentication import JwtCookieAuthentication"},{"note":"The exception handler was moved directly under `edx_drf_extensions`.","wrong":"from edx_drf_extensions.utils.exception_handler import exception_handler","symbol":"exception_handler","correct":"from edx_drf_extensions.exception_handler import exception_handler"},{"symbol":"DefaultPagination","correct":"from edx_drf_extensions.pagination import DefaultPagination"},{"symbol":"ReadOnlyAuditMixin","correct":"from edx_drf_extensions.mixins import ReadOnlyAuditMixin"},{"symbol":"JwtAuthenticationError","correct":"from edx_drf_extensions.auth.jwt.errors import JwtAuthenticationError"}],"quickstart":{"code":"import os\nfrom rest_framework import viewsets, status\nfrom rest_framework.response import Response\nfrom rest_framework.decorators import action\nfrom django.http import Http404\n\n# Ensure these imports are correct for your installed version\nfrom edx_drf_extensions.auth.jwt.authentication import JwtCookieAuthentication\nfrom edx_drf_extensions.exception_handler import exception_handler\n\n# In a Django settings.py file, you'd typically configure DRF:\n# REST_FRAMEWORK = {\n#     'DEFAULT_AUTHENTICATION_CLASSES': [\n#         'edx_drf_extensions.auth.jwt.authentication.JwtCookieAuthentication',\n#         'rest_framework.authentication.SessionAuthentication',\n#     ],\n#     'EXCEPTION_HANDLER': 'edx_drf_extensions.exception_handler.exception_handler'\n# }\n\nclass MyTestViewSet(viewsets.ViewSet):\n    \"\"\"A simple DRF view demonstrating edx-drf-extensions authentication.\"\"\"\n    authentication_classes = [JwtCookieAuthentication]\n    # Permission classes would typically be added here, e.g., IsAuthenticated\n\n    def list(self, request):\n        if request.user.is_authenticated:\n            return Response({\"message\": f\"Hello {request.user.username}, authenticated via JWT!\"}, status=status.HTTP_200_OK)\n        return Response({\"message\": \"Authentication failed.\"},\n                        status=status.HTTP_401_UNAUTHORIZED)\n\n    @action(detail=False, methods=['get'])\n    def cause_handled_error(self, request):\n        \"\"\"Endpoint to demonstrate the custom exception handler.\"\"\"\n        # This error will be caught by DRF's exception handling, if configured.\n        raise Http404(\"The requested resource was not found. (Handled by edx-drf-extensions)\")\n\nprint(\"Quickstart code demonstrates applying JwtCookieAuthentication to a DRF ViewSet.\")\nprint(\"It also hints at configuring the custom exception_handler in settings.py.\")\nprint(\"To run fully, integrate into a Django/DRF project and configure REST_FRAMEWORK.\")\n","lang":"python","description":"This quickstart demonstrates how to apply `JwtCookieAuthentication` to a Django REST Framework ViewSet, allowing JWT-based authentication via cookies. It also shows how the `exception_handler` can be used (typically configured in `settings.py`) to provide consistent error responses. The `cause_handled_error` action simulates an exception that would be processed by the custom handler."},"warnings":[{"fix":"Upgrade your Python environment to 3.9 or higher, or pin `edx-drf-extensions` to a version prior to 10.4.0.","message":"Python 3.8 support was dropped in version 10.4.0. Projects using older Python versions must upgrade their environment or stick to `edx-drf-extensions < 10.4.0`.","severity":"breaking","affected_versions":">=10.4.0"},{"fix":"Review your authentication backend configuration and `edx-drf-extensions` settings. If you rely on strict JWT validation, ensure it's explicitly enforced, or adjust your system's authentication flow to account for 'forgiving' behavior.","message":"The behavior of JWT authentication changed significantly in v10.0.0, making 'forgiving JWTs' the default. This means JWTs that fail verification due to expiry or other issues might be silently ignored if another authentication method succeeds, which could alter security assumptions.","severity":"breaking","affected_versions":">=10.0.0"},{"fix":"Thoroughly test authentication after upgrading, especially if your application relies on both JWT and session authentication. Refer to the specific changelogs for each version for detailed behavioral changes.","message":"There were several changes, reverts, and fixes related to JWT vs session user checks around versions 9.1.0-9.1.2. Upgrading between these minor versions, or to/from 10.0.0, could lead to unexpected authentication behavior or regressions.","severity":"gotcha","affected_versions":"9.1.0-10.1.0"},{"fix":"Ensure your `edx-drf-extensions` version is compatible with your Django version. Upgrade to the latest `edx-drf-extensions` (10.6.0+) if using Django 5.2.","message":"Version 10.6.0 added support for Django 5.2. If you are using an older version of `edx-drf-extensions` with Django 5.x, you may encounter compatibility issues or `DeprecationWarnings` from Django. Older `edx-drf-extensions` versions are not guaranteed to support newer Django releases.","severity":"gotcha","affected_versions":"<10.6.0 with Django >=5.0"}],"env_vars":null,"last_verified":"2026-04-17T00:00:00.000Z","next_check":"2026-07-16T00:00:00.000Z","problems":[{"fix":"Update your import statement to `from edx_drf_extensions.exception_handler import exception_handler` and adjust your `REST_FRAMEWORK` settings accordingly.","cause":"The `exception_handler` was moved directly into the top-level `edx_drf_extensions` package.","error":"ModuleNotFoundError: No module named 'edx_drf_extensions.utils.exception_handler'"},{"fix":"If you're raising `JwtAuthenticationError` directly, ensure you're calling it with the correct arguments as expected by the version you're using. If you have custom error handling, review how this exception is caught and handled.","cause":"In version 10.2.0, the base class for `JwtAuthenticationError` was changed, potentially altering its constructor signature or expected arguments.","error":"TypeError: JwtAuthenticationError.__init__() takes 1 positional argument but 2 were given"},{"fix":"Add `'edx_drf_extensions'` to your `INSTALLED_APPS` list in your Django `settings.py` file.","cause":"The `edx-drf-extensions` package itself needs to be registered with Django.","error":"django.core.exceptions.ImproperlyConfigured: 'edx_drf_extensions' must be in INSTALLED_APPS to use 'edx_drf_extensions.auth.jwt.authentication.JwtCookieAuthentication'"}]}