GET http://localhost:5000/booksIdea/show 403 (Forbidden)
i check the token in the website https://jwt.io/ i got invalid signature so i guess why the problem came from but i ignore how to fix it
i searched abt this error and this is what i found : Receiving a 403 response is the server telling you, “I’m sorry. I know who you are–I believe who you say you are–but you just don’t have permission to access this resource. Maybe if you ask the system administrator nicely, you’ll get permission. But please don’t bother me again until your predicament changes.”
API GET function on front end:
import axios from 'axios'
export const ShowBooks = () => {
let token = localStorage.getItem("usertoken")
return axios.get("http://localhost:5000/booksIdea/show", {
headers: {
Authorization: `Bearer ${token}`, //here remove + in template litereal
},
})
.then(res => {
console.log("Success")
})
.catch(error => {
console.log(error)
})
}
backend app.js
const express = require('express')
var cookieParser = require('cookie-parser')
const app = express()
var cors = require('cors')
var bodyParser = require('body-parser')
const port = 5000
const routes = require("./routes");
const con = require('./db')
var cors = require('cors')
app.use(cors())
// database connect
con.connect(function(err) {
if (err) throw err;
console.log("Connected!");
});
//cookie
app.use(cookieParser())
//routes
// support parsing of application/json type post data
app.use(bodyParser.json());
//support parsing of application/x-www-form-urlencoded post data
app.use(bodyParser.urlencoded({ extended: true }));
app.use("/", routes);
app.listen(port, () => console.log(`Example app listening on port ${port}!`))
here is routes
var express = require('express')
var router = express.Router()
var Controller = require('./controller')
var authController = require('./authController')
var BooksIdeaController = require('./BooksIdeaController')
router.post('/register',Controller.register);
router.post('/login',authController.login);
router.post('/booksIdea/:id',authController.verify,BooksIdeaController.addComment)
router.post('/booksIdea/addbook',authController.verify,BooksIdeaController.addBookIdea)
router.get('/booksIdea/show',authController.verify,BooksIdeaController.showBookIdea)
router.put('/booksIdea/edit/:id',authController.verify,BooksIdeaController.UpdateBookIdea)
router.delete('/booksIdea/delete/:id',authController.verify,BooksIdeaController.DeleteBookIdea)
module.exports = router;
authController
const con = require('./db');
var bcrypt = require('bcrypt');
let jwt = require('jsonwebtoken');
const express = require('express')
var cookieParser = require('cookie-parser')
const app = express()
module.exports.login=function(req,res){
var username=req.body.name;
var password=req.body.password;
con.query('SELECT * FROM users WHERE username = ?',[username], function (error, results, fields) {
if (error) {
res.json({
status:false,
message:'there are some error with query'
})
}else{
if(results.length >0){
bcrypt.compare(password, results[0].password, function (err, result) {
if (result == true) {
jwt.sign({user:results},'configSecret',(err,token)=>{
res.json({
token:token
})
});
// res.json({
// status:true,
// message:'successfully authenticated'
// })
} else {
res.json({
status:false,
message:"username and password does not match"
});
}
});
}
else{
res.json({
status:false,
message:"username does not exits"
});
}
}
});
}
module.exports.home=function(req,res){
res.send('hello');
}
//////
// if(password==results[0].password){
// }else{
//
// }
module.exports.verify = function verifyToken(req, res, next) {
// Get auth header value
const bearerHeader = req.headers['authorization'];
// Check if bearer is undefined
if(typeof bearerHeader !== 'undefined') {
// Split at the space
const bearer = bearerHeader.split(' ');
// Get token from array
const bearerToken = bearer[1];
// Set the token
req.token = bearerToken;
// Next middleware
next();
} else {
// Forbidden
res.sendStatus(403);
}
}
How can I fix this error? thank you in advance for your help
Check your localstorage localStorage.getItem("usertoken")
Your token can be:
missing or undefined
incorrect token - probably a typo
Related
I tried to make simple application with login and middleware.
const express = require('express');
const cookieParser = require('cookie-parser');
const logger = require('morgan');
const cors = require('./services/CORS.service');
const authorization = require('./middleware/auth');
const loginRouter = require('./login/login.routes');
const usersRouter = require('./users/users.routes');
const app = express();
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(cors);
app.use('/login', loginRouter);
app.use('/users', authorization, usersRouter);
const PORT = 5000;
app.listen(PORT, () => {
console.log(`Node app is running in: http://localhost:${PORT} ..`);
});
module.exports = app;
like you can see, I have login router and users with middleware router.
This is the loginRouter:
const express = require('express');
const router = express.Router();
const _ = require('lodash');
const cryptoService = require('../services/crypto/service');
router.post('/login', login);
async function login(req, res, next) {
try {
const { account, session } = await controller.login(req.body);
if (!req.body.username || !req.body.password) {
throw { message: 'Missing BasicAuth user and password', status: 400 };
}
const encryptedPassword = cryptoService.encrypt(password);
const toEncrypt = JSON.stringify({username: username, password: encryptedPassword, timestamp: new Date()});
const session = cryptoService.encrypt(toEncrypt);
res.status(200).send({ session });
}
catch (err) {
const errMessage = _.get(err, 'message', 'error occurred');
const errCode = _.get(err, 'status', 500);
res.status(errCode).json({ message: 'error occurred', error: errMessage });
}
}
module.exports = router;
and this is the middleware:
const _ = require('lodash');
const cryptoService = require('../services/crypto/service');
const moment = require('moment');
const SESSION_TOKEN_EXPIRATION_IN_MINUTES = 50;
module.exports = async function (req, res, next) {
try {
const session = _.get(req, 'headers.session');
console.log(session);
let decryptedSession = '';
try {
decryptedSession = cryptoService.decrypt(session);
}
catch (err) {
throw { message: 'Session is not valid, please re-login', status: 401 };
}
if (!decryptedSession) {
throw { message: 'No session provided, please re-login', status: 401 };
}
const { username, password, timestamp } = JSON.parse(decryptedSession);
if (!timestamp || moment.duration(moment().diff(timestamp)).asMinutes() > SESSION_TOKEN_EXPIRATION_IN_MINUTES) {
throw { message: 'Session expired, please re-login', status: 401 };
}
res.locals = res.locals || {};
res.locals.account = account;
next();
}
catch (err) {
const errMessage = _.get(err, 'message', 'error occurred');
const errCode = _.get(err, 'status', 500);
res.status(errCode).json({ message: 'error occurred during auth validation', error: errMessage });
}
};
when the application running, I sending postman post request to login with username and password in the body.
I got a correct session.
but when I open the users page I got error:
No session provided, please re-login
because the session in the middleware is undefined.
what can I do to fix this code?
tnx
I'm new on node js, and the company that i work for needs a proof of concept about postgraphile, the situation is this:
I created a node js mini server that uses postgraphile to access the data on postgres
The mini server works fine and can return data and also can use mutations.
I used keycloak-connect to try to access keycloak to authenticate the token from the request that is sent by postman but there is a problem.
If the token is valid or not it does not matter for the mini server, the only thing that seems to matter is that is a bearer token.
I tried to use other plugins (like keycloak-nodejs-connect, keycloak-verify, etc) but the result is the same, i also changed my code to use the examples in the documentation of those plugins but nothing.
This is my code: (keycloak-config.js file)
var session = require('express-session');
var Keycloak = require('keycloak-connect');
let _keycloak;
var keycloakConfig = {
clientId: 'type credential',
bearerOnly: true,
serverUrl: 'our company server',
realm: 'the test realm',
grantType: "client_credentials",
credentials: {
secret: 'our secret'
}
};
function initKeycloak(){
if(_keycloak){
console.warn("Trying to init Keycloak again!");
return _keycloak;
}
else{
console.log("Initializing Keycloak...");
var memoryStore = new session.MemoryStore();
_keycloak = new Keycloak({store: memoryStore}, keycloakConfig);
return _keycloak;
}
}
function getKeycloak(){
if(!_keycloak){
console.error('Keycloak has not been initialized. Please called init first');
}
return _keycloak;
}
module.exports = {
initKeycloak,
getKeycloak
};
My Index.js file:
const express = require('express')
const bodyParser = require('body-parser')
const postgraphile = require('./postgraphile')
const app = express()
const keycloak = require('../config/keycloak-config').initKeycloak()
var router = express.Router();
app.set( 'trust proxy', true );
app.use(keycloak.middleware());
app.use(cors());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(postgraphile);
app.get('/', keycloak.checkSso(), (req, res) => {
res.send('success');
} );
var server = app.listen(8080, () => console.log(`Server running on port ${8080}`));
Also I used this code to get the token and use the keycloak-verify plugin but got nothing:
router.get('/',keycloak.protect(),function(req, res, next) {
var token=req.headers['authorization'];
console.log(token);
try {
let user = keycloak.jwt.verify(token);
console.log(user.isExpired());
} catch (error) {
console.error(error);
}
})
I know that I lack the knowledge because I am a backend (C#) developer, can somebody help me with this?, thanks in advance.
I found the answer to my problem:
const express = require("express");
const request = require("request");
var keycloakConfig = require('../AuthOnly/config/keycloak-config').keycloakConfig;
const postgraphile = require('./postgraphile');
const app = express();
const keycloakHost = keycloakConfig.serverUrl;
const realmName = keycloakConfig.realm;
// check each request for a valid bearer token
app.use((req, res, next) => {
// assumes bearer token is passed as an authorization header
if (req.headers.authorization) {
// configure the request to your keycloak server
const options = {
method: 'GET',
url: `${keycloakHost}/auth/realms/${realmName}/protocol/openid-connect/userinfo`,
headers: {
// add the token you received to the userinfo request, sent to keycloak
Authorization: req.headers.authorization,
},
};
// send a request to the userinfo endpoint on keycloak
request(options, (error, response, body) => {
if (error) throw new Error(error);
// if the request status isn't "OK", the token is invalid
if (response.statusCode !== 200) {
res.status(401).json({
error: `unauthorized`,
});
}
// the token is valid pass request onto your next function
else {
next();
}
});
} else {
// there is no token, don't process request further
res.status(401).json({
error: `unauthorized`,
});
}});
app.use(postgraphile);
app.listen(8080);
I'm working on a node.js application.
In my application the requests are going through a middleware which checks if the user is authenticated. In my middleware file though, I keep getting the "next is not defined" error back in my client. What might be the issue? I'm adding the App.js and the middleware file in here:
App.js:
const express = require('express');
const cors = require('cors');
const bodyParser = require('body-parser');
const graphqlHttp = require('express-graphql');
const { sequelize } = require('./models');
const graphqlSchema = require('./graphql/schema');
const graphqlResolver = require('./graphql/resolvers');
const auth = require('./middleware/auth');
// return instance of the app
app = express();
// setting up the cors config
app.use(cors({
origin: '*'
}));
// tell the app to parse the body of the request
app.use(bodyParser.urlencoded({extended: true}));
app.use(bodyParser.json());
// tell the app to go through the middleware before proceeding to graphql
app.use(auth);
// setting the graphql route
app.use('/graphql', graphqlHttp({
schema: graphqlSchema,
rootValue: graphqlResolver,
graphiql: true,
formatError(err) {
if (!err.originalError) {
return err;
}
const data = err.originalError.data;
const message = err.message || 'An error occurred.';
const code = err.originalError.code || 500;
return { message: message, status: code, data: data };
}
})
);
app.use((error, req, res, next) => {
const status = error.statusCode || 500;
const message = error.message;
const data = error.data;
res.status(status).json({ message: message, data: data });
});
sequelize.sync({ force: true })
.then(() => {
app.listen(8080);
})
.catch(err => {
console.log(err);
});
the auth.js file (the middleware):
const jwt = require('jsonwebtoken');
module.exports = (req, res, next) => {
const authHeader = req.get('Authorization');
if (!authHeader) {
req.isAuth = false;
return next();
}
const token = authHeader.split(' ')[1];
let decodedToken;
try {
decodedToken = jwt.verify(token, 'somesupersecretsecret');
} catch (err) {
req.isAuth = false;
return next();
}
if (!decodedToken) {
req.isAuth = false;
return next();
}
req.userId = decodedToken.userId;
req.isAuth = true;
next();
};
Working locally but when running prod build, I get the 401 error. Not sure what I am missing. I am having {message: "Invalid Token"} whenever I tried to make a call to any api within the app.
Server.js
require('rootpath')();
const express = require('express');
const app = express();
const cors = require('cors');
const bodyParser = require('body-parser');
const jwt = require('./_helpers/Jwt');
const errorHandler = require('_helpers/Error-handler');
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use(cors());
// use JWT auth to secure the api
app.use(jwt());
// api routes
app.use('/users', require('./users'));
// global error handler
app.use(errorHandler);
// start server
const port = process.env.NODE_ENV === 'production' ? (process.env.PORT || 80) : 4000;
if (process.env.NODE_ENV === 'production') {
app.use(express.static('../portal/dist'));
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname, 'portal', 'dist', 'index.html'))
})
}
const server = app.listen(port, function () {
console.log('Server listening on port ' + port);
});
JWT.js
const expressJwt = require('express-jwt');
const config = require('../config.json');
const userService = require('../users/user.service');
module.exports = jwt;
function jwt() {
const secret = app.set('JWT_TOKEN', (process.env.JWT_TOKEN)) ;
return expressJwt({ secret }).unless({
path: [
// public routes that don't require authentication
'/users/authenticate',
'/users/register'
]
});
}
async function isRevoked(req, payload, done) {
const user = await userService.getById(payload.sub);
// revoke token if user no longer exists
if (!user) {
return done(null, true);
}
done();
};
Error handler.js
module.exports = errorHandler;
function errorHandler(err, req, res, next) {
if (typeof (err) === 'string') {
// custom application error
return res.status(400).json({ message: err });
}
if (err.name === 'ValidationError') {
// mongoose validation error
return res.status(400).json({ message: err.message });
}
if (err.name === 'UnauthorizedError') {
// jwt authentication error
return res.status(401).json({ message: 'Invalid Token' });
}
// default to 500 server error
return res.status(500).json({ message: err.message });
}
config.js
{
"secret": "Gu_*s+dF]x$E~n2B:#FwS.&Y;#M:sLMQ"
}
Added the interceptor into the app module. Not sure if I am missing something.
You need to provide isRevoked to the jwt instance
return expressJwt({ secret, isRevoked })
I have making an API using express and node.
Here is my app.js
const express = require('express');
const bodyParser = require('body-parser');
const dotenv = require('dotenv');
// setup dotenv to read environment variables
dotenv.config()
// Load Environment Varibles
const env = require('./utils/env');
// INIT MONGODB CONNECTION
require('./mongoose');
// create a new express application
const app = express();
// setup bodyparser middleware to read request body in requests
// we're only reading JSON inputs
app.use(bodyParser.json());
// Listen to API routes
const apiRoutes = require('./routes')
app.use('/api', apiRoutes);
// Start listening to requests
app.listen(env.PORT, () => {
console.log(`Server started on PORT ${env.PORT}`);
});
And here is the API routes that are being imported
const express = require('express');
const apiController = require('./apiController');
const apiValidator = require('./apiValidator');
const router = express.Router();
router.post('/login', apiValidator.loginUserValidator, apiController.loginUserController);
router.get('/rand', (req, res) => {
res.send('Some randon text');
});
module.exports = router;
Here is the middleware
const {
failureResponse
} = require('./../utils/response');
const errorcodes = require('./../utils/errorcodes');
const loginUserValidator = (req, res, next) => {
const user = req.body;
if (!user.username) {
return res.status(400).json(failureResponse(errorcodes.ERROR_INVALID_BODY_PARAMETER, "Invalid username"));
}
if (!user.password) {
return res.status(400).json(failureResponse(errorcodes.ERROR_INVALID_BODY_PARAMETER, "Invalid password"));
}
if (user.authTokens) {
delete user.authTokens;
}
next();
};
module.exports = {
loginUserValidator
};
Here is the controller
const User = require('./../models/user');
const {
successResponse,
failureResponse
} = require('./../utils/response');
const errorcodes = require('./../utils/errorcodes');
const loginUserController = async (req, res) => {
try {
const user = req.body;
// find if the user already exists
const existingUser = await User.findOne({
username: user.username
});
if (existingUser) {
// user exists. generate token and login user
console.log('Existing user login');
const token = existingUser.generateAuthToken();
return res.status(200).json(successResponse(token));
} else {
console.log('New user login');
const savedUser = await new User(user).save();
const token = savedUser.generateAuthToken();
return res.status(200).json(successResponse(token));
}
} catch (e) {
console.log(e);
return res.status(400).json(failureResponse(errorcodes.ERROR_SERVER_ERROR, "Unable to login user"));
}
};
module.exports = {
loginUserController
};
Here the issue is when I try to hit the login route from Postman, I am getting an error which says Could not get any response.
But when I hit the rand route, the output is correct.
So the issue isn't the arrangement of the code.
Why am I not able to use the login route here?