I am using express js with mongodb
Using jsonwebtoken for authentication
after successful login i put a token in cookies
For incoming requested data i check the token in cookies. if token is valid i
re-generate token and puts new token in cookies and response
requested data (just like refreshing token for each request).
Till now everything working fine and no use of db
I want to invalidate old token without db, but seems that it is impossible So doing thing as mentioned below.
For successful login i set the cookies with jwt token. Also store
that token in an array and user's info document in db too.
For each request for data i validate the token and check the token
present in array matching or not, if match i delete that token from
array generate new token put new token in array and user's info
document in db, again set new token in cookies and response data.
Above step also working fine and i am able to invalidate old token
But what if server down?? If server down all token for each users lost and all are forcefully logout
For preventing that issue i check the token in user's info document in db if token for matching token
By doing this step, no need to go in db and check for valid token or not. Db lookup only when token not present in array.
My question is for security and speed performance
Question is this implementation good? Is speed performance will be good as users increase and so many token in array for each user. Means need looping all token for matching a token in array.
Sorry for bad english
Related
I am currently making a login and registration system as a project for a website, but I am uncertain of how I can safely implement the routes/logic for it. Currently, in my client side code I send a fetch request to my login or register route, and do the logic there, and then send a JSON object back, which is manipulated whether there is an error or not, and I have implemented CORS and Header (Origin and Referrer headers) authorization middleware within my POST routes, so no external script can mass produce users/login [aka brute force]. Is there another safer and better way of handling this?
What you want to do is, to use either JWT or Session Cookies.
Algorithm ->
User visits the /login page
User enters user id and password
U send a fetch or Axios request to your servers POST API route
axios(`/<api_route_here>`,{
method: "POST",
headers: {
Authorization: `Basic ${btoa(`${username}:${password}`)}`
}
})
In the above code, we are encoding the username and password with base64 and then sending them back to the server with the Authorization header. username:password
Note: Make sure u are using an HTTPS connection
In the server u decode the Authorisation value from the header. Then create a hash of the password with username as its salt. Then query your database if the hash matches the user's password's hash.
We are hashing here to prevent leaking passwords in case of a database hack.
It is obvious, that you will store the password for the user using the same hashing technique.
If the query is positive then send a 200 response else send a 401.
In the Axios promise resolution check for the headers status code to figure out if the sign-in was successful
To prevent asking the user their password every time. U must use session cookies. i.e in step 4 if the password is correct add a Set-Cookie header property with a session token value. Store that session token to your database. Next time you API is hit, check for the cookie. if the cookie exists then check that session token with your database. otherwise, send a 401
To prevent route spamming, implement a captcha.
I'm in doubt, how should I get current user info, should I pass it with token while logging in or get it by decoding token and querying by token payload ?
In second case I should make a request every time I need current user info, I guess it's better to have less requests because of performance..
Before getting to the actual question
Alright I have created my own authentication system that I am going to use on my API.
Simple explanation:
On /signup the user types in username, password etc... the API grants the user with tokens which are stored in the user document in the database. The API also returns with a response body with the new refreshToken and accessToken, my thought here is so the app easily can store the tokens on the phone for later calls to the API.
/login is pretty much the same thing except you only provide username and password.
One of the routes in the API is the /article which you can GET & POST.
Now if you try to for example GET the /article and your accessToken is expired the API will automatically call /token which requires the refreshToken in the header, the /token will then grant you a new accessToken and request the same route you were trying to get (in this case /article) with the new accessToken in the header.
The question:
What is the best way to update the accessToken in the app with the new accessToken?
router
.route('/article')
.get(
AuthenticateController.authenticate,
NewsController.getAllArticles,
AuthenticateController.sendAuthorize
);
This is how I do it now, AuthenticateController.authenticate authenticates the accessToken and checks if it is expired and all that then calls next().
The NewsController.getAllArticles gets all the articles and also calls next() so the AuthenticateController.sendAuthorize can run and return the new accessToken in the response header when a new one is granted (I thought this would make it easier to obatin the new token in the app). This is where my question comes in because I can't call next() on every route because on some routes the main function already returns a response and that means that next() cannot be called which means AuthenticateController.sendAuthorize will never run. I want the AuthenticateController.authenticate to be the only middleware required to authenticate the user.
Instead of waiting until the last route to send the new token, you should move the sendAuthorize middleware above the route's main response (or combine it with authenticate), and instead send a 401 Unauthorized response with the new token. Then, update the token on the client and resend the request.
It seems like a silly practice to send a valid response with an invalid accessToken anyway. You're going to want to invalidate tokens eventually (I.e on log out or password change), and you don't want users to be able to make unauthenticated requests.
I'm creating an app using Angular 1.5.8 and Laravel 5.2. I'm using a library by Luca Degasperi to create Token Based Auth
Via Angular I make a call and I receive access_token, TTL and refresh_token. I store access_token and refresh_token on localStorage. I can use access_token that I get to make calls to get some data from my API. When token expires I'm getting a message that the token is invalid with 401 code
So my question is how to check if the token is still valid before I send a http request to my API? What is the best way to refresh the token? Ok, I can send a request for the refresh my token to https://my.api/oauth?grant_type=refresh_token&refresh_token=f32j93201h00xpaf1, but how to check it before every http request? Can I repeat the call if the response code is 401? And how?
Please, give me some advice :)
I had exactly the same problem few days ago. Angular Error response interceptor is all you need ;) Also, this article was really helpful
You cannot. You have to check against a login. Therefore it's just a re-login.
I guess that if you get a 401, your refresh token is already done.
Though I guess that you can join that refresh token with all your requests? I might be wrong.
Ensure that your token TTL is always up to date by refreshing its TTL from time to time (like with requests to your API).
Can't you use the TTL to determine if the token is still active? When you store your tokens in local storage you can add the date/time the token was stored and each time you go to make a service call you can check the TTL against the time the token was stored.
It will only tell you when it expires, though, and not if the token was invalidated for some other reason.
Essentially, I want to just pass the ID Token and the Access token into a cookie so that I can access them from another url that my app links the user to after logging in and returning these tokens. After I have the ID token and the Access Token in a cookie, I want to be able to access them in the next url and then check if they have not expired. How would I go about doing this?
I can't really find documentation on this as User Pools are still in their Beta on AWS. Thoughts?
Thanks
The ID and Access tokens are formatted as JWT (JSON Web Tokens). These tokens have additional details (including expiration) embedded in their payload. You can parse payload of ID and Access tokens as a JSON string and read the token expiry timestamp. Use this timestamp to find out if the tokens are still valid.