I writing code for authorization. After click on the button for login I create a new header with
res.header('Authorization', token)
admin_login router:
router.post('/admin_login', async (req, res) => {
const adminDB = data.admins;
const admin = adminDB.find(admin => req.body.email === admin.email)
if (!admin) return res.status(400).send('Email in not found!')
if (admin.password !== req.body.password) return res.status(400).send('Invalid password')
const token = jwt.sign({ admin }, 'the_secret_key')
res.header('Authorization', token)
res.redirect('/admin')
})
I wont to recieve Authorization header after login in admin router, but I wont recieve it. I see Authorization header in
Code for verification:
const jwt = require('jsonwebtoken')
module.exports = (req, res, next) => {
const token = req.header('Authorization')
console.log(token)
if (!token) return res.status(401).send('Access Denied')
try {
const verified = jwt.verify(token, 'the_secret_key')
req.admin = verified
next()
} catch (e) {
res.status(400).send('Invalid token')
}
}
first img: headers in admin router
second img: headers in admin_login router after click on the button for login
Please, help me
As far as I can tell from the documentation, there is no header method on the Express Request object or the Node.js IncomingMessage it extends.
The Express documentation says that to retrieve a header, you use get:
req.get(field)
Returns the specified HTTP request header field (case-insensitive match).
So:
const token = req.get("Authorization");
Or you could use the headers object from IncomingMessage:
const token = req.headers["authorization"];
(Note the lower case, Node.js makes the header names lower case when building the object.)
You should use the req.get(headerName) method
Related
Here is the situation:
I have a database which contains a user and password registered.
My assignment, for now, is to create a login form, and login with a registered uname and pw.
Uname and pw are registered in the server/database already.
ps: I did not create the server nor database.
Node server code
import express from 'express';
import cors from 'cors';
import http from 'http';
import { Sequelize } from 'sequelize';
import { Data } from './database';
import { router } from './routes/Router';
import { initialData } from './database/someData';
const closeServer = async (
server: http.Server,
sequelize: Sequelize,
signal?: string
) => {
server.close();
await sequelize.close();
process.exit();
};
const runServer = async (): Promise<void> => {
const PORT = process.env.PORT || 8082;
const app = express();
const sequelize = Data.init();
app.use(
cors({
credentials: true,
origin: 'http://localhost:3000',
})
);
app.use('/api', router);
const server = app.listen(PORT, () => {
console.log(`Starting server at ${PORT}`);
});
try {
await sequelize.authenticate();
await sequelize.sync({
force: process.env.SERVER === 'reset',
});
if (process.env.SERVER === 'reset') await initialData();
} catch (e) {
closeServer(server, sequelize);
throw e;
}
};
runServer()
.then(() => {
console.log('Run successfully');
})
.catch((ex: Error) => {
console.log('Unable to run:', ex);
});
I need help on what is that I have to do.
When I input username and pw, on the form, what are the methods to use for sending the info?
And then, when the info reaches the server, i think the username and pw need to be validated with jwt, and then check if the user and pw exists. how do i do that?
What i have understood so far is that i gotta use axios to send info to server, but thats it.
Do i need to use jwt for the login?
What is the normal flow for this kind of mechanism?
I am using react as a framework.
So there are quite few steps here.
First you have to create endpoint on your backend server for issuing jwt tokens. Jwt tokens can be used as a pass for user to login. So in your router you would add something like this:
router.post('/login', (req, res)=> {
const username = req.body.username
const password = req.body.password
// Then you make db call to verify username and password are correct.
if Credentials are valid, you would issue jwt token
jwt.sign({
// here you can save extra information of user. Also remember this information must be public since anyone can see it. Do not put user password here
email: 'email',
userId: 'id',
}, "secret")
})
After this, you need some kind of middleware on backend, so that on each user request, you check and verify this jwt token which is sent from react application. For example you could write isAuth middleware:
const jwt =require("jsonwebtoken");
export const isAuth= (req, res, next) => {
try {
// here we attach request in auth header, with Bearer "jwt token" format. So we extract jwt token and verify it
const authHeader = req.get("Authorization");
if (!authHeader) {
return res.status(401).json({ message: "no token" });
}
const token = authHeader.split(" ")[1];
let decodedToken;
decodedToken = jwt.verify(token, "secret");
if (!decodedToken) {
return res.status(401).json({ message: "Wrong token" });
}
req.userId = decodedToken.userId;
next();
} catch (err) {
console.error(err);
return res.status(401).json({ message: err });
}
};
Now you would be able to have backend endpoints like this:
// This is how you would require login on some routes
router.post("/getMyPrivateInfo", isAuth, QueryPrivatInfo)
Now on React side, you would make request for login like this:
axios.post("/login", {
username: '1',
password: "2"
})
This would return jwt token, now you would save this token in local storage.
After its saved in local storage and you make request with axios for private info you would do following
axios.post("/getMyPrivateInfo", {any request body info neeeded}, {
headers: {
Authorization: "Bearer jwtTokenFromLocalStorage"
}
})
This is how whole flow will work, hope it makes sense
I have a question on how to search for my JWT token inside of a user's browser cookies.
Below I have some code that searches the user's browser for cookies in the response header, but I am not sure how to make the code more specific and search for the JWT token within the cookie and verify that it is an actual JWT token that was a assigned to that user.
const jwt = require('jsonwebtoken');
const router = require('express')();
const cookieParser = require('cookie-parser');
router.use(cookieParser());
module.exports = function(req,res,next){
const token = req.header('Cookie');
if (!token) {
return res.status(403).send('Access Denied');
}
try{
const verified = req.header('Cookie');
req.user = verified;
// const verified = jwt.verify(token, process.env.TOKEN_SECRET);
// req.user = verified;
next();
} catch (err) {
res.clearHeader;
res.status(403).send('Invalid Token');
}
};
I hope I didn't misunderstand your question and waste a bunch time.
Short Answer: How to retrieve information
Use req.body or req.headers. If something will contain the token or authentication details, then it's one of these two.
Full Auth Walkthrough:
To get the JSON Web Tokens you first have to generate them. Wouldn't recommend implementing your own token authentication though. I'll show how to create a whole authentication system here step by step.
For simplicity, let's say we have an exported route in a file auth.js, this route will be a sub-route domain.com/auth, an array of all active refreshTokens and the jwt:
const express = require("express")
const jwt = require("jsonwebtoken")
let route = (exports.route = express())
let refreshTokens = []
What we will do is generate a long-lasting refresh token, which users will be able to use to generate a smaller 15-minute access token. Afterwards, you generate a new access token with the refresh token and so on. But to get the refresh token you need to login or register. Users can also logout killing the refresh token.
route.post("/token", async (req, res) => {
// Input: Refresh Token
// Output: Access Token Generation
})
route.post("/login", async (req, res) => {
// Input: User, Password
// Output: Refresh Token
})
route.delete("/logout", async (req, res) => {
// Input: Token to Remove
})
Let's start with the end. You have a refresh token, you won't to destroy it. Simply filter the array against this token and submit a status. The token becomes unusable after it's cleared from the array, that's the goal here.
route.delete("/logout", async (req, res) => {
refreshTokens = refreshTokens.filter((token) => token != req.body.token)
res.sendStatus(204)
})
With me so far? Now let's jump back to the start. If you log in with an email and password, if they're wrong respond with an error message, if they're correct receive the tokens.
route.post("/login", async (req, res) => {
const username = req.body.username
const password = req.body.password
// This is just a quick demonstration,
// you would have to use the bcrypt hash
// or other hash/salt methods. DO NOT
// STORE passwords plaintext
// Not existent user = Unauthorized
if (username != 'admin') return res.sendStatus(401)
// Wrong Password = Forbidden
if (password != 'abc123') return res.sendStatus(403)
const user = {
id: 0,
username: username,
password: password
}
const accessToken = generateAccessToken(user)
const refreshToken = generateRefreshToken(user)
let result = {
success: true,
accessToken: accessToken,
refreshToken: refreshToken,
}
res.send(result)
})
Now how do we sign the JSON web tokens? Let's take a look at the two methods used here:
function generateAccessToken(content) {
return jwt.sign(content, process.env.ACCESS_TOKEN_SECRET, {
expiresIn: "15m",
})
}
function generateRefreshToken(content) {
const token = jwt.sign(content, process.env.REFRESH_TOKEN_SECRET)
refreshTokens.push(token)
return token
}
Both use some sort of environment tokens, but why? That's the token you will have to generate once for the back end. It will be used as a public key. We simply generate the access tokens for 15 minutes and push the refresh tokens to the array.
route.post("/token", async (req, res) => {
const refreshToken = req.body.token
if (refreshToken == null) return res.sendStatus(401)
if (!refreshTokens.includes(refreshToken)) return res.sendStatus(403)
jwt.verify(refreshToken, process.env.REFRESH_TOKEN_SECRET, (err, user) => {
if (err) return res.sendStatus(403)
res.json({ accessToken:
generateAccessToken({
id: 0,
username: user.name,
password: user.password
})
})
})
})
We verify the refresh token, if it exists and it is valid, return a new access token for 15 minutes. That's it for the token part, you can login (create refresh token), retrieve an access token and logout (kill refresh token)
How to Use: Authenticate and Authorize
Admin pages should return 403 while the forum board should be different whether you're logging as a guest or an actual user. The first one is authentication, the second authorization.
Let's create two functions for each. Express is quite handy with the next() function
exports.authenticate = function (req, res, next) {
const authHeader = req.headers["authorization"]
const token = authHeader?.split(" ")[1]
jwt.verify(token || "", process.env.ACCESS_TOKEN_SECRET, (err, user) => {
req.user = err ? {} : user
next()
});
};
exports.authorize = function (req, res, next) {
const authHeader = req.headers["authorization"]
const token = authHeader?.split(" ")[1]
if (token == null)
return res.sendStatus(401)
jwt.verify(token, process.env.ACCESS_TOKEN_SECRET, (err, user) => {
if (err) return res.sendStatus(403)
req.user = user
next()
})
}
Now you're done with the whole authentication system (aside some cleanup's) and probably the registration system. Let's make use of it.
Client side you can create a REST api like so:
POST http://localhost:8081/auth/login
Content-Type: application/json
{
"username": "admin",
"password": "abc123"
}
# Returns refresh and access token.
###
DELETE http://localhost:8081/auth/logout
Content-Type: application/json
{
"token": "REFRESH_TOKEN"
}
# Logs out a user.
###
POST http://localhost:8081/auth/token
Content-Type: application/json
{
"token": "REFRESH_TOKEN"
}
#
# This is how you can provide the access token
# when making a request to say a forum api
#
GET http://localhost:8081/forum/api/board/0
Authorization: Bearer ACCESS_TOKEN
Usage:
route.get("forum/board/:id", authenticate, async (req, res) => {
res.send(req.user)
})
Expected Output when going to localhost:8081/forum/board/7 authenticated:
{id:0,username:"admin",password:"abc123"}
Otherwise:
{}
Nevertheless, do not try implementing your own authentication. Really, you shouldn't.
Source
https://www.youtube.com/watch?v=mbsmsi7l3r4
So I am writing tests using Mocha, Supertest and Chai. All my API's require an Authorization header which can be gotten from req.headers["authorization"]. This is the current setup of what my test looks like.
...
describe("Upload media files", () => {
it("uploads a file successfully", async () => {
const imagePath = path.join(__dirname, "../../fixtures/profile.jpeg");
const res = await app.post("/api/v1/account/upload") //app is global
.set("Authorization", "ey83hfjksksls...") //right here
.set("content-type", "multipart/form-data")
.attach("media", imagePath);
expect(res.status).to.eql(200);
expect(res.body.data).not.to.be.null;
expect(res.body.data).to.match(/https:/);
});
});
My tests always fail because a 401 is always returned for some reason that I do not know. Here's the function that handle's the decoding of the JWT
async function decodeToken() {
const sessionUser = req.session.userId;
const token = req.headers["authorization"] // token value is present here.
if (!token && !sessionUser) {
return res.status(401).json({
error: "Access denied, no valid credentials.",
});
}
if (token) {
const secret = sails.config.custom.jwtSecret || process.env.JWT_SECRET;
const decoded = jwt.verify(token, secret);
req.me = decoded;
return proceed();
}
const user = await User.findOne({
id: sessionUser,
});
req.me = user;
return proceed();
}
From the function above, when I do a console.log of the token variable, I do get a long string returned which shows that the token is being generated and passed into the .set('Authorization', 'eyeur9339..') header, but the test still fails. I don't know what to do anymore. Any help is appreciated, thank you.
if you use jwt for authorization, use Bearer before token so you should write Bearer, like this :
Bearer 5d5bd7f7e35a86541686f96c9cdd72ed67f5ba223811634e0319af224164823edc2d0090d1f6c2c3b1dec842ea783c71feb443ac2d26e
and for get token from header do like this :
const token = req.headers.authorization.split(' ')[1]
const decodedToken = jwt.verify(token, secret)
I have a node js app. I'm trying to do authorization usin JWT. When my code is as i wrote below, im trying to login with a user in my database but it firstly reach the middleware and it says 'Auth Failed'. But if I delete middleware and login with a user who is in my database it returns a token to me. Then i add the middleware again and i use that token for another user, this time it works and it accepts that token for another user too! But I dont want this. I want that when I login with a user in my database, it should return a unique token for the user and then i should reach the middleware. Here is my codes:
Here is my middleware:
const jwt = require('jsonwebtoken');
module.exports = (req, res, next) => {
try {
const token = req.headers.authorization.split(" ")[1];
const decodedToken = jwt.verify(token, 'secret_key');
req.userData = decodedToken;
next();
}catch(error) {
return res.status(401).send({
message: 'Auth failed'
});
}
And here is my login code (im creating the token here) if password is true:
const token = jwt.sign({
email:user.email,
password: user.password
},
'secret_key',
{
expiresIn :"2h"
}
)
return res.status(200).send({ message: 'success', token: token});
And in app.js:
const checkAuth = require('../middleware/checkauth');
router.get('/api/company',checkAuth,companyController.list);
How can I do this authorization security using JWT as I want? Any Suggestion ?
I am trying to build an authentication system so, i used node , mysql,express for that so now i am simply saving and checking user exist in database can access but now i added JWT to it, so now i want this JWT token to store in localstorage or in cookies so, can someone guide me how can i do so
this is my authentication controller.js
var Cryptr = require('cryptr');
cryptr = new Cryptr('myTotalySecretKey');
var express = require('express');
const ap = express();
var jwt = require('jsonwebtoken');
var connection = require('./../config');
module.exports.authenticate = function (req, res) {
var email = req.body.email;
var password = req.body.password;
connection.query('SELECT * FROM users WHERE email = ?', [email], function (error, results, fields) {
if (error) {
res.json({
status: false,
message: 'there are some error with query'
});
} else {
if (results.length > 0) {
decryptedString = cryptr.decrypt(results[0].password);
if (password == decryptedString) {
jwt.sign({ email, password },
'secretkey',
{ expiresIn: '10days' },
(err, token) => {
console.log('token:' + token);
module.exports = token;
console.log(token);
res.redirect('/home.html');
}
);
} else {
res.redirect('/login.html');
console.log("Wrong Input");
}
}
else {
res.redirect('/login.html');
}
}
});
};
now i want to pass the token value to the local-storage or cookies so that i can restrict someone from acessing a page, i am reallly new to node js so any help would be appriciated
First I should notify you that do not put any secret things like password in jwt payload because the values of the payload could be accessed easily, you can try to copy paste a jwt in jwt.io site and see the payload.
set jwt in cookie like below, this will use express cookie method that does set Http Set-Cookie header:
res.cookie('jwt', generated_cookie)
.redirect('/home.html');
Also if you want to use localStorage you can set jwt in header and then in your code get the jwt from the header of login request and save it in localStorage and after that you should pass it as header in all other request, but this approach is a better solution for api calls like when you use react or vue ...
res.set({x-token: generated_token});
// In your code get
// get token from response
localStorage.setItem('token', token);
// now whenever calling api pass token as header
I show you one solution using jwt token, you choose another way:
Back-end file e.g. api.js
let jwt = require('jsonwebtoken')
let secret = 'yourSecret'; //secret key necessary to encode token
let Cryptr = require('cryptr');
let cryptr = new Cryptr('myTotalySecretKey');
module.exports = function(router,upload) {
function tokenAuth(req, res, next){
let token = req.body.token || req.body.query || req.headers['x-access-token']
if(token){
jwt.verify(token, secret, function(err,decoded){
if(err){
res.json({ authenticated: false, message:'Invalid token'})
} else {
req.decoded = decoded;
next()
}
})
} else {
res.json({success:false, message:'No token provided'});
}
}
router.post('/authenticate', function(req, res){
connection.query('SELECT * FROM users WHERE email = ?', [email], function (error, results, fields){
if(error) {
res.json({ success:false, message: err })
}
if(!results.length){
res.json({success:false, message:'User no found'})
} else if (results.length>0){
if(!req.body.password){
res.json({success:false, message:'Password was not provided'});
} else {
var validPassword = cryptr.decrypt(results[0].password);
if(validPassword === req.body.password){
res.json({success:false, message:'Incorrect password'})
} else {
var token = jwt.sign({username: results[0].username, email: results[0].email}, secret, {expiresIn: '24h'})
res.json({success:true, message:'You have logged in correctly!', token: token })
}
}
}
})
})
//If you want create a route for authenticated users for example comment posts, you can use our `tokenAuth function`
router.post('/post/comment',tokenAuth,function(req,res){
//access only for authenticated users
}
return router
}
This tokenAuth function we'll be use in paths restricted to authenticated users
server file e.g. server.js
const express = require('express');
const app = express();
const port = process.env.PORT || 80;
const http = require('http').Server(app);
const routes = require(path_to_api.js)(router);
app.use('/myApi', routes)
//***Here you should implement more details about your project such as routes, body parsers and other middlewares*****//
//Connect to your database
http.listen(port, ()=> console.log(`Server running on ${port}`))
Front-end file e.g. controller.js
function(login){
return fetch('/myApi/authenticate',{
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(login)
}).then(result=>result.json()).then(data=> window.localStorage.setItem('token', data.token))
}
//`login` argument should be an object and should be like {username: 'user username', password: 'user password'}
In order to make a user store cookies, you can use the Set-Cookie header. From MDN:
Set-Cookie: <cookie-name>=<cookie-value>
In order to pass a header using Express, you can use res.set(), e.g. res.set("Set-Cookie", "Token=" + token). I also suggest you use the HttpOnly cookie directive, since it seems from your post that you don't access this token directly via Javascript and you simply want to check it when the client requests a webpage: res.set("Set-Cookie", "Token=" + token + "; HttpOnly").
The client will send the Cookie header to you when it requests a resource. You can check this header using req.header('Cookie'), and the output will be "Token=<token>" if the user is authenticated. You can then check this token for authenticity.