Cross-Domain Media with authentication for Django
The situation: You serve media files from a different domain than your main web application domain (good idea). You want to use nginx's internal redirect (X-Accel-Redirect) to authorize media file delivery.
The problem: You don't have access to the user's session on the media domain and can't authenticate or authorize media access.
The solution: You handle media URLs with an expiring token attached which temporarily authorizes access and can be refreshed via redirects when needed.
HTTP View
Here's how it works in HTTP:
- -> GET media.example.org/path/file.pdf
- <- 302 www.example.com/path/file.pdf
- -> GET www.example.com/path/file.pdf
- if not authorized <- 403
- if authorized <- 302 media.example.org/path/file.pdf?token=XYZ
- -> GET media.example.org/path/file.pdf?token=XYZ
- <- 200 file.pdf
- after expiry -> GET media.example.org/path/file.pdf?token=XYZ
- See step 2
Use in Django
# Development
MEDIA_URL = '/media/'
# Production
MEDIA_URL = 'https://media.example.org/media/
INTERNAL_MEDIA_PREFIX = '/protected/'
from crossdomainmedia import (
CrossDomainMediaAuth, CrossDomainMediaMixin
)
class CustomCrossDomainMediaAuth(CrossDomainMediaAuth):
'''
Create your own custom CrossDomainMediaAuth class
and implement at least these methods
'''
SITE_URL = 'https://www.example.com'
def is_media_public(self):
'''
Determine if the media described by self.context
needs authentication/authorization at all
'''
return self.context['object'].is_public
def get_auth_url(self):
'''
Give URL path to authenticating view
for the media described in context
'''
obj = self.context['object']
raise reverse('view-name', kwargs={'pk': obj.pk})
def get_media_file_path(self):
'''
Return the file path relative to MEDIA_ROOT
'''
obj = self.context['object']
return obj.file.name
class CustomDetailView(CrossDomainMediaMixin, DetailView):
'''
Add the CrossDomainMediaMixin
and set your custom media_auth_class
'''
media_auth_class = CustomCrossDomainMediaAuth
Some other useful methods
# Get your media URLs with token outside of view
mauth = CustomCrossDomainMediaAuth({'object': obj})
mauth.get_full_media_url(authorized=True)
# Send file via nginx internal redirect response
mauth.send_internal_file()
Nginx config
This is how an Nginx config could look like.
server {
# Web server with session on domain
listen 443 ssl http2;
server_name www.example.com;
# ...
location / {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header Host $host;
# etc...
proxy_pass wsgi_server;
}
}
server {
# Media server with no session on domain
listen 443 ssl http2;
server_name media.example.org;
# ...
location /media/ {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header Host $host;
# etc...
proxy_pass wsgi_server;
}
location /protected {
internal;
alias /var/www/media-root;
}
}
Metadata
Release files for django-crossdomainmedia 0.0.4
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| django-crossdomainmedia-0.0.4.tar.gz | 7.2 kB | Without provenance | Details for django-crossdomainmedia-0.0.4.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| django_crossdomainmedia-0.0.4-py2.py3-none-any.whl | Python 3, Python 2 | none | any | Details for django_crossdomainmedia-0.0.4-py2.py3-none-any.whl |
Total release size: 14.1 kB
Release files / django-crossdomainmedia-0.0.4.tar.gz
| Download URL | django-crossdomainmedia-0.0.4.tar.gz |
|---|---|
| Size | 7.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
71265b33804d631da3ce7e5e8c960c50b6dcca5859bce6f3b777269ee751d605
|
|
BLAKE2b-256 checksum How to use checksums |
cbd6ad536efc64d6f0b9e844bebe0f7c2c4ef20427033610b9a2e2611e341441
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/4.0.2 CPython/3.10.12
|
Release files / django_crossdomainmedia-0.0.4-py2.py3-none-any.whl
| Download URL | django_crossdomainmedia-0.0.4-py2.py3-none-any.whl |
|---|---|
| Size | 6.9 kB |
| Tags | Python 2 Python 3 |
|
SHA-256 checksum How to use checksums |
e8c487511353d92a04fc050e887bf9dff1638432339c2eb6b0bef32b3e53593f
|
|
BLAKE2b-256 checksum How to use checksums |
c4ba23f98509211657c1f7924458830d5bc4f28723f846df58c937ee6c5b2976
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/4.0.2 CPython/3.10.12
|
Security for django-crossdomainmedia 0.0.4
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.