1

I'm changing the authentication to handle expiry on a website that is still under dev. (so have full control over changes at the moment). This is what I currently have (Pseudo code). I have included 4 routes and the db currently holds userToken (id of user), userSecret (changes when user logs out)

SignUpRoute.post('/signup', (req, res) => {
//Save userdetails, userToken, userSecret in DB
}


BidderRoute.post('/logout', userAuth, (req, res) => {
find account with matching email
update db.userSecret
response success
}

userRoute.post('/login', (req, res) => {
if req.body.email === db.email
if req.body.password === db.password(hashed)  
response (db.userToken, db.userToken)  //can this be a cookie?
    
ProductRoute.post('/data', userAuth, (req, res) => {
// some action here
}


userAuth middleware:
req.body.userSecret, req.body.userToken from body
fetch db collection where req.body.userToken === db.userToken
if userToken !== db.userToken && userSecret !==db.userSecret then error (401) - redirect to login
next()

I require to add an expiry to prevent the user from being logged in for more than 30mins, so figured I should add a expiry field in collection and alter /login route and middleware:

userRoute.post('/login', (req, res) => {
if req.body.email === db.email
if req.body.password === db.password(hashed)    
updated and save db.userSecret
updated and save db.expiryDate //30mins
response (db.userToken, db.userToken)  //can this be a cookie?

ProductRoute.post('/data', userAuth, (req, res) => {
// some action here
}
    
userAuth middleware:
req.body.userSecret, req.body.userToken from body
fetch db collection where req.body.userToken === db.userToken
if  now > db.expiryDate  then error (401) - redirect to login
if userToken !== db.userToken && userSecret !==db.userSecret then error (401) - redirect to login
if db.expiryDate < 2mins remaining then renew db.expiryDate (save in db)
next()

Q1. Before I implement I'm wondering if I've missed anything obvious in the steps.

Q2. Currently the front-end stores the userSecret and User token in local storage, and the server sends out a 200 response with userToken and userSecret (not a cookie) (see /login). If I want to hold this data in a cookie on the FE, should the above code be sending a cookie instead or does it not matter as the FE can save the response a s a cookie?

UPDATE - If I was to use a cookie - Because cookie has an expiry, I think I can just use this rather than attempting to maintain expiry in db. Will the below work ?

userRoute.post('/login', (req, res) => {
if req.body.email === db.email
if req.body.password === db.password(hashed)    
updated and save db.userSecret
 send cookie (with userSecret, userToken)  with 30mins expiry


ProductRoute.post('/data', userAuth, (req, res) => {

Refresh cookie here ?
}


userAuth middleware:
If cookie received //i.e. not expired
    else re-direct to /login
    
Parse userSecret, userToken from COOKIE
fetch db collection where req.body.userToken === db.userToken
if userToken !== db.userToken && userSecret !==db.userSecret then error (401) - redirect to login
if db.expiryDate < 2mins remaining then renew db.expiryDate (save in db)
next()

1 Answers1

0

I think you can add jwt-token in the headers in order to authenticate logged-in users.

  1. Once the user logins in create a payload and create a jwt-token and add it to the response.

  2. On the subsequent request from the FE you can add the auth header with same token.

  3. On the backend, verify the token, if it is expired try to refresh it and follow the step first again.

There are several tutorials available online to help you create jwt-token. You can check here. Also, this article is really good to setup authentication on node.js.

Q1. Before I implement I'm wondering if I've missed anything obvious in the steps.

There are quite a few mistakes in it. You should not save token on DB's instead use JWT-token to check the expiry, you can also use sessions in node.js

Q2. Currently the front-end stores the userSecret and User token in local storage, and the server sends out a 200 response with userToken and userSecret (not a cookie) (see /login). If I want to hold this data in a cookie on the FE, should the above code be sending a cookie instead or does it not matter as the FE can save the response a s a cookie?

To allow FE to save this response in the cookie, you need to create one at the backend. When you attach it to the response browser on the subsequent request will attach it automatically. Go through how cookies work.

Apoorva Chikara
  • 8,277
  • 3
  • 20
  • 35
  • The links are excellent, thanks. I think JWT may get complex, particularly around refresh token. If I chose cookies I think I could avoid maintaining a expiry in db as in the original idea. I've added an updated pseudo to question - is this correct? Also, I understand that if I was to use cookies, the server should send res.cookie('session_id', mycookie). True? – Orange Juice Jones Mar 21 '21 at 18:30
  • When you say 'You should not save token on DB's', which token are you referring to, is this true if i was to use cookies as described in the updated pseudo? – Orange Juice Jones Mar 21 '21 at 18:40
  • Usertoken that you referred is in the question provides access to the user on diff routes. Generally, these sessions/usertoken should be stored in the cache like Redis or session storage. Please check this link : https://security.stackexchange.com/questions/72475/should-we-store-accesstoken-in-our-database-for-oauth2 – Apoorva Chikara Mar 22 '21 at 06:10
  • If I chose cookies option I think I could avoid maintaining a expiry in db as in the original idea. I've added an updated pseudo to question - will this work? – Orange Juice Jones Mar 22 '21 at 10:43
  • Yes, that looks good. here is the link that can help you to do it. If the answer helps you can accept and upvote. Thanks! – Apoorva Chikara Mar 22 '21 at 16:15
  • I think you have missed the link? – Orange Juice Jones Mar 22 '21 at 21:11
  • https://stackoverflow.com/questions/14049294/change-cookie-expiration-in-express. this links might help you to check the cookie expiration and extend it. hope that helps! – Apoorva Chikara Mar 23 '21 at 07:47
  • In my update, I refresh the cookie (expiry time) in the /data route. However its the middleware function that authenticates cookie. Should the cookie not be refreshed here, otherwise I will need to alter all the routes to send a refresh cookie. Which is best option here please? – Orange Juice Jones Mar 25 '21 at 10:34