Gaining an understanding of Session Cookies and JWT Token

Thanks for stopping by. For a brief context, I’m currently create a ecommerce side project for my wife which may (most likely) use PayPal API for when dealing with purchases. Now here is the tech question I’m trying to better understand. Please correct me if I’m wrong with some things.

Session Cookies - This is something that we can create locally. One form is by using Phoenix put_session and save the information we may need in the future like a user ID and we can remove/delete the information after the user logs out is my understanding. This will help keep the user logged in.

JWT Token - This one confuses me. From my understanding we will parse the information from the header (HTTP request). Although what I don’t understand is while I implemented a context file and guardian file that suppose to check and insert a current_user, it is always failing since in routes, it runs before we hit any controllers. I learned it is because we need to send a Bearer and token to authenticate the user. But the part that confuses me is, if we need to send this information, how is this information being send from the frontend when making a http request?

Session Steps -
1 - hit end point login_user
2 - check if the user is valid
3 - if true save to the session cookie
4 - logout endpoint
5 - remove current_user from session cookie

JWT Token -
0 - Check if current_user exist
1 - hit end point login_user
2 - check the header token if present
3.1 - Not present returns %{}
3.2 - Present then check if user is valid by checking password and saved password_hash
4 - return {user: user, token: JWT_Token}

From the steps what I don’t get is when does current_user get placed in a session through JWT token? and how are we sending authorization/token to the backend when lets say my React project does an axios request of post with user information? One solution I noticed some people say is save to the DB the token but also seen people say that is a bad idea.

Thanks for the clarity on these concepts.

1 Like

If you are using graphql you don’t need axios, you can use apollo to send directly the graphql api to the frontend.

A naive implementation of this I have here https://github.com/wolfiton/medium_graphql_api/tree/develop.

It uses guardian and Absinthe context to set the token for the login mutation.

This project is under MIT and will be available fully after I finish it with the help of others.

In this branch i don’t have the apollo part but it should be available here https://github.com/wolfiton/medium_graphql_api/tree/tao_branch

Also the frontend is not react but quasar which is a vue based framework something like preact, but much more.

Hope this helps

Hello @wolfiton Thanks for replying and showing an example with what you are currently building. After checking your github, I noticed my files are exactly the same in regards to the approach except two things.

First, for me when I do Guardian.decode_and_verify(token) I get in return an error related to the function saying it requires decode_and_verify/4 same for signing. Was there something done to avoid the approach of having to write Guardian.decode_and_verify(MyApp.Guardian, token)

Second, I was planning to use Apollo and actually did not know with Apollo we wouldn’t need Axios. (I haven’t gotten to the frontend yet, but thank you for that heads up). With that in mind, I’m still a bit confused in regards to JWT_Token and it’s existent.

As I mentioned earlier, when context.ex runs, it does right from the beginning where technically the header should fail as a token shouldn’t exist. But I don’t see the token being saved anywhere but instead it is being returned.

Question - how does this work
1 - Hit sign up user (meaning a token doesn’t exist for them)
2 - Before it hits the method, context would run meaning since it can’t find a header token it’ll return %{}
3 - sign up method runs which should create then sign out user returning user and token

What I don’t get is how do we use token for authenticating? I don’t notice us saving it ever during the entire flow and I’m wonder when we return token do we save that to Apollo? is that how we are using token to authenticate when making a request?

Again thanks for the help in understanding and really appreciate the GitHub project you send. Really will help in understanding where my approach was wrong.

Glad I could help you,

So the JWT or JSON WEB TOKEN is saved in localstorage in the browser, but in my current implementation, I am not at that stage yet.

The token will have usually the following values issuer validity(exp) and user id.

  • Issuer makes sure that the token was created by our backend
  • validity(expiration time 1h 1m 1y) the time it takes to expire and becomes invalid
  • userid - the id of the user that is logged in.

To understand better about auth I also asked some questions here and posted a video about json web tokens in post 3, you should watch that video because it explains JWT.

Also the talk is being help by a security expert at okta.

PS: If you are not using a lot of js in your app a better approach is to maybe use phoenix directly with html views.

Here is that function used in the plugs to set the context of absinthe medium_graphql_api/lib/medium_graphql_api_web/plugs/context.ex at develop · wolfiton/medium_graphql_api · GitHub

To get a better understanding on how this all works clone the repo and try to play with it.

Use the playground in graphiql to create and login users.

I also new to phoenix elixir and vue, maybe this tut could help you get a better idea of the whole project it was the inspiration for my current project https://www.youtube.com/watch?v=uoCFQu9gQHE&list=PLw7bfDlTRWbgiApK7X1bRKJJ03xoDU3hm

1 Like

Hello @wolfiton I just got home. First, I would like to say thank you for providing everything to me. Also the video in regards to Session Cookies vs JWT. It really was amazing to see from an expert why they still would advise to stick what has not been broken.

Although I’m still puzzled by the idea how so many companies decide to use JWT instead of pure cookie based. I even had friends tell me it should be something I should implement to improve a bit of security.

I got a question. Since I noticed your post you’ve been trying to find a way not to use JWT, is there a reason why you still continued after watching the video? or that is for a different project?

1 Like

After i had some private discussions with different members of the forum they convinced me to try both auth ways.

So the project(Medium Clone) that I am doing, with the help of @FelisOrion and other members of the forum will be:to create 2 versions:

  • one with JWT auth
  • one with cookie auth

I considered that if you receive(help, guidance) something from a community like the one at elixir forum then you need to give something back to others.

This is a wide topic. Session Cookies and JWT tokens are not the same thing and though when we compare them only by their names we are not comparing the same thing.

Using session cookies for authentication is a good use case scenario of cookies if your backend server is a monolith or if you have some kind of API gateway that keeps and translates cookies into user_ids for other services and you are not using something like zero-trust network.

JWTs are more of a tool than a user authentication solution. It comes in 2 flavors: signed tokens (JWS) and encrypted tokens (JWE). Both have their use cases that almost always fall on the category of distributed trust, like all your servers need to verify the authenticity of a token and you won’t share a global cookie store because you would need to also share the cookie signing keys and so on.

So, in my personal opinion, use what makes more sense to you. If it is a simple single server just use a cookie session and you’re good. Remember to make your cookies https only (to avoid JS accessing those) and you should be fine.

When the time comes for a more complex authentication/authorization solution, look for different approaches. One of them might be JWTs which might be persisted but make sure to research first.

To answer one of your questions, the traditional way of passing authentication data in the standard HTTP specification is to use the reserved header name authorization. The value starts with the name of the authentication scheme (something like “Basic”, “Digest” or “Bearer”) and the value of it. See here for a better explanation.

When you use cookies, the frontend also sends them through headers, in this case, the COOKIE, header. See here again for a better explanation.

@wolfiton be careful when storing tokens on local storage! It is not best practice when dealing with tokens on the frontend. See here for reference.

2 Likes

Thanks @victorolinasc for the reference, but I am building a SSR not a spa with PWA capabilities.

So from my point of view I would gladly just use encrypted cookies with expiration time of 1 day then deal with json web tokens that are vulnerable to xss no matter where you store them.

But all the major frontend frameworks support officially only the jwt implementation if you want a cookie one, you will need a lot of luck to find a tutorial or a reference how to do that. In most cases you will get a nice advice to give up or do it yourself, because cookies are not important and they don’t have time for this. So use JWT in loclaStorage because it is easy and secure. Which is evidently not easy or secure and the reject tokens need to go in a blacklist.

That is my experience with this topic

Also wanted to add that OSWAP doesn’t like JWT’s in general.

Also if there is interest at what i am trying to build let me know and I will create a separate thread with the idea and some simple documentation, even though right now i am trying to figure out the best practices to create the medium clone.

So for several days I will be busy reading learning and comparing the different option i have available to create this.

That’s to be expected as cookies with http only active are not readable to javascript. They’re only useful to the server, but not to any client side code. But the question is: Do you need authentication handling on the client side?

I will have use the client side when the app goes in PWA(Progressive Web App) mode. So i was thinking to set a cokkie server side with expiration of one day. But then again i will get into the problem that my client can’t verify if the cookie expired.

Hello @victorolinasc Thank you for replying and providing links to better understand. I loved the video presented in User management with absinthe for api by @wolfiton which had a discussion why JWT isn’t safe and how vernible it is in comparison to a session token. That is something I never knew since most of my friends who have been in tech longer than I have (just landed my first job a few months ago) all recommend adding JWT to your application.

Although I would like some clarity. The Stack I’m implementing for this project currently is BE - PostgresQL, Phoenix/Elixir and Absinthe/GraphQL as for the FE - React/Apollo.

After reading the link regarding cookies and how it’s being send from the FE to the backend as a header I’m now becoming confused with the purpose of JWT. I thought its use was to mainly send a userID to the frontend and save their information in order to persist that a user . is logged in. We then use that ID to find the user and check if it matches to lets say their email when logging in.

The way I saw it was not save any information into a JWT except for the user ID that we can use to look them up when logging in. After logging in we should just save the ID? or do people normally save the entire User? and if yes why is this the case when it’s a risk of leak occurring?

Also am wondering if cookies are safer as most including OWASP have stated, would it be recommended to use backend to check the cookie is valid before sending information back? if we wanted to persist some information should we for example in regards to cookies

1 - hit backend when logging in
2 - save user to cookies
3 - send logged in user information (mainly use the ID) and save to a state management like Redux as current_user: 1
4 - This will be our false catch to use when trying to validate a user interaction to the frontend?

Reason I mentioned redux is because I don’t have much experience with Apollo/Client yet.

Again thank you for clarity and also providing your experience/feedback on this matter.

If you need to handle auth client side (without the server being available) then cookies are not useful to you. Cookies are only a good storage for session IDs/data because http only ones cannot be read/modified by the client and the server handles everything related to authentication. Once that’s out of the picture you need to look for alternatives.

1 Like

Hello @LostKobrakai Thanks for replying to this post. I’m starting to question a lot of things. I know when I build personal projects at a bootcamp we never used JWT but instead a session token. I haven’t done a project in a while since I got hired and as I’m about to build a project different questions have appeared, especially the use of JWT since most of my friends who has been hired much longer have said it is required in all apps, one main reason for this post was better understand the purpose and reason.

The more I read, the less I understand the reason behind JWT. Since now that I think about it, if we want to have restriction or authentication, we can have it check the cookie at every request and in a login just send the user as the current user to the frontend to be kept in a state management, right? Or is there a form of authentication that can be done with a token for the frontend as well? (new questions are coming to mind the more I’m seeing these post)

Again thanks for the feedback and opinion. Sorry if I’m also lacking in knowledge.

Thanks @LostKobrakai, for the idea, but figure some time ago that using a hhtp only cookie will not help, so going the jwt path seems like a dangerous road.

So maybe just use the cookie server side and when the client goes in pwa(offline) let it be and verify everything once it gets online again might be a better option.

Have you encountered this type of solution is it achievable?

@wolfiton That is something I never considered (also I just learned what PWA means from you so thank you for that one). I can see now why we would want some form of frontend validation. But couldn’t we mostly just for example save the user that logged in as current_user to a value in a cache/state management and then use that to verify if they are allowed to do something while access to the backend is unavailable? such as if current_user_id does not match the post.user.id (bad example) then we can’t allow them to make any changes? Just a thought.

Everything that is in JS is vulnerable to XSS Attack. So the state management falls under this category. Also if we do that then we will fall under the JWT path.

So it is not a very good solution.

One other thing to consider in pwa while offline is:

  • do we let users make changes(and then updated them once online again)
  • or only allow them to view the content

So many things to consider, so very little time

@wolfiton That is something I’ve been learning since I posted this question. How unsecure JS really is compared to when using cookies. But I also agree with so little time. I’m in the process of building to MVP ideas which also places security as important since 1 uses credit cards (maybe this can be resolved with Strip and if not I’ll use PayPal for safety). The other doesn’t have credit cards involved but I want my future clients to feel secured using my application since I really care about security.