-
-
Notifications
You must be signed in to change notification settings - Fork 6.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Document how to authenticate and serve private media files #7702
Comments
I don't think DRF has anything built in for this – |
This sort of thing is what Nginx's X-Accel is for. https://www.nginx.com/resources/wiki/start/topics/examples/x-accel/ Authenticate as normal in Django or DRF then have nginx serve the file. |
DRF has no default for it for it is outside the scope of DRF. |
Thank you for the responses. The specific challenges I'm facing when I am trying to integrate |
Related: edoburu/django-private-storage#39 |
You could delegate to django-downloadview in your DRF viewset's response phase, so have DRF do everything else such as authentication and so on. Looks like BaseDownloadView could be easily extended for that... |
I was able to patch everything together. In case this is useful to others, here is a minimal reproduction: from typing import Any, List, Optional, Tuple, Type
from django.contrib.auth.models import User
from django.core.exceptions import PermissionDenied
from django.core.handlers.wsgi import WSGIRequest
from django_downloadview import DownloadResponse, ObjectDownloadView
from rest_framework.authentication import BaseAuthentication, BasicAuthentication
from rest_framework.permissions import BasePermission, DjangoObjectPermissions
from rest_framework_simplejwt.authentication import JWTAuthentication
class DRFAuthenticatedObjectDownloadView(ObjectDownloadView):
"""A generic file download view that automatically authenticates the user and
validates permissions using DRF middleware."""
permissions_class: Type[BasePermission] = DjangoObjectPermissions
# Note: This needs to be kept in sync with
# settings.py REST_FRAMEWORK DEFAULT_AUTHENTICATION_CLASSES
auth_classes: List[Type[BaseAuthentication]] = [BasicAuthentication, JWTAuthentication]
def authenticate(self, request: WSGIRequest) -> None:
"""Updates request.user if the client has sent headers that configured ``auth_classes``
successfully authenticate.
"""
for auth_class in self.auth_classes:
auth_resp: Optional[Tuple[User, None]] = auth_class().authenticate(request)
if auth_resp is not None:
request.user = auth_resp[0]
return
def has_permission(self, request: WSGIRequest) -> None:
"""Validate that the current User has appropriate access permissions to a Model.
Raises:
PermissionDenied: If the user does not have the required permissions.
"""
instance = self.get_object()
permissions = self.permissions_class()
if not (
permissions.has_permission(request, self)
and permissions.has_object_permission(request, self, instance)
):
raise PermissionDenied()
def get(self, request: WSGIRequest, *args: Any, **kwargs: Any) -> DownloadResponse:
"""Authenticate user and check permissions before returning the file download."""
self.authenticate(request)
self.has_permission(request)
return super().get(request, *args, **kwargs) |
Nice example @johnthagen. I'm going to close this as I think it's probably out of scope for DRF itself. Thanks. |
This helped me a lot! Thanks a lot @johnthagen I am using django along with apache x-sendfile and have a complex permissions system to validate through before serving the file. Yet to implement but this looks very promising |
Checklist
master
branch of Django REST framework.Expected behavior
The docs explain how to use
FileField
s to serve media file URLs, but if these files are sensitive and need authentication/permissions, there is no mention of how to authenticate their download.Django packages exist for this, such as
django-downloadview
, but it's not clear how (or if) the built in DRF authentication can interact with this. For example, these views don't interact withREST_FRAMEWORK
'DEFAULT_AUTHENTICATION_CLASSES'
.Does DRF have a solution for efficient media file serving that links into its authentication system? If so, I'd be happy to open a PR to clarify the docs.
The text was updated successfully, but these errors were encountered: