I'm using JWT - jsonwebtokens in Nodejs.
I'm creating a token and want to throw an error if the token expires. My token is created successfully and I'm checking the token expiry in middleware of Apis in Expressjs. Then token is sent from Angular in headers and the expiration is checked in middleware.
This is how I'm creating the token:
var token = jwt.sign({
id: id,
expiresIn: '2m'
},
'mysecretkey'
);
This is how my middlware looks like:
var token = req.headers['authorization']
var idToken = token.split(' ')[1]
if(token) {
jwt.verify(idToken, 'myscretkey', (err, decoded) => {
if(err) {
return res.status(400).send('Session expired')
}
next()
})
}
This is what I'm receiving in decoded:
dec: {
id: 'an id',
expiresIn: '2m',
iat: 1596744770
}
In this case, my token is not expiring even after 2 minutes.
How can I achieve this?
In your code you added expiresIn as part of the payload. But there expiresIn has no meaning and you need to use the standard expclaim for expiration:
jwt.sign({
id: 'an id',
exp: Math.floor(Date.now() / 1000) + (60 * 2),
iat: Math.floor(Date.now())
}, 'secret')
in this example it's 2 minutes.
You can also calculate:
(60 * minutes), (3600 * hours) or (86400 * days) for minutes, hours or days.
expiresIn can be used as an option to the sign method as shown in Shivam Soods answer. I think that's the reason for your confusion.
If you want to work with hours or minutes using expiresIn you need to declare it after your secret like this
let token = jwt.sign(id,'mysecretkey',{ expiresIn: '1h'});
Read more about it here
Related
I am trying to set the expiresIn function in my javascript app. I am following the documentation, but I keep getting this error. Can anyone see what I am doing wrong?
app.get("/user", async (req, res) => {
const { name } = req.body;
const accessToken = jsonwebtoken.sign( name, process.env.ACCESS_TOKEN_SECRET, { expiresIn: 60 * 60});
res.json({ accessToken: accessToken, name })
console.log(accessToken, name)
})
Your payload needs to be an object otherwise it's treated as a string. Try this
const accessToken = jsonwebtoken.sign( {name: name}, process.env.ACCESS_TOKEN_SECRET, { expiresIn: 60 * 60});
Given the following resolver for a mutation:
async signin(parent, { name, password }, ctx, info) {
// Check if there is a user with the name
const user = await ctx.db.query.user({
where: { name }
})
if (!user) {
throw new Error('Name not found');
}
// Check if the password is correct
const valid = await bcrypt.compare(password, user.password);
if (!valid) {
throw new Error('Invalid password');
}
// Genereate the JWT
const token = jwt.sign({ userId: user.id }, process.env.APP_SECRET);
// Set the cookie with the token
ctx.response.cookie('token', token, {
httpOnly: true,
// secure: ...,
// sameSite: ...,
maxAge: 1000 * 60 * 60 * 24 * 365
});
return user;
}
When the code is like this, I get the following warning:
A cookie associated with a cross-site resource at http://timetable-yoga-pd.herokuapp.com/ was set without the SameSite attribute. It has been blocked, as Chrome now only delivers cookies with cross-site requests if they are set with SameSite=None and Secure. You can review cookies in developer tools under Application>Storage>Cookies and see more details at https://www.chromestatus.com/feature/5088147346030592 and https://www.chromestatus.com/feature/5633521622188032.
Backstory: the frontend part is a React app, that is hosted on timetable-react-pd.herokuapp.com. The backend part is a node app, hosted on timetable-yoga-pd.herokuapp.com.
Now, when I set the secure to true, as asked in the warning, the cookie header is not set. I have found on the internet, that this is normal.
When I set sameSite to false, it acts as if it were not there (expected behaviour). If sameSite is set to "none" or "None", the warning disappears, but a new error emerges, saying that GraphQL does not accept the value "none".
I implemented JWT token in node js.I am able to generate jwt token.Now I want to check when it will expire or invalid .
I check the documentation it says after 120ms it will expire .but I my token is not expire .it always decode the token why ?
I generate the token like this
'
app.get("/saveData", async (req, res) => {
try {
const token = await userService.create({
userId: "abcp",
password: "hello",
appsAccess: ["yes", "test"]
});
res.send(token);
} catch (error) {
console.log(error);
}
});
and verify the token like this
app.get("/verify-token", async (req, res) => {
let tokenStatus = await userService.verifyAccessToken(
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjp7InVzZXJJZCI6ImFiY3AiLCJhcHBzQWNjZXNzIjpbInllcyIsInRlc3QiXSwiX2lkIjoiNWQ3Yzk4MTYzZmQ1NGIwOGUwMjYzNjg0IiwiX192IjowfSwiaWF0IjoxNTY4NDQ2NDg2LCJpc3MiOiJqamoiLCJzdWIiOiJhYmNwIn0.1fqzYJ1p9jSIiNjbA7MwEsU4EsMmmpxF34TU1ZjonSA"
);
res.send(tokenStatus);
});
here is my code
https://codesandbox.io/s/lively-tree-hd0fo
verifyAccessToken(token) {
return jwt.verify(token, "jhjhhj");
}
I want if i generate the token it will expire after 10min or 30min..etc
You can use expiresIn option to do this. Example based on your code:
const token = jwt.sign(payload, "jhjhhj", {
algorithm: "HS256",
issuer: "jjj",
subject: `${user.userId}`,
expiresIn: "10m"
});
I am trying to generate a password token through speakeasy.js on a node.js express server, which shall be used as authentication. The password should change every hour. I'm using routers to retrieve the token and verify it.
If have set time to 30 seconds for testing purposes, but the token never changes.
Code:
var secret = speakeasy.generateSecret();
var token = speakeasy.totp({
secret: secret.base32,
encoding: 'base32',
step: : 10
});
router.get('/token/:token', function(req, res) {
console.log(token);
var usertoken = req.params.token;
if(usertoken == token){
res.send("Verified")
} else {
res.send("Not Verified")
}
res.json({ token: token, usertoken: usertoken });
});
Any suggestions?
EDIT
Added step to token.
When i request the end point e.g. http://localhost:8080/api/token/664006 the console shows the toke e.g. 290595. When i refresh the endpoint after a certain amount of time the token should change, but it doesn't. It's still 290595.
I've just checked the documentation and it looks that the parameter you're looking for it's step.
You should keep the time field to the default (Date.now() from the doc) and play with the step field.
Something like this:
var secret = speakEasy.generateSecret();
var token = speakEasy.totp({
secret : secret.base32,
encoding : 'base32',
// leave time field to default
step : 10
});
and for the verification use the method provided, instead of the ==:
router.get('/token/:token', function(req, res) {
console.log(token);
var usertoken = req.params.token;
var verified = speakeasy.totp.verify({
secret: base32secret,
encoding: 'base32',
token: userToken
});
//check if the token has changed
console.log(verified);
});
https://github.com/speakeasyjs/speakeasy
For me, when I added 'step' inside verify code, then everything went working.
var verified = speakeasy.totp.verify({
secret: secret,
encoding: 'base32',
token: token,
step: 10
})
I am trying to create a JWT for Firebase authentication using the server side javascript language: jaggeryJS.
Below I will outline
My approach to the JWT creation
The front-end response.
1 My approach to the JWT creation
HmacSHA256 function comes from Google's CryptoJS library and the Base64.encode is as outlined [here][3] but adding a second parameter to allow for websafe escaping.
<%
//create a jwt
//==============================================
//INCLUDES
include('../lib/config.js');
include('../lib/crypto/hmac-sha256.js');
include('../lib/crypto/base64.js');
//==============================================
// HEADER
var header = {
"alg": "HS256",
"typ": "JWT"
}
//==============================================
// CLAIMS
var claims = {
"v": 0,
"iat": Math.floor(new Date().getTime() / 1000),
"d": {"user":"test"},
"exp": (60 * 60 * 24 * 60),
"admin": true,
"debug": true
}
//PREPARE SIGNING
var headerBase64 = Base64.encode(stringify(header), true),
claimBase64 = Base64.encode(stringify(claims), true),
signingInput = headerBase64 + "." + claimBase64;
//CREATE SIGNATURE
var hash = CryptoJS.HmacSHA256(signingInput, FIREBASECONFIG.secret).toString(),
signature = Base64.encode(hash, true);
//CONSTRUCT JWT ('jot') TOKEN
var jwtToken = signingInput + "." + signature;
print(jwtToken);
2 The front-end response.
var dataRef = new
Firebase("https://intense-heat-2343.firebaseio.com");
var AUTH_TOKEN = "...." //what is printed above "jwtToken"
dataRef.auth(AUTH_TOKEN, function(error) { if(error) {
console.log("Login Failed!", error); } else {
console.log("Login Succeeded!"); } });
CONSOLE OUTPUT:
Login Failed! Error {code: "INVALID_TOKEN", stack: (...), message:
"INVALID_TOKEN: Could not parse auth token."}
When I pass my secret in directly I am able to authenticate successfully. Any help is appreciated. Thank you!