I'm trying to build an android application using node.js web services,the first interface allow the user to connect to a host using ip address,login and password, so he can get all the databases,i want to save the object credentials to use in all other routes,i tried express-session but it didnt worked.
Any solution?
app.post('/connect',function(req,res){
sess=req.session;
sess.user=req.body.user;
sess.password=req.body.password;
sess.server=req.body.server;
sess.database=req.body.database;
console.log(sess)
user = req.body.user;
password = req.body.password;
server = req.body.server;
database = req.body.database;
var config = {
user: user,
password: password,
server: server,
database: database
};
// connect to your database
sql.connect(config, function (err) {
if (err) {res.json({success: false, message: "error connexion to SQL Server"});
sql.close()}
else{
res.json({success: true, message: "connexion established to SQL Server"});
sql.close();
}
});
});
In your case the request make by http lib of android (or another) which is not a browse then express-session will not work. Your server must be like a API server, client(android) request login server response a token (api key or the same), in next request client push data embeded token and server side can credentials the request. I suggest read about JWT (Json Web Token) to do this.
This is easy if you are using express module in node application.
You basically create routes using express and can pass the required data to the appropriate routes and views as follows
router.get('/', function(req, res, next) {
res.render('category',
{
videodata: vd
});
});
Here while rendering the response, the data that is to be passed is also included. It's name is videodata and value is vd
Related
So I am making an application with React on the front end and express on the backend. The way my application works on the front end is I have two apps: an authenticated app and an unauthenticated app.
const {authenticated} = useAuth().authData;
return authenticated ? <AuthenticatedApp/> : <UnauthenticatedApp/>
Here the authenticated variable comes from an AuthContext that I can access globally throughout the application. What it does is store the authenticated value in localStorage. What I am stuck on is when/where I set this authenticated value. In my express backend I have a middleware that checks if the session is authenticated (the user has logged in).
app.use((req, res, next) => {
console.log('Checking session...');
if (!req.session.authenticated) {
const err = new Error('Not authenticated!');
err.status = 401;
return next(err);
} else {
return next();
}
});
I originally had a function called checkSession that would make a call to express to check if the session is authenticated. This would occur as a separate request along with every request. I see a lot of overhead in this so I am looking for an alternative. What I am considering to do now is set a header value on every response from express like so.
app.use((req, res, next) => {
console.log('Checking session...');
if (!req.session.authenticated) {
const err = new Error('Not authenticated!');
err.status = 401;
return next(err);
} else {
res.setHeader('Authenticated', true);
return next();
}
});
And then I would access this in every response on the front end and do the following.
setAuthenticated(res.header.authenticated)
Is there a simpler way to do this without making two API calls for each request or having to write setAuthenticated() in every response from the backend? What I am essentially trying to fix is the user manually changing the localStorage value for authenticated to something that isn't null.
You can update the "authenticated" state in local storage only once when the app is loaded, or even when you log the user in. If someone updates that state in the local storage it should be "their problem". Of course, your backend should separately authenticate incoming requests, based on tokens or cookies, not the value from the local storage. Should the user make a request to a secured endpoint, without valid authentication credentials (access token or cookie) then the backend should respond with a 401 response. The front end can catch 401 responses from your backend and then update the "authenticated" state in local storage, and as a result, render the unauthenticated app.
When we use jsonwebtoken in Node, we sign a particular token for the user and send it back. However, when we verify the token when the user sends it in the header (Authentication: <token>), how does the jwt know that that token which it is verifying is for that particular user and not for some other user who also sent a request at the same time? Does it store the token somewhere internally?
At the time of login, you sign a token where payload is the userId, which is nothing but the _id field in the queried user object.
loginUser: async (req, res, next) => {
try {
const { email, password } = req.body
const user = await User.findOne({ email })
const token = auth.signToken({ userId: user._id })
res.status(200).json({ user, token })
} catch (error) {
return next(error)
}
}
auth.js
function signToken(payload) {
return jwt.sign(payload, JWTSECRET)
}
function verifyToken(req, res, next) {
const token = req.headers.Authorization || req.headers.authorization || ""
if (!token) {
return res.status(403).json({ error: "Not authorized" })
}
jwt.verify(token,JWTSECRET, (err, decodedObj) => {
if (err) {
return res.status(403).json({ error: "Not authorized" })
}
req.user = decodedObj
next()
})
}
module.exports = { signToken, verifyToken }
In the callback of jwt.verify, you get a decodedObj which is like:
{ userId: '5edb3ae6d6b129183c1393bc', iat: 1591425786 }
where iat is the time at which the jwt was issued.
req.user = decodedObj
Here, we're "attaching" the decoded data to the user object so that when a request is made to the protected route, we can get the userId from the request object, like req.user.userId, and then query it from the database.
When you sign a token, you provide a payload which can be a userId and a secret. So, the token gets signed. After that, you need to verify the token in case you're trying to access some protected page that requires a token.
So, when you send a request to that protected route, like this:
router.get("/me", auth.verifyToken, usersController.identifyUser)
where identifyUser is a controller function that just identifies the logged in user by checking the userId(remember the user object contains the decoded object data).
how does the jwt know that that token which it is verifying is for that particular user and not for some other user who also sent a request at the same time? Does it store the token somewhere internally?
It's because of the payload that you give, which is unique to the user.
The Authentication token is stored in an Authentication Server, so when you send the Authentication token in your request header, the Authentication Server authenticated your client.
After being authenticated by Authentication Server, the client can now pass JWT to make API calls to the Application Server. Since client is allowed to make API calls, Application Server can verify the JWT token the client has sent and can process the API call.
Note that for making API calls, the client has to send a Authorization: Bearer <token> for each API call, which is stored at the server (aka Authorization Server)
the token is most store in the client
when the token verifying successfully, we will get some user info, etc account id, so we can use account id to find more user info in the database, and check the use is really exist
maybe it is useful for you?
You will typically sign the token with the user id when sending it from the server. So when the client then sends back that token you decode it and it will return the id to you. Which you then use to find the user in the data base
I am using Node.js and ExpressJS to save a mongoose model. I am getting the error of Error: Can't set headers after they are sent. I think it has to do with the line res.redirect("/dashboard/it/model"); conflicting with setRedirect({auth: '/login'}), from my route, the code in the setRedirect is below labeled. The setRedirect is from a middleware called middleware-responder that came as part of the template I am using to create Stripe user accounts. I can not remove it as far as I know. my GitHub repo I have committed all files that are not test files and are relevant (no unneeded views ect than what is already there)
Save Model
if(type=="aps"){
var newAccessPoint = {
name: name,
manufacturer: manufacturer,
model: model,
range: range,
bands: bands,
channel: channel,
poe: poe,
notes: notes,
signout: signout,
author:author
};
// Create a new access point and save to DB
AP.create(newAccessPoint, function(err, newlyCreated){
if(err){
console.log(err);
} else {
//redirect back to models page
res.redirect("/dashboard/it/model");
}
});
}
Route
app.post('/dashboard/it/model/new',
setRender('dashboard/it/modelCreate'),
setRedirect({auth: '/login'}),
isAuthenticated,
dashboard.getDefault,
(req, res) => {
setRedirect code
exports.setRedirect = function(options){
return function(req, res, next){
if(req.redirect){
req.redirect = _.merge(req.redirect, options);
} else {
req.redirect = options;
}
next();
};
};
setRender code
exports.setRender = function(view){
return function(req, res, next){
req.render = view;
next();
};
};
That's happening because you are trying to send a response to the client when you already closed the connection.
Hard to tell by the way you are showing us your code but it seems like you are redirecting to options and then in the same request you are redirecting to dashboard/it/model
I pull your code from github.
I think the error message was clear. in your getDefault() middleware you are rendering a response so the server start sending data to your client and just after you try to redirect him to another url. Thats why when your comment out that middleware all work nicely.
I manually created a user in Azure active directory for my project and I am able to get the users. I made a chrome extension and GCM provides me a ID which I want to be linked with the microsoft account.
So for each user, I want a GCM id (got this part) and an Azure AD Id linked together.
I was doing the following:
router.route('/users')
// create a user accessed at POST http://localhost:8080/api/users)
.post(function(req, res) {
// Get an access token for the app.
auth.getAccessToken().then(function (token) {
console.log(token)
var user = new User({
officeId: token,
name : req.body.name,
email :req.body.email,
chromeId : req.body.chromeId
});
user.save(function(err) {
if (err)
res.send(err);
res.json({ message: 'User created!' });
});
});
});
However, what this does is take the auth token id, chromeId, name and email and just adds it to my mongoose database.
What can I do differently in order to get what I want to achieve? My teammate says what I am doing is correct but I checked the Azure AD and I don't see my user authorized there.
Btw, in the front-end, I ask a user to give their microsoft email and name.
Also, I merged my code with the code found here https://github.com/OfficeDev/O365-Nodejs-Microsoft-Graph-App-only
// #name getAccessToken
// #desc Makes a request for a token using client credentials.
auth.getAccessToken = function () {
var deferred = Q.defer();
// These are the parameters necessary for the OAuth 2.0 Client Credentials Grant Flow.
// For more information, see Service to Service Calls Using Client Credentials (https://msdn.microsoft.com/library/azure/dn645543.aspx).
var requestParams = {
'grant_type': 'client_credentials',
'client_id': config.clientId,
'client_secret': config.clientSecret,
'resource': 'https://graph.microsoft.com'
};
// Make a request to the token issuing endpoint.
request.post({url: config.tokenEndpoint, form: requestParams}, function (err, response, body) {
var parsedBody = JSON.parse(body);
if (err) {
deferred.reject(err);
} else if (parsedBody.error) {
deferred.reject(parsedBody.error_description);
} else {
// If successful, return the access token.
deferred.resolve(parsedBody.access_token);
}
});
return deferred.promise;
};
If you want to create use in your AAD, you can leverage the Microsoft Graph API: Create User, which is not implemented in your code or the graph.js code at github repository.
You need to implement the function yourself like:
Additionally, it seems that we have to generate the access token in Authorization Code Grant Flow to complete the operation. As in my test, I got the Authorization_RequestDenied error when I use the app-only flow access token to authorize the operation, and the graph server returned me the message:
"message": "Insufficient privileges to complete the operation."
you can refer to https://github.com/OfficeDev/O365-Nodejs-Microsoft-Graph-Connect/ for the sample.
I am new to Node.js and I'm trying to figure out for few days how to make a simple login-register feature for a website using Express.js with EJS template engine and MySql.
I have installed Node on my PC and I've used the Express-Generator to make a basic folder structure (views, routes, public folders).
I understand how I can pass variables from node to the front end using ejs but I don't know how to pass it back. I've tried watching some tutorials on the internet but nothing seems to make me see the logic. Where do I put the MySql code? How can I pass back the input values once the user clicks "SUBMIT"?
How says Jake, I suggest to use Sequelize for MySQL.
I will try to make a small steps for your start, and after you can study more about each process and tool.
1) Front-end (EJS);
<form id="login" action="/login" method="post">
<input name="username" type="text">
<input name="password" type="password">
<input type="submit">Ok</input>
</form>
Here, the form will request the route login. The route:
2) Route
module.exports = function (app){
var login = app.controllers.login;
app.get('/', login.index);
app.post('/login', login.login)
};
The route will call the login method in the controller called login.js.
3) Controller
module.exports = function(app) {
var sequelize = require('./../libs/pg_db_connect'); // resquest lib of connection to mysql/postgres
var LoginController = {
index: function(req, res) {
res.render('login/index');
},
login: function(req, res) {
var query = "SELECT * FROM users"; // query for valid login
sequelize.query(query, { type: sequelize.QueryTypes.SELECT}).then(function(user){
if (req.body.username == user[0].username && req.body.password === user[0].password ){
res.redirect("/home");
} else {
res.render("login/invalid_access");
}
});
}
};
return LoginController;
};
In this point, is exec the query for to valid the login and verify if user can be log in. Request method is the main point.
For response and send information to view, it used res.SOME_METHOD:
res.send();
res.end();
res.download();
res.json();
Plus: Sequelize MySQL connection.
In the express structure, it's localized in lib/my_db_connection.js:
var Sequelize = require('sequelize');
module.exports = new Sequelize('database_name', 'user', 'pass', {
host: 'localhost',
dialect: 'mysql',
pool: {
max: 10,
min: 0,
idle: 10000
},
});
I suggest before you code, read the necessary docs.
You're going to have to use some sort of AJAX library (or vanilla js ajax) to send the information to a http endpoint you set up in express. For simple stuff the jquery ajax methods will do just fine. You will likely are looking to make a POST request.
As for the MySql code, checkout Sequelize. Its a cool library for interacting with sql databases from express. Its similar to how mongoose works for mongo.