Show Menu if Logged in using JWT authentication - node.js

I have a simple node express web app with passport JWT auth created. I use ejs for templates. Now I'm stuck.
I try to detect if User is Logged in or not. When Logged the User-Menu-dropdown on top right should be shown, otherwise a Login button. In the User-Menu-dropdown, the Email of the User should also be shown.
This is my setup:
Routes:
/user/* <-- From here all request will be authenticated using passport
/ <-- this are public sites
Code:
To detect if user are logged in, i use this ejs code:
<% if(email) { %>
<%- include('../header/userMenu', {email: email}); %>
<% } else { %>
<%- include('../header/loginButton'); %>
I use the {email: email} to pass the email porperty. This is came from the Site-Controllers, e.g. /user/dashboard where i define this like
res.locals.email = req.user.email
Now, i am a logged in user, and go to site /user/dashboard. In the top right, the User-Menu-dropdown are shown correctly, also the Email.
But, when i go to /help, the top Menu are shown BUT not the email address. After debug: In the Site-Controller help, the email are undefined.
I think, the problem is because the Routes in / are not authenticated through passport. Because of the JWT Authentication, i need tho verify the also the not-authenticated routes.
Also, I don't want to define the email property on every Controller.
How do I solve this problem?

Related

How to implement social logins in MEAN stack?

I have successfully implemented multiple social logins in Node JS.
I'm stuck with the implementation in MEAN stack.
The flow I have implemented till now:
Step 1:
Button in Angular. On Click, I'm calling an API in Node which returns the OAuth URL to which the user has to be forwarded.
Step2:
Once the user enters his correct credentials, access_token is generated and sent to callback URL in Node.
Step3:
I need to send a callback to Angular, whether access_token has been generated or not. I'm not sure as to how I should pass data to Angular Page.
Is this the right approach?
so i myself am doing a mean-stack social media project and i used oauth.io,
https://github.com/oauth-io/oauth-js
its really easy to use and implementable only thing you need to know is how to import a npm package in angular.
linkedin HTML component
<html>
<header>
</header>
<body>
<a (click)="linkedinConnector()" id="linkedin-button" class="btn btn-block btn-social btn-linkedin">
<i class="fa fa-linkedin"></i> Sign in with Linkedin
</a>
</body>
</html>
linkendin TS component
import { Component, OnInit } from '#angular/core';
import 'oauthio-web';
declare var OAuth: any;
#Component({
selector: 'app-linkedin-connector',
templateUrl: './linkedin-connector.component.html',
styleUrls: ['./linkedin-connector.component.css']
})
export class LinkedinConnectorComponent implements OnInit {
constructor(private api: ApiService) { }
ngOnInit() {}
public linkedinConnector() {
OAuth.initialize('OAUTH-IO PUBLIC KEY');
// Use popup for oauth
OAuth.popup('linkedin2').then(linkedin => {
console.log('linkedin:', linkedin.access_token);
linkedin.get('/v1/companies/[company-ID]/updates?format=json').then(data => {
//do with the data what you want
});
});
}
}
however im using pop-up instead of redirect.
they have redirect too so you can implement it using there documentation
http://docs.oauth.io/
There are two ways you can do it. One is using passport.js and using OIDC client. Here are the examples for both autentication
Passport.js implementation
Oidc implementation
So when the auth token is generated. You will redirect user to some callback url along with auth token. Your node server will be listening to that url and will store user session using some node library for sessions.
Along with it what you will do is you will do a res.redirect to url on which user will land if auth token is generated if not redirect him to some other url.
Say in your angular app you have two URLs login url, logged in url.
In case auth is success :
So if auth token is generated you will redirect user to logged in url and set a session cookie for the user.
In case auth fails :
If auth token is not generated you will redirect the user to login url with some error state as part of url query params. Something like /login?auth_error=true where you can handle auth_error appropriately and show on client.
From security perspective, write a middleware on your node layer that will validate all your api requests and check if users session cookie is valid or not else redirect him to login page.
Also in my opinion, there could be multiple approaches to do this but this is how I have implemented login in my applications. So this answer is from that perspective.
In Angular you can use already available libraries for that. No need to do it yourself.
Here you have links to two such libraries that are also OIDC certified:
angular-auth-oidc-client
angular-oauth2-oidc
I add also the link to the Google instructions for OIDC authentication where you have all the necessary information to configure the libraries to use the OIDC authentication from Google.
Check also this library angular-6-social-login which provides login for Google, Facebook and LinkedIn.
This are all open source so you can still do it yourself and use the libraries as samples for how to do it.

Can I access cookie from ejs page in server-side not the browser-side?

I need to make routine for checking login status under an environment - node.js, express, ejs.
I think I need to check login status in all the ejs view pages in server-side not in the browser-side.
To do this I think I need to write a code in ejs pages that find and look
a cookie - this cookie proves the user has login properly.
Can I access browser cookie from ejs page?
If so, could you guide me how to access cookie from ejs page?
Can I use cookie-parser module from ejs?
If there is no way to access cookie from server-side in ejs page, I believe I only have to access cookie in browser-side. Is this normal way to handle login?
So you want to track user's session. You can do the following to achieve this.
When user logged in successfully with right credentials then add that user details to session.
if(loginSuccess){
req.session.user = userObject;
}
Add a middleware to read user from session and put it into res.locals so that you can access the userObject in ejs files.
app.use(function(req, res, next) {
res.locals.user = req.session.user;
next();
});
Now you will have the userObject available in your ejs file so write your logic accordingly in ejs file. Let say if you want to display login when user not logged in and logout when your logged in, you can add code something like below
<% if(user && user.email){ %>
Logout
<% } else { %>
Login
<% } %>
Browser Cookie values can be found in req.headers.cookie.
For Example :
Print cookie in console:
router.get("/example"), (req, res) => { console.log(req.headers.cookie); }

How should I structure user login and others in this website I am working on? Please see description

I apologize if the question is not too clear.
As a background, I am working with ExpressJS and MongoDB (with mongoose etc). Also, I am a bit familiar with the topic, but I would like to do this the right way. I also use Handlebars as a view engine.
What I am trying to get at is, how do make it so that the server knows that a user is logged in and sends the right page, navigation bar, and other things?
I worked on a hackathon where I did something like this. Basically, it worked like this. When a user created an account, their informations were saved in a database. Inside the index js, I would check if the password and all matched (they were encrypted with Passport), then it they do, send the page with a parameter logged = true. If they weren't logged in, I would send the page with logged = false. Here's an example for logged out:
router.get('/', function(req, res, next) {
res.render('index', {title:'randomtitle', logged=false});
});
An example for logged in:
router.get('/', function(req, res, next) {
// code checks for cookies. Results shows that user exists. So we send this. we also find the username saved in the variable "someuser"
res.render('index', {title:'randomtitle', logged=true, username: someuser});
});
Then, the handlebars page will check if the user is logged in. For example:
<body>
{{if logged}}
<li> Hello {{username}}! </li>
{{else}}
<li> LOGIN </li>
{{/if}}
</body>
Hopefully, that makes sense. But I think that's a very sketchy approach of doing this! How do professional websites do it? Is there somewhere I can find examples for this?
Also, when I create initialize a server with express for example, it creates 2 routes automatically: index.js and user.js. What is the user.js for?
If anyone knows how it works in general (not specific to Node or Express), also please let me know.
A lot of people use passportjs.org for authentication in express. You have a lot of work to do. basically you can save user info from frontend form (html) to the database with get and post requests then add user info to session. This way at your routes you know who is authenticated. You could send the session to the front end template.
you could check to see if the user object is in the session and if it is that means they are logged in.
passportjs helps out with this a lot.
you could do req.session.logged = true

Using node/express/passport, how can I make a user object available to the browser?

This is a 'best practices' question. (UPDATED for clarity)
I am trying to find the best way to make my browser-side code adaptive to user attributes, like whether the user is authenticated, an admin, or has certain attributes.
I am creating a static application. For some valid reasons, I cannot have the pages rendered by the server. They need to be static; the same pages are served to everyone; so a solution where the server renders pages isn't feasible (please take that as given for the sake of this question).
All of the security of this application is server-side. All served pages and routes are access-managed by express and passport, verifying authentication from the cookie sent by the browser, and redirecting to /login when authentication fails. So this isn't about moving security to the browser side; I very much am implementing security server-side; this is about how to present state to the user.
I am using express-session to store the session id in a cookie. By default, it only puts the session id in the cookie, and marks it httpOnly, so I can't access it from browser code.
I modified the config of express-session to turn off httpOnly, so I can now see the cookie on the browser via javascript, but it is still just the session id.
What I'd like to be able to do is attach additional, specific information to the session cookie so my pages can decide what to show/hide based on this information.
So the question comes down to:
How do I get express/passport to pass a session cookie with additional, specific user attributes, and how do I read it on the client?
You mentioned that you are using passport for authentication so that will be the starting point of my proposed solution.
Remember we invoke done(err) if an exception occurs while trying to connect to our database, otherwise if the user is not found or the passwords do not match, we invoke done(null, false). If successful we invoke done(null, user). This attaches the user object to the request object of express (req.user).
Now that we have that out of the way, this is how we can make the user object attributes available to the user:
app.get('/',function(req, res) {
res.render('index', {
// Ternary operator which checks if the user object is empty or not
username: req.user ? req.user.username: '',
title: 'Tutorial'
})
);
I then display the 'username', if a user is logged in the username will not be empty otherwise I display the form:
<%if( !username ) {%>
<ul>
<li>Signup</li>
<li>Signin</li>
</ul>
<%} else {%>
<p><%= username %></p>
<form method="post" action="/posts">
<input type="text" name="title"><br/>
<textarea name="content"></textarea><br/>
<input type="submit" value="Post">
</form>
<%}%>
You could do the same with an attribute like 'role' for your users and check if the role is an admin or not in your view file. I am not quite sure if this answers your question though, hope it helps.
#robertklep's suggestion ended up being what I implemented.
Since express-session intentionally places only a session id it the session cookie, and that appears to be unchangeable, my only route to do this was to place an additional cookie in the response using res.cookie(), and I read that in my client app wherever needed.

Can I display messages from the server using node.js without templating?

Currently building a Single-page App with Node, with user authentication using passport and mongodb. I want to be able to send the user messages like "that username is already taken" or "please fill out all fields" on signup and login. However, all of the examples of this I have seen use a templating engine with a package like flash to render html based on javascript sent from the server. Is there a way around this? My app is pretty far along, and switching to a templating service is going to be a real pain. I don't need to render html, a simple alert box will suffice.
You can create controller action that matches the route and manually pass found model to the view.
In UserController:
find: function(req, res) {
User.findOne({'id': req.params['id']}, function(err, user) {
res.view({user: user})
})
}
Then You can reference this model in views/user/find.ejs:
<%- user.id %>
<%- user.name %>
use the above syntax to give alert();
I hope this is what you are looking for!

Resources