prevent manipulation of JWT token in nodejs - node.js

I am trying to verify that somene if changed the JWT token from browser .The user should logout.
authorisedUser has some fields like username,id.
My code is working for only the case when any of this is changed and user is getting logged out.
But if i replaced this with another valid authorisedUser ,user is not logged out
So user A can user user B cookie and have access to his data.How should i change below code to verify it.
This is a light weight application so use of session or database is not there.
jwt.verify(req.cookies["authorisedUser"], "shhhhh", function (err, payload) {
if (err) {
res.redirect(db.env.application.logout_url+'?error=true');
//res.redirect(db.env.application.logout_url);
}
else{
//normal code}}

Related

Logout JWT with nestJS

I'm using JWT passaport to login module:
async validateUser(userEmail: string, userPassword: string) {
const user = await this.userService.findByEmail(userEmail);
if (user && user.password === userPassword) {
const { id, name, email } = user;
return { id: id, name, email };
}else {
throw new UnauthorizedException({
error: 'Incorrect username or password'
});
}
}
async login(user: any) {
const payload = { email: user.email, sub: user.id };
return {
access_token: this.jwtService.sign(payload),
};
}
This part is running.
My question is: how do the logout? I read about creating a blacklist and adding the token to it, but how do I get the user's access token?
Something you should know about token-based authentication is that it is stateless. This means that even the server does not keep track of which users are authenticated, like with session-based authentication. As such, you do not need to do anything on the server side to "log out" a user. You simply need to delete the t\JWT token on the client. If you make a request to the server app, without a valid JWT token, it will be treated as the user is not logged in.
Generally when a logout request would be sent the Authorization header should be present, so you can grab the token from there. Then you can save the token to the database's restrict list table.
When user click to "Log out" btn, you should sent a request which is attached Authorization header with bearer token. In the backend side, you need to extract header and push the token to the blacklist token (as your solution). Basically, you only need remove token in client side, it's so easy to do but in the worst case when the token was stolen by hacker, your token still valid. Using blacklist token is more secure but it can be lead to performance issue and scalable. What is the best solution? it's depend on you.
Read the Nestjs Execution context get the token from the request header and verify this token from JWT.
everything defines in the NESTJS link
//here we check the token from the header is valid or not expired
const tokenVarify = await this.jwtService.verify(token);
my idea is make whitelist every generate new token and remove it when user logout. so u need to check on guard also every user with token access its exist on whitelist or note
You must be refresh expire token to 1ms with:
https://webera.blog/how-to-implement-refresh-tokens-jwt-in-nestjs-b8093c5642a9
Actually there is a workaround for this, but not so straightforward!
The idea is to keep track of the tokens for logged out users (use some sort of black-list) and query provided token against that black-list.
To sum it up, you can follow these 4 steps:
Set a reasonable expiration time on tokens
Delete the stored token from client side upon log out
Have DB of no longer active tokens that still have some time to live
Query provided token against The Blacklist on every authorized request
For detailed explanations, you can check this post: medium
A guide in how to do the implementation is in this youtube video
Code with Vlad
, and there's as well the github source nestjs-jwts. I followed this video and implemented myself as well..

firebase.auth().currentUser returning null

In the html file that I have for the sign-in page, I perform the authentication using Firebase and on successful authentication, I redirect the given user to the homepage. When I call firebase.auth().currentUser in the express file, I use for rendering and routing pages, I get undefined or null for the current user.
Can anyone help me understand what the issue might be?
This is how I perform the authentication:
firebase
.auth()
.signInWithEmailAndPassword(temail, tpass)
.then(function(firebaseUser) {
window.location.href = "http://localhost:5000/homepage";
})
.catch(function(error) {
window.alert("incorrect pass");
});
This is the code that I have in my express file:
app.get("/homepage", (req, res) => {
var user = firebase.auth().currentUser;
console.log("USER IS " + user);
res.render("menu", { title: "Welcome" });
});
Backend code doesn't have a sense of "current user". When you sign in on the frontend, the current user is only known on that client. It isn't known on the backend. If you want the backend to know which user is signed in, the client will have to send an ID token to the backend for it to verify. The documentation for the Firebase Admin SDK is used for that on the backend. The client must send the ID token to in the request to your route, and the code handling that route must verify the token in order to know the user that made the request. From the documentation:
If your Firebase client app communicates with a custom backend server, you might need to identify the currently signed-in user on that server. To do so securely, after a successful sign-in, send the user's ID token to your server using HTTPS. Then, on the server, verify the integrity and authenticity of the ID token and retrieve the uid from it. You can use the uid transmitted in this way to securely identify the currently signed-in user on your server.
When the user lands on a new page, Firebase automatically restores their previous authentication state. But to do so, it may have to contact the server, which means that it may take a few moments. While Firebase is restoring the state, auth().currentUser will be null.
To ensure you get the correct authentication state, you should use an authentication state listener, as shown in the documentation on getting the current user:
firebase.auth().onAuthStateChanged(function(user) {
if (user) {
// User is signed in.
} else {
// No user is signed in.
}
});

Authorize a WordPress site and a React app with a web hook and token?

Problem: The client is using MemberPress/Wordpress as their main platform. The users are being managed there. I built a React app to coexist with the Wordpress platform.
What I have done: Memberpress has webhooks. So when a user logs into WordPress I hook into that action with a node server that inserts the user into a custom database and I generate a token so that the user can access the nodes the user owns within my infrastructure.
module.exports = (req, res) => {
const { id, email } = req.body.data;
request(
"https://api.graph.cool/simple/v1/73289237283967",
mutation,
{
wpId: id,
email
}
).then(data => {
res.json({ status: "success" });
});
};
The above gets triggered every time a user logs in. This executes a graphQl mutation that has a custom resolver that checks if the user with that wpId exists. If not it will create a new user. Then it generates a node token https://github.com/prisma-archive/graphcool-templates/blob/master/auth/email-password/src/signup.ts and sends back in the response.
Once I obtain the token I can make requests on the user.
Problem: I am not sure how I can connect the two. I have to redirect the user to the wordpress login page. The login action triggers the event, and a token will be generated. I am not sure how I can store that token in an efficient way that can then be sent back to my app.
My thought would be to write a small plugin inside WordPress to handle the response of the hook and store the token in local storage within WordPress. Then whenever the user clicks to go to the app I can put the token in the URL (feels slightly weird and cant directly go to the URL). I am out of any other thoughts and would appreciate a nudge in the right direction.

Phonegap + Hello.js (server side authentication)

I have a Phonegap application that is communicating with Nodejs server.
Also for the Facebook\Twitter login I'm using Hello.js library (which is very easy to use by the way).
Unfortunately this library only makes client side login (authentication), so at server side I don't know if the user is valid or not (have been looged in with Facebook\Twitter).
Edit:
After the user is logged in (client side), Hello.js provides the user credentials, with a Facebook unique user ID, but I don't know how to pass it safely to the server, or generally if its a good idea to use it as a user id in my DB.
I'm looking for a simple example that will check the validity of the login at server side too.
Thanks.
If you are using https then sending the id to your server will be fine. What you can do is just check to see if that unique id already exists in your DB and return that users data (if needed) or create a new account.
I would also recommend creating a JWT (JSON Web Token) on the server side and sending that back to the app to be stored in local storage and used to validate all future requests to your node server. You can implement that method pretty easily if you use the jwt.verify method as middleware on all of your routes.
Here is a quick example:
var jwt = require('jsonwebtoken');
var jwtValidation = function(req, res, next) {
var token = req.body.jwt_token;
if (token) {
jwt.verify(token, 'yourSecretKeyHere', function(err, decoded) {
if (err) {
// Error when checking JWT - redirect to unauthorized
res.redirect('/unauthorized');
} else if (decoded.id) {
// Token that was passed in has been decoded
// Check your DB for the decoded.id
// Complete any other needed tasks then call next();
next();
} else {
// Something else went wrong - redirect to unauthorized
res.redirect('/unauthorized');
}
});
} else {
// No token present - redirect to unauthorized
res.redirect('/unauthorized');
}
};
module.exports = jwtValidation;
This is the main idea as I figured:
In the Phonegap application, after the user has logged in, this function will be called:
hello.on('auth.login', function(r){
var token = r.authResponse.access_token;
}
now, you can send only the token to the server, and the server will get the user credentials directly from Facebook.
For example, in Facebook, call this usr:
https://graph.facebook.com/me?access_token={token}

Using Resource Owner Password in Oauth2orize module

I am developing an app with an mobile client for which I want to deploy Oauth2orize as Oauth server an use authenticate with Resource Owner Password way. But I am not able to understand how the flow should be. I searched for lots of examples but could not find one where this use.
What should the flow be to give a token to the client?
This came a little late but I think this post can help someone else. I just spent a week trying to implement this because oauth2orize mix all the oauth flows in one file in the samples so is difficult to figure out which one to use to obtain the desired result.
To start answering your question you ask about a resource owner password grant as described here. This should give you a head start on the steps defined by oauth2 to exchange a username(or email) and password for a token and optionally a refresh token.
Step 1: The client requests a token using username and password to the authorization server
Step 2: The authorization server issues a token to the client if the client has valid credentials
So you start sending a request to an authentication resource in application/x-www-form-urlencoded format containing a username, password and grant_type params, optionally you can also use scopes. Oauth2orize provides the server.token() function which generates a middleware to parse this request.
app.post('/token', server.token(), server.errorHandler());
But before this stage you should have the server created and configured. I usually use a different file and use module.exports to pass the middleware back to the app.
authorization.js file
// Create the server
var server = oauth2orize.createServer();
// Setup the server to exchange a password for a token
server.exchange(oauth2orize.exchange.password(function (client, username, password, scope, done) {
// Find the user in the database with the requested username or email
db.users.find({ username: username }).then(function (user) {
// If there is a match and the passwords are equal
if (user && cryptolib.compare(password, user.password)) {
// Generate a token
var token = util.generatetoken();
// Save it to whatever persistency you are using
tokens.save(token, user.id);
// Return the token
return done(null, /* No error*/
token, /* The generated token*/
null, /* The generated refresh token, none in this case */
null /* Additional properties to be merged with the token and send in the response */
);
} else {
// Call `done` callback with false to signal that authentication failed
return done(null, false);
}
}).catch(function (err) {
// Signal that there was an error processing the request
return done(err, null);
})
};
// Middlewares to export
module.exports.token = [
server.token(),
server.errorHandler()
];
Later in your app you write something like this
var auth = require('./authorization');
app.post('/token', auth.token);
This is a basic example of how you do it. Moreover you should enable some sort of protection on this endpoint. You could use client credential validation with the passport-oauth2-client-password module. This way the client variable in the oauth2orize.exchange.password function will contain information about the client that is trying to access the resource enabling an extra security check for your authorization server.

Resources