JWT destroy token on logout - angularjs

I'm developing a MEAN App, the problem that I have is that I want to destroy the token generated by JWT. Initially I thought that the logout function would the job:
router.get('/logout', function(req, res) {
req.logOut();
res.status(200).json({
status: 'Bye!'
});
});
But now I realized that "req.logOut()" is just a passport function that doesn't do anything to the token.
I send the token from client in the header of the request, so in case the user saved the token somewhere else, when logout, the user can still have access to the app if the token is included in the request. So my questions are the following, how do I destroy the token ?, is it "stored" somewhere ? is it ever auto-destroyed ?

I did not find any method to destroy simple JWT token. But I have a suggestion to solve your issue.
You can keep the token in DB for each session. So you can validate the client request by comparing 'token from DB' with the token in 'client request header'. While logout you can remove the token form DB. So user can't access the app after logout.

Related

Log out from all tabs/devices using React, JWT and cookie

I'm using React on frontend and Node on backend. How I structure the authentication is, when a user logs in, a JWT token is created and stored into the user data model. That token then get stored into cookie (instead of Localstorage).
Localstorage, on the other hand, is used to store user info such as username, name, and email.
When a user logs out, the JWT token is removed, and so is the cookie and userinfo in Localstorage. I designed my React so that if there's no userinfo in Localstorage, then the private routes would become inaccessible to users.
When a user logs out from all devices, all JWT tokens are removed (but cookie and Localstorage on other devices are not, since they are local).
However, this approach results in some problems:
since removing all JWT tokens doesn't remove the userinfo from Localstorage, the private routes can still be viewed, which is undesirable
after all JWT tokens are removed, even if a user wants to log out from another device, they can't, because now without any token, the user can't pass the authentication.
What would be a better way to structure the logOutAll component?
In order to logout the user if there isn't any JWT available, using Axios interceptor you can catch the response error and status. So in your case the API will response with status code 401 or any other status code you're sending. If the API fails with 401 status you could add your logout logic.
Here's the code snippet using Axios interceptor, hope this helps.
axios.interceptors.response.use(
(response) => response,
(error) => {
const { status } = error.response;
if (status === 401) {
// your logout logic goes here
}
return Promise.reject(error);
}
);

Misunderstanding the process of JWT authentication

I create project using React + Redux + Apollo Client + Graphql
When we need to log in in our app we need to use token (saved in localStorage for example) which is put in the headers parameter like in the code below:
const client = new ApolloClient ({
uri: 'http://localhost:4000/api',
headers: {
authorization: `Bearer ${localStorage.token}`,
},
});
After request server verifies token and becomes aware who is the user.
My question: from where do we need to get token and put it to the headers parameter for log on (sign up) process? A new customer comes to our log on page, he has no token (in localStorage or somewhere else) at the beginning but server requires it in the requests. And if we remove headers parameter from our client, the log on process will proceed but server won't understand who is the current user.
Typically the server would be the one issuing the JWT token, and this would happen during user login or maybe during account creation. For these particular calls, you should not be expecting the JWT in the header. Instead, the user would be passing credentials, such as username and password. For most other calls, it is appropriate to pass the JWT in the header of the request.
Keep in mind that the main purpose of the JWT is free the user from having to provide personal credentials during most requests. Instead, the user can just present a JWT, much as one would present a passport, to get access to your web services.
In response to your comments below, I would suggest that you keep the signup/registration process separate from the user-only area of your application. Here is a typical workflow:
Prospective user visits your site, and creates an account, by choosing a username and password, and possibly by providing certain other personal information
Your application creates an account, and then sends an email verification link to the user's email address. The server lands the user on a page which mentions all of this
The user opens the email, which contains a verification link, which when clicked will activate the account. Your application returns a web page which then asks the user to login.
Finally, the user logs in from the normal login page.
Note carefully here, that JWT were not at all involved in the signup process, nor do they need to be. The user JWT only needs to come into existence after the user actually logs in for the first time.
Decision:
you need to check for token in localStorage and update the request if token exists
const client = new ApolloClient({
uri: 'http://localhost:4000/api',
request (operation) {
const headers = {};
const token = localStorage.getItem('token');
if (token) headers.authorization = 'Bearer ' + token;
operation.setContext({ headers });
}
})

how to refresh token when expired in jwt

I am implementing JWT in my project. I implemented jwt and gave it an expiration time of 1 minute. The jwt that is generated from the api side is during login and the token and expiration details are sent in the result and are stored in local storage. How can I refresh the expired token from API side and send it back again to the client so that it can be stored in local storage and sent for every call using interceptor?
this is how I created jwt and gave expiration time
// let us suppose this is my input
tokenObject = { User: { username: name, pwd: pwd } };
//creating a jwt here
jwt.sign({ tokenObject }, "secretkey", { expiresIn: "60s" }, (err, token) => {
res.json({
token
});
});
After this, I'm verifying the token in the result and sending it in result to the client.
After a minute how do I regenerate the token?
Please help and let me know the way and tell me if I am doing something wrong . Thanks!!
You need to add a function or middleware that will check that the JWT is valid or not. You can use the verify method of JWT library:
jwt.verify(token, 'secretKey', function (err, decoded) {
if (err) {
if (err.name === 'TokenExpiredError') {
//create a new token and send the same way you created initially
}
}
});
You can create an API that accepts a JWT token, validates it and then issues a new token for the same user.
Take a look at the verify method of jsonwebtoken.
While verifying the token you can use ignoreExpiration: true option to verify the expired token as well. Then then generate the new one using sign method.
So while making the request from the frontend, if you get a token expired error, then you issue a new token using that API and save that token.
With that said, I do recommend you to take a look at the note about refreshing the JWT token from the docs:
First of all, we recommend to think carefully if auto-refreshing a JWT
will not introduce any vulnerability in your system.
We are not comfortable including this as part of the library, however,
you can take a look to this example to show how this could be
accomplished. Apart from that example there are an issue and a pull
request to get more knowledge about this topic.
Here is the link of the gist that has the code.

Angular - refresh jwt token

I am having a backend in Laravel and making an app in Ionic. I am using satellizer on the frontend side and this package on the laravel side for JWT authentication. Since I need to have token for users until they log out, I need a way to refresh their token somehow. I am not sure how to do this, would it be better to have all routes requesting auth token and sending 401 response if not present, and then do token refresh, or refreshing a token with timer on the frontend side and how to actually do that?
This is is my routes file:
Route::group(['jwt.auth', ['except' => ['authenticate']], 'prefix' => 'api', 'namespace' => 'Api'], function() {
Route::post('authenticate', 'AuthenticateController#authenticate');
Route::get('user', 'AuthenticateController#getAuthenticatedUser');
Route::get('comment', 'AuthenticateController#comment');
Route::get('articles/latest', 'ArticlesController#latest');
Route::get('articles/by-score', 'ArticlesController#byScore');
Route::get('article/{id}', 'ArticlesController#show');
Route::get('comments', 'CommentsController#index');
Route::get('comments/{id}', 'CommentsController#show');
Route::post('comments/create', 'CommentsController#store');
Route::put('comments/update', 'CommentsController#update');
Route::delete('comments/delete', 'CommentsController#destroy');
Route::post('article/upvote', 'VotesController#upvote');
Route::delete('article/upvote/delete', 'VotesController#destroyUpVote');
Route::post('article/challenge/vote', 'VotesController#challengeVote');
Route::delete('article/challenge/vote/delete', 'VotesController#destroyChallengeVote');
});
What I've done in the past is to do authorization on every request and then do create a new token when the expiry of the token in your database is within some length of time. For me, a 1 hour token would refresh if a user is still active within the last 15 minutes. Then, if the token is refreshed, set the new token inside of Laravel and invalidate the old. Or you could just extend the refresh time in the database. My recommendation would be to have some expire_time set when the token is initially created. And then return a 401 if the token is expired.

How can i expire my JWT token, when user is idle for sometime(Token based authorization) in nodeJS/Express and Angular

I am generating the JWT token for a user when he logs in with correct credentials at Server side.Previously,I was storing the token in database and for every request I am getting the token from database which leads to bad practice(If i am not wrong).At client side(In my controller),i can store that token in $rootscope so that i can send that token with each and every request.I am unable to find where should i store my JWT token to access at server side for every request??
Some one,suggested me to use Redis to store JWT token.
If i use Redis,can i set maxAge for my token which deletes the token when user is idle for certain time??
Can any one please provide me the suggestions for my procedure?If it is wrong,Suggest me with a right approach!
Note:I am new to NodeJS/Express and AngularjS
JWT's have an exp claim. Set it to the time to which you want the tokens to be valid and have a check in the route if the token has expired.
If it has, send a 401. Else let the route handle the request.
The simplest way:
Add 'validDate' field to token payload when you issue new token for logged user, then check this field when processing the request. If date is expired just return 401 error

Resources