y'all, I'm trying to create a signup and login local-Strategy with passport and have been seeing a PROXY ERROR:. I thought I was returning all possible endings for the functions but maybe I'm missing something? I'm new to development and am going crazy haha... Any help is much appreciated, also let me know if I missed adding pertinent code. (I did not add the return block from the react component, I assumed it unnecessary). I am importing my strategies through a strategy index.js (also did not include).
SignupStratagy.js / local strategy
const Strategy = require("passport-local").Strategy;
const User = require("../models/User");
// for password encryption;
const bcrypt = require("bcrypt");
const saltRounds = 10;
const SignupStrategy = new Strategy({ passReqToCallback: true }, function (
req,
username,
password,
done
) {
// console.log(username, password);
const encryptedPass = bcrypt.hashSync(password, saltRounds);
// console.log("encryptedPassword", encryptedPass);
const phone = req.body.phone;
const email = req.body.email;
const street = req.body.street;
const city = req.body.city;
const state = req.body.state;
const zip = req.body.zip;
const isAdmin = req.body.isAdmin;
User.findOne({ username: username }, (err, user) => {
// console.log("SignupStrategy.js / req:", req.body);
if (err) {
return done(err, user);
}
if (user) {
return done("User Name is already taken:", user);
}
})
// .lean()
// .exec();
// console.log("SignupStrategy.js / encrypted password:", encryptedPass);
let newUser = {
username,
password: encryptedPass,
phone,
email,
street,
city,
state,
zip,
isAdmin,
};
User.create(newUser, (error, newUser) => {
if (error) {
return done(error, null);
}
// delete the user password before it is sent back to the front-end;
newUser.password = undefined;
delete newUser.password;
return done(null, newUser);
});
});
module.exports = SignupStrategy;
apiRoute.js / route for signup
const router = require("express").Router();
const db = require("../models");
const passport = require("../config");
// const isAuthenticated = require("../config/middleware/isAuthenticated");
// USER SIGN-UP ROUTE
router.post("/api/signup", function (req, res, next) {
// console.log(req.body);
passport.authenticate("local-signup", (error, user) => {
// console.log("apiRoutes.js / error:", error, "apiRoutes.js / user:", user)
if (error)
return res.status(500).json({
message: error,
});
else {
return res.status(200).json(user);
}
})(req, res, next);
});
Signup / react component
import React, { useState } from "react";
import axios from "axios";
import { Redirect, Link } from "react-router-dom";
import chip from "../../images/chipper/chipperOne.png";
import "./style.css";
function Signup() {
const [signupState, setSignupState] = useState({
username: "",
password: "",
phone: "",
email: "",
street: "",
city: "",
state: "",
zip: "",
key: "",
redirect: false,
adminRedirect: false,
isAdmin: false,
});
const onChange = (e) => {
// console.log("working")
// console.log(typeof e.target.type)
if (e.target.type === "checkbox") {
if (signupState.isAdmin === false) {
setSignupState({
...signupState,
isAdmin: true,
})
} else {
setSignupState({
...signupState,
isAdmin: false,
});
}
} else {
setSignupState({
...signupState,
[e.target.name]: e.target.value,
});
}
};
const onSubmit = async (e) => {
e.preventDefault();
if (signupState.isAdmin === true) {
const response = await axios.post("/api/admin-sign-up", {
key: signupState.key,
});
console.log(response.status);
if (response.status === 500) {
console.log(response);
return;
}
if (response.status === 200) {
console.log(response.status);
setSignupState({
...signupState,
adminRedirect: true,
});
}
}
// console.log(`onSubmit ${signupState}`);
axios.post("/api/signup", {
username: signupState.username,
password: signupState.password,
phone: signupState.phone,
email: signupState.email,
street: signupState.street,
city: signupState.city,
state: signupState.state,
zip: signupState.zip,
isAdmin: signupState.isAdmin,
})
.then((res) => {
console.log(res);
if (res.data) {
console.log(`Sign-in Successful`);
setSignupState({
...signupState,
redirect: true,
});
}
})
.catch((err) => {
if (err) console.log(`Sign-Up server error ${err}`);
});
};
ERROR:
Proxy error: Could not proxy request /api/signup from localhost:3000 to http://localhost:3001.
[1] See https://nodejs.org/api/errors.html#errors_common_system_errors for more information (ECONNREFUSED).
Related
I'm using passport strategies for different socialMedia logins and getting the following two errors
InternalOAuthError: Failed to fetch user profile
Cannot set headers after they are sent to the client
I have doubt there somewhere I have returned a callback or response so getting 2nd error but for 1st don't know reasons scope seems to be correct!
strategy code
passport.use(new GoogleStrategy({
clientID: GOOGLE_CLIENT_ID,
clientSecret: GOOGLE_SECRET_KEY,
callbackURL: GOOGLE_CALLBACK_URL
}, async (acessToken, refreshToken, profile, done) => {
await User.findOne({ email: profile._json.email }, async (err, user) => {
if (err) {
console.log("passport.config --> err", err);
done(err, null);
} else if (user) {
if (user.socialType !== "GOOGLE" || user.socialType === null)
done(`LOGIN_CREDENTIALS_WITH_${(user.socialType || "PASSWORD").toUpperCase()}`, false);
else {
done(null, user);
}
} else {
// console.log(profile);
const user = {
email: profile._json.email,
socialId: profile.id,
socialType: "GOOGLE",
firstName: profile.name.givenName,
lastName: profile.name.familyName,
isActive: profile._json.email_verified,
isVerified: profile._json.email_verified,
socialImageUrl: profile._json.picture,
userType: "CUSTOMER"
};
const newUser = new User({ ...user });
const newUserData = await newUser.save();
done(null, newUserData);
}
});
}));
route code:
router.get('/auth/:socialType', customerCtrl.socialTypeLogin);
router.get('/auth/:socialType/callback', customerCtrl.socialTypeLoginCallback);
controller code:
const socialTypeLogin = async (req, res) => {
await customerService.socialTypeLogin(req, res);
};
const socialTypeLoginCallback = async (req,res) => {
await customerService.socialTypeLoginCallback(req,res);
};
service code:
const socialTypeLogin = async (req, res) => {
try {
const socialType = (req.params.socialType || '').toLowerCase();
const GOOGLE_SCOPE = ['email', 'profile'];
const FACEBOOK_SCOPE = ['email'];
let scope = [];
if (socialType === 'google') {
scope = GOOGLE_SCOPE;
} else if (socialType === 'facebook') {
scope = FACEBOOK_SCOPE;
}
let oauthOptions = { scope: scope};
const { returnUrl } = req.query;
if(returnUrl && returnUrl.trim().length !== 0) {
oauthOptions['state'] =JSON.stringify({ returnUrl: returnUrl });
}
passport.authenticate(socialType, oauthOptions)(req, res);
}
catch (error) {
}
}
/**
* #param {string} socialType
*/
const socialTypeLoginCallback = async (req, res) => {
const socialType = (req.params.socialType || '').toLowerCase();
// return new Promise((resolve, reject) => {
try {
passport.authenticate(socialType, async (err, user) => {
let webappRedirectURL = WEBAPP_LOGIN_URL;
try {
const state = req.query.state;
if(state) {
const stateObj = JSON.parse(state);
webappRedirectURL = stateObj.returnUrl;
}
} catch (err1) {
console.log("customer.service --> parsing error",err1);
}
if (err || !user) {
console.log("customer.service --> !user",err);
res.render('oauth-redirect', {
webappRedirectURL: webappRedirectURL,
success: false,
error: err,
timerCounter: 5,
accessToken: undefined
});
}
else {
console.log("customer.service --> Generating Token",user.generateJWT());
res.render('oauth-redirect', {
webappRedirectURL: webappRedirectURL,
success: true,
timerCounter: 5,
accessToken: user.generateJWT(),
error: undefined
});
}
})(req, res);
}
catch (error) {
console.log("customerService.js ==> socialTypeLoginCallback -->",error);
}
};
Thanks for help in advance!
I have doubt there somewhere I have returned a callback or response so getting 2nd error but for 1st don't know reasons scope seems to be correct!
In socialTypeLogin
add line
oauthOptions['session'] = false;
I'm developing a server in Node JS where there are two routes - Login and Signup.
Whenever I do signup, I am getting response as success and the data is being stored in MongoDB database successfully and then I'm getting [nodemon] app crashed - waiting for file changes before starting... in my console.
Note:- "The problem is in signup only not in login".
postSignup() will be called when a user requests for signup which is validated according to schema and inserted in database.
I'm providing the code related to signup.
signup.js
const { User } = require("../../models");
const createError = require("http-errors");
const postSignup = (req, res, next) => {
//validation
const validation = User.validate(req.body);
if (validation.error) {
const error = new Error(validation.error.message);
error.statusCode = 400;
return next(error);
}
//check Existence
const user = new User(req.body);
user
.checkExistence()
.then((result) => {
if (result.check) {
const error = new Error(result.message);
error.statusCode = 409;
return next(error);
}
user.save((err) => {
if (err) {
console.log(err);
return next(createError(500));
}
res.status(201).json({
message: "User has been Successfully Created",
});
});
})
.catch((err) => {
next(createError(500));
});
};
module.exports = {
postSignup,
};
User.js
const { dbCon } = require("../configuration");
const { userValidator, logSchema } = require("../validator");
const { hashSync, compareSync } = require("bcryptjs");
class User {
constructor(userData) {
this.userData = { ...userData };
}
save(cb) {
dbCon("users", (db) => {
try {
const hashPass = hashSync(this.userData["password"], 12);
this.userData["password"] = hashPass;
db.insertOne(this.userData);
cb();
} catch (err) {
cb(err);
}
});
}
checkExistence() {
return new Promise((resolve, reject) => {
dbCon("users", async (db) => {
try {
const user = await db.findOne({
$or: [
{ username: this.userData["username"] },
{ email: this.userData["email"] },
],
});
if (!user) {
resolve({
check: false,
});
} else if (this.userData["username"] === user.username) {
resolve({
check: true,
message: "username already exists",
});
} else if (this.userData["email"] === user.email) {
resolve({
check: true,
message: "email already exists",
});
}
} catch (err) {
reject(err);
}
});
});
}
static validate(userData) {
//console.log(userData);
return userValidator.validate(userData);
}
module.exports = User;
userValidator.js
const Joi = require("#hapi/joi");
const schema = Joi.object({
username: Joi.string().alphanum().required().min(3).max(15),
email: Joi.string().email().required(),
password: Joi.string()
.pattern(
new RegExp(
"^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!#$%^&*-]).{8,}$"
)
)
.message(
"Password must contain at least eight characters, at least one number and both lower and uppercase letters and special characters"
)
.required(),
first_name: Joi.string().required(),
last_name: Joi.string().required(),
});
module.exports = {
schema
};
I faced the same issue. I don't know what was the issue but I tried to change node version in mongo db connect and then used the new connect URL.
If it still doesn't work, then try to create new cluster and connect it again with new cluster.
it seems that the create method does not return any promise that then can handle
I tried different things but nothing worked
this is my routes file
const express = require("express")
const router = express.Router();
const controller = require("./controller")
router.post("/signup", controller.create);
module.exports = router;
and this is my model file
const mongoose = require('mongoose');
const User = new mongoose.Schema(
{
firstName: {
type: String,
required: true
},
lastName: {
type: String,
required: true
},
picture: {
type: String
},
password: {
type: String,
select: false
},
email: {
required: true,
type: String,
unique: true
}
},
{
timestamps: true
}
);
User.index({
firstName: 'text',
lastName: 'text',
});
module.exports = mongoose.model('User', User);
and this is the controller file
const User = require('./model');
const { hash, compareHash } = require('../lib/util');
const { createToken, findUserByToken } = require('../lib/auth');
const cookieIsSecure = process.env.ENVIRONMENT === 'production';
exports.create = async (req, res) => {
const password = await hash(req.body.password);
const rawUser = {
...req.body,
password,
};
User.create(rawUser)
.then(async user => {
return user.save();
})
.then(async user => {
const newUser = user.toObject();
res.send(newUser);
})
.catch(err => {
if (err.code === 11000) {
res.status(400).send({ message: 'A user with this email address has already registered.' });
return;
}
res.status(500).send({ message: 'An unexpected error occurred' });
});
};
it always return the 500 error "an unexpected error occurred"
which is not really specific. and i do not know what is the problem exactly. but I am sure it has something to do with the model.create() it does not return any promise.
Here you are mixing methods. create doesn't want save in it as it's implicit:
https://mongoosejs.com/docs/api.html#model_Model.create
Please try this, I've refactored your code a bit and added much easier to read and use try/catch:
const rawUser = new User({ ...req.body, password});
try {
await rawUser.save();
res.status(201).send(newUser);
} catch(err) {
if (err.code === 11000) return res.status(400).send({ message: 'A user with this email address has already registered.' });
res.status(500).send({ message: 'An unexpected error occurred' });
}
You need to use async/await like this:
exports.create = async (req, res) => {
try {
const password = await hash(req.body.password);
const rawUser = {
...req.body,
password
};
const user = await User.create(rawUser);
const newUser = user.toObject();
res.send(newUser);
} catch (err) {
console.log("ERROR: ", err);
if (err.code === 11000) {
return res.status(400).send({
message: "A user with this email address has already registered."
});
}
res.status(500).send({ message: "An unexpected error occurred" });
}
};
For, an user verification now I hardcoded the username and password directly on my code. But I want this dynamically using database username and password. As, i'm new to hapi.js it seems quite difficult for me. This is my code :
app.js
const auth = require('hapi-auth-basic');
const hapi = require('hapi');
mongoose.connect('mongodb://localhost:27017/db', {
useNewUrlParser: true }, (err) => {
if (!err) { console.log('Succeeded.') }
else { console.log(`Error`)}
});
const StudentModel = mongoose.model('Student', {
username: String,
password: String
});
const user = {
name: 'jon',
password: '123'
};
const validate = async (request, username, password, h) => {
let isValid = username === user.name && password === user.password;
return {
isValid: isValid,
credentials: {
name: user.name
}
};
};
const init = async () => {
await server.register(auth);
server.auth.strategy('simple', 'basic', {validate});
server.auth.default('simple');
server.route({
method: 'GET',
path: '/',
handler: async (request, h) => {
return 'welcome';
}
});
}
I tried to do this by changing the validate as below :
const validate = async (request, username, password, h) => {
let isValid = username === request.payload.name && password === request.payload.password;
return {
isValid: isValid,
credentials: {
name: request.payload.name
}
};
};
but i got the type error "name" as it's natural. How can I modify this?
Here, fetch user and check in the validation method
const validate = async (request, username, password, h) => {
// fetch user here
const user = await StudentModel.findOne({username, password}).exec();
// user doesn't exist
if(!user) return {isValid: false}
// just make sure here user really exists
return {
isValid: true,
credentials: {
name: user.name
}
}
}
I'm trying to update an invitation when the invited user registers. The invitation has an auth property which is a nested object, which itself has a property with the key "used." I'm just trying to explicitly declare the value to be true, and save, using async/await. But it's not updating. Is there a better way to do this?
My function:
exports.invitedSignup = async (req, res, next) =>
{
const { firstName, lastName, company, password, email, companyCode, token } = req.body;
console.log(email);
try
{
const user = await User.findOne({ email });
const invitation = await Invitation.findOne({ email }).sort({ field: 'asc', _id: -1 }).limit(1);
if (user) { return res.status(422).send({ error: "User is already registered" }); };
if (!invitation) { return res.status(422).send({ error: "No invitation on record" }); };
if (token !== invitation.auth.token)
{
return res.status(422).send({ error: "Something has gone wrong, please sign up again" });
}
try
{
invitation.auth.used = true;
const updateInvitation = await invitation.save();
console.log("authorization: " + invitation.auth.used);
} catch (e)
{
return next(e);
}
try
{
const saveUser = new User({
firstName: firstName,
lastName: lastName,
email: req.body.email,
password: password,
company: company,
companyCode: companyCode,
role: 1,
auth: { used: true }
});
const newUser = await saveUser.save();
const { email, firstname, lastname } = newUser;
res.json({ token: tokenForUser(newUser), email, firstName, lastName });
}
catch (e)
{
return next(e);
}
}
catch (e)
{
return next(e);
}
};
The invitation schema:
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const bcrypt = require('bcrypt-nodejs');
//define model
const invitationSchema = new Schema({
email: { type: String, unique: true, lowercase: true, unique: true },
inviter: String,
company: String,
companyCode: String,
created: Date,
auth: {
token: String,
used: Boolean,
expires: Date,
}
});
invitationSchema.pre('save', function (next)
{
const invitation = this;
bcrypt.genSalt(10, (err, salt) =>
{
const tomorrow = new Date();
invitation.created = tomorrow;
tomorrow.setDate(tomorrow.getDate() + 1);
if (err) { return next(err); };
invitation.auth = { token: salt, used: 0, expires: tomorrow };
next();
});
});
//create model class
const ModelClass = mongoose.model('invitation', invitationSchema);
//export model
module.exports = ModelClass;
http://mongoosejs.com/docs/schematypes.html#mixed
person.anything = { x: [3, 4, { y: "changed" }] };
person.markModified('anything');
person.save(); // anything will now get saved