React Native with Django backend how to make sure sure that only users with passed token can access images?

78 views Asked by At

I am building a react native app with Django backend. In the app I let the users upload images which are stored in a models.FileField(). The problem I just noticed is that anyone can access the images from the backend server if they have the right link which raises privacy issues. How would the python and React Native code look like for making sure images that go into can be obtained only with passing a "POST" request which has a "user" and a "token" and how to put those images to be displayed with ? Thank you

1

There are 1 answers

2
Mihail Andreev On

Recommended solution

I recommend to use django-private-storage instead.

It specifically designed to serve this purpose. It provides a secure way to handle private files and media uploads in Django, ensuring that only authenticated users have access to them.

Or some alternatives

Serve Images Through Django

Rather than serving files directly, use Django views to serve them. This allows you to implement authentication and permissions on the views.

Let's do it step-by-step.

1. Django URLs:

Let's start by creating the URL pattern to serve your images.

Application's urls.py:

Inside the application's urls.py, you'll create a URL pattern for the view that serves the image.

from django.urls import path
from . import views

urlpatterns = [
    ...
    path('image/<str:file_path>/', views.serve_protected_image, name='serve_protected_image'),
    ...
]

2. Django View:

Here's a simple Django view that serves the image after checking for user authentication:

from django.conf import settings
from django.http import FileResponse, HttpResponseForbidden
import os

def serve_protected_image(request, file_path):
    # Ensure the user is authenticated or meets any other criteria
    if not request.user.is_authenticated:
        return HttpResponseForbidden()

    # Serve the image
    file_location = os.path.join(settings.MEDIA_ROOT, file_path)
    response = FileResponse(open(file_location, 'rb'))
    return response

3. React Native:

In your React Native application, you would make an authenticated HTTP request to the Django server to get the image. Once you receive the image, you'd display it using the <Image /> component.

Here's a basic example using the fetch API:

import React, { useState, useEffect } from 'react';
import { Image } from 'react-native';

const DisplayImage = ({ imagePath }) => {
    const [imageURI, setImageURI] = useState(null);

    useEffect(() => {
        fetch('https://your-django-server.com/app_name/image/' + imagePath + '/', {
            method: 'GET',
            headers: {
                'Authorization': 'Token your_auth_token',  // if you're using token-based authentication
                // ... any other headers ...
            },
        })
        .then(response => {
            if (!response.ok) {
                throw new Error('Network response was not ok');
            }
            return response.blob();
        })
        .then(blob => {
            const imageURI = URL.createObjectURL(blob);
            setImageURI(imageURI);
        })
        .catch(error => {
            console.error('There was a problem with the fetch operation:', error.message);
        });
    }, [imagePath]);

    return (
        <Image 
            source={{ uri: imageURI }} 
            style={{ width: 100, height: 100 }}  // Modify as needed
        />
    );
};

Note that the process uses the Blob API to convert the fetched data into a format that React Native's Image component can use. The URL.createObjectURL function creates a local object URL that you can use as the image source.

Do remember that the authentication part (Authorization header in the fetch request) is crucial. You'd typically get the token after a login process and then use it for subsequent requests to your server.

This is a simplified example and in a real-world scenario, you might want to handle caching, loading states, and error states in a more comprehensive manner.

Use Secure or One Time URLs

When using cloud providers, you can generate secure, temporary URLs for your files. These URLs will expire after a set amount of time, ensuring that even if someone does get hold of the URL, they won’t have indefinite access.