authentication for specific routes in passport
Is there a way by which I can unauthenticate specific routes say if I want to unauthenticate /seller page..
Please help me out
You could potentially log users out when they navigate to that page using req.logout.
Example:
app.get('/seller', (req, res) => {
req.logout();
}, (req, res) => {
// seller page logic
});
If you want the users to stay logged in for other pages then I would recommend instead creating an authorization middleware so only specific users would see the seller page.
Brief example:
const authorize = (req, res, next) => {
const { user } = req;
if (user && user.loggedIn && user.admin) {
// Allow access
return next();
}
};
Related
I've built some conditional logic to control access to a subdomain (producer.localhost:3000)
Only users with role 'admin' should be able to access the site, everyone else (with role of 'user') should be redirected to their profile page.
This is the code inside producerController.js :
index = (req, res, next) => {
if ((req.oidc.user['https://localhost:3000.com/roles']).includes("user")){
res.redirect('http://localhost:3000/user/profile')
}
else {
res.render('producer/index')
};
};
The problem is that it redirects for ALL user roles (rather than just those with ‘user’ as a role)
Doesn't seem like an express issue to me, try something like this
const express = require('express');
const app = require('express');
//Only allows users to continue to route if admin is one of their roles
const adminRoute = (req, res, next) =>{
if(req.oidc.user['https://localhost:3000.com/roles'].includes('admin'))
next();
else
res.redirect('http://localhost:300/user/profile');
}
//Example use case
//Everything affected by this app.use() (in this case anything underneath it) will only be accessible to users with the admin role
app.use('*', adminRoute)
app.get('/protectedRoute', (req, res) =>{
res.send('Protected route')
})
//Or you can use it directly inside the route
app.get('/protectedRoute', adminRoute, (req, res) =>{
res.send('Protected route')
})
app.listen('80', () =>{
console.log('Listening on port 80')
})
This should work 100% of the time, the only logical conclusion is that your if statement isn't returning the proper value.
In which case you can try using
if(array.indexOf('admin') !== -1)
The code shouldn't conflict just put them underneath eachother
//Executes this first
app.use((req, res, next) =>{
doThing();
next();
})
//Then executes the next route/use
app.use((req, res, next) =>{
doOtherThing();
if(something == false) return res.redirect('https://test.com');
next();
})
//Lastly if next was called in every use statement before this access route
app.get('/someRoute', (req, res) =>{
res.send('Accessed some route');
}
Not sure if I understand your issue
I am building an API endpoint with Express, NodeJS, PassportJS, and TypeScript. I want to allow two types of authentication for this endpoint. SAML (for humans) and token for automation. For human authentication, I'm using the passport-saml strategy. For token auth I'm using passport-http basic authentication. So far my code looks like:
import session from "express-session";
const samlStrategy = getSamlStrategy();
const basicStrategy = getBasicStrategy();
app.use((req, res, next) =>
session({
// store sessions in db
})(req, res, next)
);
app.use(passport.initialize());
app.use(passport.session());
passport.serializeUser((user, done) => {
//...
});
passport.deserializeUser((username, done) => {
//...
});
passport.use(samlStrategy);
passport.use(basicStrategy);
const requireApiAuth: express.Handler = (req, res, next) => {
if (req.user) {
next();
} else {
res.status(401);
}
};
const tryTokenAuth: express.Handler = (req, res, next) => {
if (!req.user && req.headers.authorization && req.headers.authorization.indexOf("Basic") > -1) {
passport.authenticate("basic", { session: false })(req, res, next);
} else {
next();
}
};
//...
// SAML endpoints here
//...
app.use(
"/api",
tryServiceUserAuth,
requireApiAuth,
The basic idea is the middleware function tryTokenAuth will check to see if a user is already present on the request. If there is, then that means a human has already logged in via SAML auth. If there is no user AND if the request specifies Basic authorization then we should use the basic strategy to authenticate. At the moment, this is working. I am able to authenticate using either strategy for the /api route.
The issue is that even though I specify {session: false} for basic authentication I'm STILL getting a session cookie sent back in the response. And a session is being recorded in my database. I don't understand what I need to configure to prevent this behavior. I do NOT want a session to be created when basic auth is used.
Is there any way to accomplish this?
As it turns out specifying session: false in the call to authenticate only prevents passport from adding its session data to a request session. The reason a session is still being created is because my config says:
app.use((req, res, next) =>
session({
// store sessions in db
})(req, res, next)
);
In order to prevent this when using basic auth I had to update to:
app.use((req, res, next) => {
if (req.headers.authorization && req.headers.authorization.indexOf("Basic") > -1) {
next();
} else {
session({
// store sessions in db
})(req, res, next)
}
});
I am stucked with one problem. As you can guess from title , problem is that i am making redirect loop . Simple situation but as a beginner i couldn't solve it . I will provide my code for you to see the problem.
So this is my express routers `
const passport = require('passport');
module.exports = (app) => {
app.get('/auth/eventbrite',
passport.authenticate('eventbrite', {}));
app.get('/auth/eventbrite/callback',
passport.authenticate('eventbrite', { failureRedirect: '/' }),
(req, res) => {
if (!req.user) {
throw new Error('user null');
}
res.redirect('/dashboard');
});
app.get('/api/logout', (req, res) => {
req.session = null;
req.logout();
res.redirect('/');
});
app.get('/api/current_user', (req, res) => {
res.send(req.user);
});
app.get('/dashboard', (req, res) => {
console.log(req.user, 'user');
if (!req.user) {
res.redirect('/');
} else {
res.redirect('/dashboard');
}
});
};
You can notice that i redirect user to /dashboard both in passport authentication and for get requests . My goal is to prevent user to come to dashboard if he/she is not authenticated .
If the user is logged in and is redirected to the dashboard, the dashboard redirects him again to the dashboard. This creates an endless loop. Instead, if the user is logged in, the dashboard route should respond. Most probably you want to send him the dashboard html page.
I'm developing a RESTful API with Express.js and I'm using Passport.js for authentication purposes.
Here is an example of how I'm using passport with routes:
const beerRoutes = require('./beerRoutes') // an instance of express router
let authenticateRoute = passport.authenticate('jwt', { session: false })
router.use('/beer', authenticateRoute, beerRoutes)
Inside beerRoutes.js :
const router = require('express').Router()
router.post('/', (req, res) => {})
router.get('/', (req, res) => {})
router.patch('/', (req, res) => {})
router.delete('/', (req, res) => {})
The problem is, I want unauthenticated clients to be able to create new users (i.e. POST /beer/).
But I also want to give additional permissions to authenticated clients when they send a request to the same endpoint.
How can I achieve this without letting unauthenticated clients to access other routes inside beerRoutes (e.g. PATCH /beer/)?
This can be addressed with a custom middleware which calls the Passport.js middleware.
const authenticationWhiteList = [
'POST /beer'
]
function Authenticate (request, response, next) {
let route = `${request.method} ${request.baseUrl}`
if (_.indexOf(authenticationWhiteList, route) !== -1) {
next()
} else {
passport.authenticate('jwt', { session: false })(request, response, next)
}
}
Then change the authentication code to this one:
const beerRoutes = require('./beerRoutes') // an instance of express router
// let authenticateRoute = passport.authenticate('jwt', { session: false })
let authenticateRoute = Authenticate
router.use('/beer', authenticateRoute, beerRoutes)
I am building an app using Express/Node.js with Passport.js(passport-local) & Mongoose.
There are two kind of users:
regular users (they login using /user-login page and passport strategy 'local-user-login'; regular users are stored in "Users" MongoDB collection)
admins (they login using /admin-login page and passport strategy 'local-admin-login'; admins are stored in "Admins" MongoDB collection)
I also have 2 pages: /user_home (needs to be accessible to logged regular users only) and /admin_home (for logged admins only)
Route for /user_home:
app.get('/user_home', isLoggedIn, function(req, res) {
// render the page
});
function isLoggedIn(req, res, next) {
if (req.isAuthenticated())
return next();
res.redirect('/login');
}
If I log in as an admin and try to access /user_home, it doesn't allow me, which is fine. My question is: how can I define another "isLoggedIn" function that checks if I am logged in as an admin rather than a regular user? Ideally I would like to have a function "isLoggedInAsUser" and another one "isLoggedInAsAdmin".
So far I tried defining the /admin_home route the same way:
app.get('/admin_home', isLoggedIn, function(req, res) {
// render the page
});
But it's obvious why it doesn't work. The code doesn't know that I want it to check if it's an admin rather than a regular user.
Passport stores authenticated user in req.user. So you can write middleware functions like this:
function allowAdmins(req, res, next) {
if (req.user.role === 'Admin') return next();
res.redirect('/user-login');
}
function allowRegular(req, res, next) {
if (req.user.role === 'Regular') return next();
res.redirect('/admin-login');
}
And then in routes:
var userRouter = express.Router();
userRouter.use(isLoggedIn);
// Only authenticated users are allowed
userRouter.get('/home', isRegular, function (req, res) {});
userRouter.get('/admin', isAdmin, function (req, res) {});
app.use('/user', userRouter);
in session object store role information
in the route configuration level, write middleware like
var adminRoutes = express.routes();
adminRoutes.route('/admin/*', function (req, res,next)
{
if(req.session.role==='Admin')
return next();
else
{
res.send("Authorization Error")
}
}
app.use(adminRoutes);
same for user routes