How can I setup an OpenID Connect authentication with Node Js? - javascript

here is the thing. I have my app that has separated back-end and front-end into two different project (back-end with Node-JS, and front-end with Vue-JS). I got a home page with a button that should redirect the user to the authentication server to log in.
So i made an "on-click" function in my homePage.vue that will consume a function from my api.
I've read a lot of documentation and seen some examples. But to be honest, during those past weeks, even if I tried, I still do understand nothing about how authentication works.
You can see below the js file i wrote inspired by examples that i found:
auth.js
const express = require('express');
const { auth } = require('express-openid-connect');
const app = express();
app.use(
auth({
issuerBaseURL: 'myDomainUrl',
baseURL: 'http://localhost:8080',
clientID: 'myClient_ID',
secret: 'aaaaaaaaaaaaaaaaaaaa',
idpLogout: true,
authRequired: false,
})
);
module.exports = app;
There is also the route with the function that I try to implement:
auth.route.js
module.exports = app => {
var router = require("express").Router();
router.get('', location.replace('myDomainUrl'));
app.use('/api/login', router);
};
I don't know if it's important but my back-end runs on the port 4000 and my front-end runs on the port 8080.
If someone can explain me how I can do to make my authentication work and what I have to change, it would be great.
Thanks you in advance, I hope I was clear enough about my problem. If not, do not hesitate to ask me what was not clear.

Related

Firebase Authentication via Server Side to access routes

I am using sessionStorage and also firebase authentication for email and password.
In my server.js I am wondering how can I make it so that if a user is not logged in they cannot access a route, or rather be redirected to the login route instead.
The firebase sdk I am using is only usable via the client side. Is there any documentation to help that I have been unable to find.
Please let me know if I need to clarify my question more and I will do my best to do so.
Here is my server.js:
const express = require('express');
const admin = require('firebase-admin');
const bcrypt = require('bcrypt');
const path = require('path');
let serviceAccount = require("./1234.json");
admin.initializeApp({
credential: admin.credential.cert(serviceAccount)
});
let staticPath = path.join(__dirname,"public");
const app = express();
app.use(express.static(staticPath));
app.use(express.json());
app.get('/login', (req,res) => {
res.sendFile(path.join(staticPath, "form.html"));
})
app.get('/seller', (req,res) => {
// if(!user) res.redirect('/login');
res.sendFile(path.join(staticPath, "seller.html"));
})
Edit:
So far the only thing that helps me with this is by creating a seller.js
and inserting this code here, but I am unsure of if this method is safe or if there is a way to hide this from being manipulated:
body = document.getElementsByTagName('BODY')[0];
user = JSON.parse(sessionStorage.user);
if(user && user.seller){
console.log('Allow Access')
} else{
console.log('Deny')
body.innerHTML = `
<div class="sticky" id="nav"></div>
<div style="padding:300px">
<center>You do not have permission to view this page.</center>
</div>
<div id="footer"></div>
`;
}
You can use the firebase-admin package to verify the token on the server. If the verification passes, you can continue with route logic. To make things simple, you could wire up a middleware in Express that verifies the token, rather than repeating the calls for authenticated routes.
Relevant documentation: https://firebase.google.com/docs/auth/admin/verify-id-tokens#web
Also, you should not rely on client-side scripting to verify a user's authentication status if you're trying to restrict resources on a server. It would be trivial for someone to find the endpoints being used, and, assuming there's no logic on the server to verify the user, they could potentially retrieve sensitive information.

How to pass id of object to another page?

I have full stack application which i deployed on netlify, my frontend structure (vanilaJS) is following:
client
-index.html
-training.html
-scripts
-style
My backend is in Express and successfuly deployed to Heroku. I have the following rutes:
const express = require('express')
const app = express()
const trainingRoute = require('./routes/training')
app.use('/training', trainingRoute)
In the index.html on frontend i have card:
<div class="trening-plan-container">
<div class="plan-btn">
<button>Pogledaj</button>
</div>
</div>
452153221489 is id of item in database. When i click on link, i get my url:
https://example.netlify.app/training/452153221489
and i get 404 status, not found.
How can i make request to my backend route /training/452153221489 which i have defined in
app.use('/training', trainingRoute) :
const express = require('express')
const router = express.Router()
const {
getTrainingPlan,
} = require('../controllers/trainingPlan')
router.route('/:id').get(getTrainingPlan)
module.exports = router
When i use fetch, everything works, because i specify full url
https://trening-bek.herokuapp.com/training/452153221489
After days of research i have found proxy might be the solution but it doesn't work.
I could use Pogledaj then retreive id and make fetch api call but I'm not sure that's the way it should be done.
Is it bad practice to seperate frontend and backend on two servers?

Node.js + Express + i18next how manage two languages same time

in my Node.js + Express + i18next app I would like to keep separate frontend and backend languages. I already managed to keep separate the login session data, so that I can login as normal user in the frontend and as administrator in the backend at the same time and
independently:
const express = require('express');
const session = require('express-session');
const app = express();
...
app
.use('/admin', session({
...
cookie: {
path: '/admin',
},
name: 'adminSessionID',
...
}))
.use('/', session({
...
cookie: {
path: '/',
},
name: 'sessionID',
...
Now I need to do the same with i18next and languages. What can I do? I tried creating 2 i18next instances but the cookie created is always only the last one defined and, even worst, if I change language via query string, it changes both in front and backend...
Any advice could be usefull, thank you

Node.js with firebase does not save info in the Session

I am trying to use session in my app, to keep track on user log-in and more.
But...
When I tried using the simplest way, I kept getting the error :
Warning: connect.session() MemoryStore is not designed for a production environment, as it will leak memory, and will not scale past a single process.
There for, after much searching, I added the firebase-session functionality,
but now, even though I get no error, nothing is saved in the session.
This is my code:
const functions = require('firebase-functions');
const express = require('express');
const session = require('express-session');
const FirebaseStore = require('connect-session-firebase')(session);
const firebase = require('firebase-admin');
const ref = firebase.initializeApp(
functions.config().firebase
);
const app = express();
app.use(session({
store: new FirebaseStore({
database: ref.database()
}),
secret: 'asdfasgbrwewet53hnhwetynsy',
resave: true,
saveUninitialized: true
}));
app.get('/', function(req, res, next) {
console.log(req.session);
req.session.username='rakafa';
res.send('Returning with some text');
});
app.get('/bar', function(req, res, next) {
console.log(req.session);
var someAttribute = req.session.username;
res.send(`This will print the attribute I set earlier: ${someAttribute}`);
});
exports.app = functions.https.onRequest(app);
This is what I did so far:
My original example taht I used to start using session: session-express example
I took the firebase part from npm: npm firebase-session
Tried to use radis-store as a solution, didn't word: using radis-store solution
Using session-store, gave me the same worning as using nothing.. npm session-store
This question gave me the idea of using firebase-session database sessions explanations
I saw this an example with cookies, but didn't understand, and didn't find another example cookie session
Just another word, I only just started learning Node.js, so please try using simple examples, so I would understand ;)
And please forgive my starte's mistakes
Please, HELP....
=== edit ===
According to orxelm's answer, I changed my ref to this:
const ref = firebase.initializeApp({
//admin.credential.cert(serviceAccount)
credential: firebase.credential.applicationDefault(),
databaseURL: "https://*****.firebaseio.com/"
});
But still, when I run the app, there is nothing in the session once I refresh the page.
sessions in the server
^^
I can see that the app created a lot of sessions in the server.
but none of them have the information I added on the app,
and since I use only one browser, there should only one session, am I wrong?
I had this problem, when I was using firebase hosting and functions, but can be solved by simply setting name:"__session" in the session.
app.use(session({
name:"__session,
...
after adding this, saving values in the session like req.session.username='rakafa' worked fine.
Where is you firebase config?
Maybe try to initialize the firebase admin this way:
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: 'https://<DATABASE_NAME>.firebaseio.com'
});

Universal username/password authentication in express.js or react.js

Setting up user authentication can be easily achieved in apache by setting up .htaccess and .htpasswd However I am developing an new web application and I am using express.js or react.js to create a web server. I searched user authentication online but they are long projects for email style logins like here. All I need is a single universal username and password. When a user browse to my website a pop appear for the username and password. (Same like .htaccess style)
As per my understandings you need http server authentication in nodejs.
I know one npm module. link
And it's pretty easy to setup also.
Basic example
// Authentication module.
var auth = require('http-auth');
var basic = auth.basic({
realm: "Simon Area.",
file: __dirname + "/../data/users.htpasswd"
});
// Creating new HTTP server.
http.createServer(basic, (req, res) => {
res.end(`Welcome to private area - ${req.user}!`);
}).listen(1337);
If anyone is interested to do in ES2016 then follow the following code. Set the babel etc to make it work.
import express from 'express';
import auth from 'http-auth';
// Configure basic auth
const basic = auth.basic({
realm: 'SUPER SECRET STUFF'
}, (username, password, callback) => {
callback(username == 'admin' && password == 'password');
});
// Set up express app
const app = express();
// Create middleware that can be used to protect routes with basic auth
const authMiddleware = auth.connect(basic);
// Protected route
app.get('/', authMiddleware, (request, response) => {
response.send('you made it!');
});
app.listen(3000);

Categories