0

What I want to accomplish is a secure and user experience friendly approach to authenticating and storing user's token.

  1. As seen here the recommended answer suggests to use a set of two cookies which would have to have the secure and httpOnly attributes (Since I have Django and React on different domains I would not be able to use any sort of sameSite cookie)

  2. In the same question the next best answer proposes using Redux (Is Redux even more secure?) to store the token in a variable and refresh it with a refresh token stored in LocalStorage that would be used to get a auth token. Now the problem I see with this is that he mentions that he used LocalStorage in his solution as a cookie would not be good for his stateless approach. If I am not mistaken a cookie is neither stateful nor stateless as is just a transport medium and what is inside is what is stateless or not such as a sessionId which Django does with its templates and Session Authentication.

  3. I have seen others recommend using an httpOnly cookie and a csrf token which is the approach I wanted to take. I want to have users authenticate and if user is found then a token is returned in a httpOnly cookie and a csrf token that can be accessible by js to prevent attacks. This would help mitigate both issues I am concerned about. Additionally, I would have to implement a refresh token as each time the page is refreshed the cookies are lost and I do not want users to have to log in every time they refresh. This is also what I think occurs in pages like SO or Instagram that have tokens in cookies and LocalStorage so there must be something good about it.

With this in mind and my goal mentioned I would like to know the best approach from a security standpoint and how could I accomplish this. I do not want the code to the answer as I am learning how to build my first application which might be used in real world and I security is important. As mentioned in the answer from point 2 despite my limited knowledge I do not see tutorials that just use LocalStorage and do not give it too much thought as helpful except for a quick app.

As of now this is how my API looks using Knox

class LoginViewAPI(generics.GenericAPIView):
    authentication_classes = [TokenAuthentication]
    permission_classes = [AllowAny]
    serializer_class = LoginSerializer
    @method_decorator(ensure_csrf_cookie)
    def post(self, request):
        serializer = LoginSerializer(data = request.data)
        serializer.is_valid(raise_exception=True)
        user = serializer.validated_data
        response=None
        if(user is None):
            return Response({"message":"The user was not found"}, status=status.HTTP_404_NOT_FOUND)
        else:
            response=Response({"user": userSerializer(user, context=self.get_serializer_context()).data})
            token = AuthToken.objects.create(user)[1]
            response.set_cookie(
                'auth_token', token, 
                httponly=True,
            )
        return response

I still have the to figure out the csrf token part as the decorator does not seem to do its job.

E_net4
  • 27,810
  • 13
  • 101
  • 139
ASC
  • 41
  • 6

2 Answers2

0

First, let me reiterate that Tokens stored in both cookies and localStorage are vulnerable to XSS attacks. The current best practice is to store tokens in a cookie with the httpOnly and Secure cookie flags. Unfortunately, Django REST Frameworks’ built-in TokenAuthentication is quite basic. It does not support setting tokens to expire, which is a security improvement that can be added. It also only generates one token per user, so a user on a website and then later a mobile app will use the same token. Since information about the user is stored locally, this can cause problems with maintaining and updating two sets of client information.

You can use JSON Web Tokens (JWTs) which are new, enhanced versions of tokens that can be added to the Django REST Framework via several third-party packages. JWTs have several benefits including the ability to generate unique client tokens and token expiration. They can either be generated on the server or with a third-party service like Auth0. JWTs can be encrypted which makes them safer to send over unsecured HTTP connections.

Your token should be stored on the local storage of your front end.

Patrick
  • 51
  • 1
  • 8
  • Yes, what I have done so far and correct me if I am wrong. I am using JWT and saving the refresh token in a http only cookie with the path set to the refresh token endpoint. Then, I am saving the access token in the application state and going with the classic refresh and access token approach. To logout I have an endpoint that overrides the refresh token cookie. I am not saving the token on local storage due to XSS attacks and for CSRF attacks on the cookie I am using a X-CSRF Token. – ASC May 28 '23 at 16:00
0

Yes. That's right. Storing your token in HTTP only cookie or server side will help mitigate risks such as CSRF, XSS, and Client-Side Data Breach. Concerning your stance on attacks on the local storage, no credentials are stored on the device, besides the token, which can be easily invalidated if needs to be. You can implement more secure communication protocols (e.g., HTTPS) and regularly rotating tokens can further enhance security.

Patrick
  • 51
  • 1
  • 8