4
31 Comments

Authentication with React and Django

Hey guys,
I recently updated my SaaS website to use React for the frontend and left the backend with Django.

I'm trying to figure out a way to use cookies to authenticate the user in the frontend (as opposed to saving tokens in local storage which is insecure), but I'm a bit confused as to the best way to do that.

Anyone have any suggestions or have personal experience with this type of setup?

  1. 4

    If the React app is served by the Django template then session auth from Django works fine as an option. We do that with Vue.

    1. 1

      Thank you for your comment!

      I'm using Django for the backend API and I have one index.html template that is the build output from the react app. This way, they are decoupled.

      How would I use the session auth to authenticate requests from the React frontend? Would I use a cookie? And if so, is that secure from CSRF attacks?

      1. 1

        If you use Django auth and the index page is served by Django (?) then the API requests can leverage session auth if the user signs into the app with Django auth (server based).

        Side note, we've used django-webpack-loader for integrating our frontend build into Django templates. This removes all of the cookie/token storage requirement from the front end for accessing protected API routes because session auth can be used.

  2. 3

    As others have already suggested - it depends on your architecture.

    If you're dropping a React app into a Django template, then like others have suggested you can just use all of Django's built in login tooling and normal session auth for everything. This is typically the approach I recommend, and I wrote an entire article describing why: Organizing a Front End Codebase in a Django App (tl;dr: you get to use all the built in functionality of Django instead of having to re-do everything in a DRF and associated libs)

    If you've completely decoupled your React app from your Django app and are using something like Node and/or SSR to serve it then as others have suggested you're in library territory.

    Hope that helps!

    1. 1

      This is the approach we've taken and I recommend. Saves on complexity and you get the goodness of what Django already offers.

    2. 1

      Thanks for your help!

      I took a look at your article, and it looks like my app is in the Hybrid architecture category. The thing is, I am trying to handle authentication (login, register, etc) in the frontend, and use the backend mostly for the API.

      I think I'm gonna go with the Django session cookies, and try to secure them in React with a library. My only problem is CSRF. Django has the CSRF Token for server-rendered forms, but all my forms are built in React. Any suggestions?

      1. 1

        Hey,

        Yeah Django has pretty good docs on this here.

        You can use the cookie to get the token and then just pass it up in a the "X-CSRFToken" header on all your requests.

        If you don't want to use cookies you can also include {% csrf_token %} somewhere on the page and use a DOM selector to pull it out.

  3. 3

    I am using JWT stored in localStorage. I don't think it's more unsafe than using cookies. As long as you prevent the usual client-side abuses (like using HTTPS, preventing cross-site-scripting) it should be fine.

    1. 1

      If it's stored in localStorage, is it accessible by XSS, even if you use HTTPS?

      1. 2

        As soon as your code enables untrusted code to run in the browser, everything stored in the browser is compromised (even cookies). HTTPS protects against man-in-the-middle attacks (like ISPs or compromised routers looking into your data as it goes through the wire).

        So XSS is a client-side attack that can be enabled by bad code from the web app, while HTTPS acts at protocol/network-level.

        1. 1

          Agree with @vladcalin, using cookies won't save you against XSS. Storing token in localStorage is OK. React also prevents XSS by design.

  4. 3

    You can use https://github.com/SimpleJWT/django-rest-framework-simplejwt to create expiring access and refresh tokens on the backend and store these in cookies on the frontend. I also went from a pure Django app to nodejs/react frontend and django-rest-framework backend and this works well for me.

    1. 1

      I've looked into JWT before. How would I store the tokens securely in the React App?

  5. 3

    Check out the following fork of the Django SimpleJWT project:
    https://github.com/NiyazNz/django-rest-framework-simplejwt/tree/jwt_cookie
    It uses HttpOnly cookies to manage the tokens, so there's no need to save them in local storage.

    1. 1

      This looks promising! I'm going to try and implement this.

      The only question I have is, what about CSRF? The HttpOnly cookies aren't secure from those attacks, correct?

      I looked into it and what seems to help is setting "SESSION_COOKIE_SECURE=True" in settings.py. Is this correct?

      Thanks for your help!

      1. 1

        So many cookies! The JWT is for authentication, and one of its features is that it does not need anything extra stored on the server, the way regular sessions do. HttpOnly is a good thing for the JWT. For CSRF protection, Django can use a separate cookie, but the docs make the case that it's not terribly useful to make that cookie HttpOnly: https://docs.djangoproject.com/en/3.0/ref/settings/#std:setting-CSRF_COOKIE_HTTPONLY

  6. 2

    I'm currently storing a JWT in localStorage and authenticating between React and Django that way with the "djangorestframework-simplejwt" package. I'm curious about using the session authentication from Django for the web client but sticking with JWTs works well for keeping things consistent with the auth method for the mobile app too.

    1. 1

      Thanks for your input!

      After reading everyone's comments, I decided I'm gonna go with JWT in cookies, and send a CSRF Token with every login.

      This article helped me: https://x-team.com/blog/my-experience-with-json-web-tokens/#:~:text=If we store the JWT,in-the-middle attacks.

  7. 2

    Try Firebase auth? Super easy to use and it handles all the messy implementation details for you. https://firebase.google.com/products/auth

    1. 1

      Thanks for your comment!

      I will definitely look into it. I've been looking for a way to do Facebook and Google login. Is this a library I would import into React? And, would I be able to view all my users in my Django Database?

      1. 1

        Firebase is a javascript library you would import into your React app.
        https://www.npmjs.com/package/firebase
        You need to set up a firebase project and get an API key and other config data.
        You would then initialized a firebase instance in your react app and use the firebase auth methods for things like signup, login, verification emails, password resets, etc.

        For each user, firebase auth will store basic data like name, password, email etc. and provide each user with a unique Id (uid).
        In your database user table, you should store the uid and any other data you need (e.g. user preferences, purchases/subscriptions etc.)
        https://firebase.google.com/docs/auth/web/manage-users

        If it's important to you, you can denormalize your data and also store email address and other data in your django database, but then you have to remember to update both databases (firebase auth and django), so it's probably better to just keep the auth data in firebase and look it up via uid when you need it.

        Hope this helps!

  8. 2

    When you authenticate the user in the django app create a token for that user's session, store it in the db and then set the token as part of the response cookie.

    If your using axios from the react app add this to the top of the file:
    axios.defaults.withCredentials = true;

    This will make it so that when the user authenticates and gets a response from the django app it will set the cookie in the browser and it will also send the cookie as part of every request.

    Then you can create an authentication class in Django that reads the token from the cookie, and queries and returns the user from the db using the token.

    1. 1

      Thanks for your comment and the help with Axios!

      Yes, I am using axios for requests in React. This is most likely what I will be implementing. I am worried about CSRF though. Can I use that "axios.default" to include a CSRF Token in each header as well?

      1. 2

        yup can use axios.defaults.xsrfCookieName and axios.defaults.xsrfHeaderName

  9. 2

    Maybe you could implement JWT authentication instead, tokens have a expire date. Also check this question in stackoverflow

    But... why not use plain normal session authentication?

    Please share your thoughts too

    1. 1

      Thanks for your input!

      This is the solution I will try to implement. I'll use JWT (httpOnly) authentication + CSRF Token, and store it in a cookie. Then, send them with every request in Axios.

      The main thing I had been afraid of was XSS and CSRF, but it seems like this solution solves the problem. The only way an attacker would impersonate the user is if they have physical access to their device.

      Thanks again for your help!

  10. 1

    load the js bundle in the django template. sessions and auth is built into django. it’s super easy.

  11. 1

    Hey @albertp201,

    None of the existing Auth solutions provide this, which is exactly why Authress is currently implementing a solution to use secure cookies (while supporting the other more common auth methods). It would handle most of the login flow and remove the need to implement anything yourself.

    While the functionality isn't globally available, it is something that we'll likely release in the next week or so. Let me know if you would be interested in early access to the feature and we can figure out what makes the most sense for you.

  12. 1

    I had a similliar issue.

    I used session authentication as @neon_affogato mentioned.

    But the issue was the user had to login every time the tab is refreshed.

    I recommend using JWT in your case.

    1. 1

      Thanks for your help!

      I'll be going ahead with JWT + CSRF Tokens. Thanks!

  13. 1

    I don’t know Django, but does this not work for some reason? https://docs.djangoproject.com/en/3.1/topics/http/sessions/

Trending on Indie Hackers
After 10M+ Views, 13k+ Upvotes: The Reddit Strategy That Worked for Me! 38 comments Getting first 908 Paid Signups by Spending $353 ONLY. 19 comments 🔥Roast my one-man design agency website 18 comments Launch on Product Hunt after 5 months of work! 16 comments Started as a Goodreads alternative, now it's taking a life of its own 12 comments I Sold My AI Startup for $1,500 and I'm Really Happy About It 11 comments