Stop users from accessing guest pages after login in Laravel 7 - laravel-7

Is there any way to stop the users from accessing guest pages after they've logged in? I tried using the guest middleware bt nothing happens. I have two sets of guards: RESTAURANT and CUSTOMERS. Once the customer has logged in I don't want them to access the guest pages before log out.
Route::group(['middleware' => 'guest'], function () {
Route::get('/home', 'HomeController#index')
->name('home'); // This is a guest page
});
My customer pages are protected with a customer guard as well.
Route::name('customer.')->middleware(['auth:customer', 'verified'])
->group(function () {
Route::get('/logout', 'Auth\CustomerLoginController#logout')->name('logout');
});
First, I logged in with the customer guard. After then when I type '/home', the home page is loading. I want to stop logged in users from accessing the guest pages.

Create a middleware and perform following code in it.
if (Auth::user()){
// if user HAS authenticated already,
// redirect him to somewhere or die(),
// or any other appropriate action
}
Apply middleware on route
Route::group(['middleware' => ['guest','middlewareName']], function () {
Route::get('/home', 'HomeController#index')
->name('home'); // This is a guest page
});
It will work

Why not just use the Auth::user() check on a Guest page:
if (Auth::user()){
// if user HAS authenticated already,
// redirect him to somewhere or die(),
// or any other appropriate action
}

Related

Why three dashboards are not working properly when all are open on localhost:3000 in different tabs in Chrome using nodejs?

So my project has 3 dashboards for client, admin and employee. All the three have different functionalities and options. (a little bit change)
All 3 login with same login page that is : localhost:3000/login
and all the 3 dashboards are dependent on each other. Suppose client add some tasks in his dashboard then admin approves it via his respective dashboard and then the employee updates the task status via his dashboard that is also being updated on the other 2 dashboards.
So to check all the functionalities parallely, I logged in all on 3 separate localhost:3000/login tabs in same Google Chrome for testing purpose instead of logging in again and again serial wise and checking if the data is being updated.
But by doing with separate dashboards, the data some-while gets mismatched and not updated.
So I am thinking that after deploying the code will that be a problem when all the 3 users will login simultaneously and start making changes? Will it work fine after deployment or is it just on localhost.
Here is the login code in nodejs I am using for all users:
router.route('/login')
.get(function(req, res, next) {
res.render('login', { title: 'Login your account'});
})
.post(passport.authenticate('local', {
failureRedirect: '/login'
}), function (req, res) {
if(req.user.tag == 'Emp')
res.redirect('/profileEmp');
else if(req.user.tag == 'Admin')
res.redirect('/profileAdmin');
else {
res.redirect('/profile');
}
// console.log(req.user.email);
});
P.S. All dashboards work fine when I make changes with one dashboard login only and then again I logout and login to another dashboard say Employee one; it works fine.
I guess you have three different login credentials, one for each role.
The way logged in session management usually works is this: upon accepting a set of credentials the passport module feeds a session cookie to your browser.
If you log in as user and then, from the same browser as admin, the admin session cookie overwrites the user session cookie. That browser (all its tabs) is now logged in as admin.
There's a Chromium web extension called EditThisCookie. It lets you see, easily, the cookies for each page. Use it to troubleshoot this kind of thing.
I use three separate browsers, Chrome, Firefox, and Edge or Safari, to debug this kind of thing. I can keep separate sessions separate by running them in separate browsers.

In node.js with express, is there a way of changing the url of a link on the fly?

I have a link on a page:
Back
which of course takes the user to '/application-reference'. However, if the session has timed out, I want the user to taken to '/session-ended' instead. Session timed out is detected by the absence of request.session.
I've tried changing the href to send the user back to the same page (i.e. the link is in 'security-code' and takes the user to 'security-code') with the idea that the handling code can look for request.session and decide which page to redirect to, only I can find no way for the code to detect that the page has been called by itself via the back button.
I think the answer is to put something in my express module so that the router.get call that redirects to '/application-reference' will under the right circumstances redirect to '/session-ended'. But I have no idea how to go about this.
I suppose the ideal would be for the '/session-ended' screen to be invoked any time the user clicks on any screen once the session has timed out.
Any suggestions?
Inside your /application-reference-handler you could check if the session on the req-object is still valid. If not redirect the request to /session-ended:
app.get('/application-reference', (req, res) => {
if(!req.session) { // or a more detailed check for the session's validity
return res.redirect("/session-ended");
}
// rest of the handler-code ...
});
An better way to do this is to define a separate middleware to check the user's session - this allows you to reuse this middleware and not having to duplicate the check in your handlers:
function validateSession(req,res,next) {
if(!req.session) { // or a more detailed check for the session's validity
return res.redirect("/session-ended");
}
// all is good, go to the next middleware
next();
});
app.get('/application-reference', validateSession, (req, res) => { ... });

Preventing man-in-the-middle attacks with user authentication (Node/Vue/Passport)

I currently have a webapp I'm writing in Node/Vuejs with Passport handling authentication, and I've run into a problem. I was thinking about how I have authentication currently set up and I realized I had a glaring security hole.
In short, I have my Vuex store hitting a local API endpoint /api/me. That endpoint does a simple return of req.user. For the sake of brevity, a typical response looks like this:
{
username: 'Bob',
roles: [] // normal user has no roles,
email: 'someguy#bob.com'
}
My admin route /admin has a beforeEnter check, as shown below, that incorporates this check using the Vuex store, so I can have a cached version of user data accessible on the frontend.
{
path: '/admin',
name: '/admin',
component: Admin,
beforeEnter: (to, from, next) => {
store.dispatch('getMe').then(() => {
if (store.getters.user.roles && store.getters.user.roles.includes('administrator')) {
next();
return;
}
next({ path: '/' });
});
}
}
Here's the thing though - I realized that someone could easily game the system. In fact, I tried it myself with a test, non-Adminstrator account, and I was able to get in by returning the following from a local server set up for this purpose in Postman:
{
username: 'Super Admin Joe',
roles: ['administrator'] // normal user has no roles,
email: 'admin#bob.com'
}
And viola! The user now has full access to admin pages.
My question is, how could I prevent against this?
I need to check that the user is authenticated on every page, but a potential attacker could quite easily proxy any request (in this case it's /api/me) to make themselves any user they want. They can login normally with their own account, open the Network tab and copy the response payload, then change the user data as they wish. There needs to be some sort of encryption between the frontend and backend when checking a users' logged-in status, I believe.
I tried thinking about how I could prevent this from happening, but anything on my end (server-side, at least) seems useless as any request could easily be redirected to an attacker's local machine.
Any advice on how to "sign" my requests to make sure they aren't being proxied? Thanks in advance!
You shouldn’t have to be signing the response body of an api request. The typical way to do authentication is to establish a signed session cookie that acts either as an identifier to session information in an external database, or contains session information itself. This cookie should be in the header of your response and passport should give you a way to administer this cookie without you even realizing it.
This way the user can’t tamper with the information sent from the server in a way that’s easy to detect, and since it’s a cookie it will automatically be sent with each request by your browser (although if you’re using some AJAX library you may have to explicitly specify you’d like to send the cookie). What MadEard was referring to in the comment is where the cookie information is able to be accessed using passprt which is the ‘user’ property in the ‘req’ object.
After reading your github files:
server.get("/admin", function(req, res){
if(req.user && req.user.roles.includes("administrator")){
//user is an administrator, render the admin panel view
}else{
//is not an admin, redirect or send error message
}
});
In every Express route, after authentication with Passport, you have the req.user object.
It is established by checking the request cookie connect.sid, and checking which session this cookie belongs to on the server.
As such, you can trust that in any Express route, the object req.user contains the information relevant to that cookie and you can act upon it.
A little note: doing server-side validation should become a reflex for you over time.
The client is meant to display information. If, at any point, you are making the client take any decision that could be a security liability, take a step back and think it again.

Angular 2 (4/5) check if user authenticated, best practices

I am new to Angular and implementing authentication for users.
Most of suggestions on the web propose to save session/username in local storage and when user is back to the app, check local storage in order to display proper navigation (in my navbar I have different nav buttons for private and public views).
However, I found this solution having some drawbacks. For example, if session on server expired, or local storage was manually added, then when app will be initialising, it will show wrong buttons in navbar.
After that I came to solution - to use service before showing navbar buttons, to send request to server to verify if user from local storage with his session is currently active. And only after that I will display nav buttons.
Here comes a question: is it the most efficient way to proof check if user from local storage is logged in and session is active?
There is another way, which I was thinking, but didn't find solution.
Since my angular webapp and nodejs server are located in two different places, is it possible for the webapp to check authentication status (make a request from webapp server to my nodejs server) when index.html is requested and respond with pre-rendered navbar and user status (logged in or not)?
Thanks.
P.S. I am using PassportJS and Express on server side.
The best practise is to use AuthGuard and implement CanActivate to check whether user can view a particular part of the application. Also an authentication service is used normally to let the user login to system and gain an access token.
This access token is then used as Authorisation-Header on each request to server (this is where they will be in sync).
You will need to check for JWT/or any other type token on load which contains user information plus session time out.
If the token is invalid you simply redirect the user to login, otherwise it will allow user to go where they wanted to.
A practical example can be found here.
To have navbar showing different elements for authenticated and non-authenticated users, one of possible solutions will be
To use some "/auth-check" request in authentication.service.ts, which will have trigger every time an event of the result of checking authorisation of current user
...
interface ShareObj { [id: string]: any; }
...
currentUserId: ShareObj = {};
currentUserUsername: ShareObj = {};
public authenticatedBehavior = new ReplaySubject(1);
authCheck(): any {
return this.http.get('/api/auth-check')
.map((resp: any) => {
if (resp.authanticated) {
this.currentUserId['global'] = resp.user.id;
this.currentUserUsername['global'] = resp.user.username;
this.authenticatedBehavior.next(true);
} else {
this.authenticatedBehavior.next(false);
this.currentUserId['global'] = null;
this.currentUserUsername['global'] = null;
}
return resp;
})
.catch(e => {
this.authenticatedBehavior.next(false);
this.currentUserId['global'] = null;
this.currentUserUsername['global'] = null;
});
}
So, in navbar.component.ts there should be a listener for this event:
ngOnInit() {
this.authService.authenticatedBehavior
.subscribe(
data => {
// do change of UI of navbar depending if user logged in or not
}
);
}
To have error-iterceptor.ts file, where you should "catch" all failed requests and check them for Unauthorised response (401). If you catch such response, do authCheck() in authentication.service.ts to make sure that session of current user expired and notify all components which listen for authenticatedBehavior

Nodejs User security

I want to check if the user accessing the web page is part of a domain.
How can I do this with nodesjs?
Pseudo code like this:
Server.on(request){
if(getDomainOf(user) === 'thisdomain.local') // User is a member of the domain
// Handle request
else
// show error (Access denied)
}

Resources