Please i am getting invalid_client as my error whenever i tried to send mail using Nodemailer and googleapis - oauth2-playground

const CLIENT_SECRET = "GOCSPX-abcdefghijk-lmnopqrstuvwxyz1"
const REDIRECT_URI = "https://developers.google.com/oauthplayground"
const REFRESH_TOKEN = "1//234567890-AaaaaaaaaAAAAAAAAaaaaaaaAAAAAAaaaaaAAAAAAAAaaaaaaAAAAAAAaaaaaaaAAAAAAAaaaaaAAAAAAaaaAAAaaAAaaa"
const CLIENT_ID = "1041154309301-9tq6odoru10747igk67gdt2etcp10env.apps.googleusercontent.com"
const oAuth2Client = new google.auth.OAuth2(CLIENT_ID, CLIENT_ID, REDIRECT_URI)
oAuth2Client.setCredentials({refresh_token: REFRESH_TOKEN})
const RegisterUser = async (req,res)=>{
try{
const {email, password, firstname, lastname} = req.body
const user = await UserModel.findOne({email})
if(user){
res.status(400).send("User already registered")
}else{
const OTP = otpGenerator.generate(6,{
digits: true, lowerCaseAlphabets: false, upperCaseAlphabets: false, specialChars: false
})
const accessToken = await oAuth2Client.getAccessToken()
const mailTransporter = nodemailer.createTransport({
service: "gmail",
auth: {
type: "OAUTH2",
user: "amberuteogenerojoshua#gmail.com",
clientId:CLIENT_ID,
clientSecret: CLIENT_SECRET,
refreshToken: REFRESH_TOKEN,
accessToken: accessToken
}})
let details = {
from: "Joshua Ogero Erute <amberuteogenerojoshua#gmail.com>",
to: req.body.email,
subject: "Verify your Email Account with Earli Finance",
html: OTP
}
mailTransporter.sendMail(details, (err)=>{
if(err){
console.log("It has an error", err)
}else{
console.log("Email has been sent successfully")
}
})
console.log(OTP)
const otp = new otpModel({
otp: OTP,
email: req.body.email
})
const salt = await bcrypt.genSalt(10)
otp.otp = await bcrypt.hash(otp.otp, salt)
const result = await otp.save()
res.status(201).send("OTP send successfully")
}
}catch(error){
res.status(404).json({message: error.message})
}

Related

How to solve client fetch error for next-auth authentication

I have created an app that connects to a mongodb cluster and stores user info. The user is then able to log in with Next-Auth functionality. The app was working just fine before deploying to Vercel. On the live site I ran into some Server Config Errors. I refractored my code yet I am still running into a few errors.
I am successfully able to connect to the database for a new user sign up.
import {
connectToDatabase,
hashedPassword,
} from "../../helper/HelperFunctions";
const isEmpty = (value) => value.trim() === "";
const isTenChars = (value) => value.trim().length >= 10;
const emailValidation = (value) => {
const pattern = /^[^ ]+#[^ ]+\.[a-z]{2,3}$/;
if (value.match(pattern)) {
return true;
} else {
return false;
}
};
export default async function handler(req, res) {
if (req.method == "POST") {
let data = req.body;
const { firstName, lastName, email, password, userName } = data;
const firstNameIsValid = !isEmpty(firstName);
const lastNameisValid = !isEmpty(lastName);
const emailIsValid = emailValidation(email);
const passwordisValid = isTenChars(password);
const userNameIsValid = !isEmpty(userName);
let userDataIsValid =
firstNameIsValid &&
lastNameisValid &&
emailIsValid &&
passwordisValid &&
userNameIsValid;
if (!userDataIsValid) {
return;
}
const client = await connectToDatabase();
const db = client.db();
const existingUser = await db.collection("users").findOne({ email: email });
if (existingUser) {
res.status(422).json({ message: "User already exists, please log in!" });
console.log("User already exists, please log in!");
client.close();
return;
}
const protectedPassword = await hashedPassword(password);
await db.collection("users").insertOne({
firstName: firstName,
lastName: lastName,
email: email,
password: protectedPassword,
userName: userName,
});
client.close();
res.status(201).json({ message: "Signed up!" });
} else {
res.status(200).json({ data: req.body });
}
}
Here is my nextauth api route
import NextAuth from "next-auth/next";
import CredentialsProvider from "next-auth/providers/credentials";
// Helper Functions
import {
connectToDatabase,
comparePasswords,
} from "../../../helper/HelperFunctions";
export default NextAuth({
session: { strategy: "jwt" },
providers: [
CredentialsProvider({
async authorize(credentials) {
const client = await connectToDatabase();
const userCollection = client.db().collection("users");
const user = await userCollection.findOne({
email: credentials.email,
});
if (!user) {
client.close();
throw new Error("No user found!");
}
const isValid = await comparePasswords(
credentials.password,
user.password
);
if (!isValid) {
client.close();
throw new Error("Invalid password");
}
client.close();
if (user) {
return {
email: user.email,
};
} else {
return null;
}
},
}),
],
});
Before I deployed my site on Vercel, this was working just fine on localhost. The user should then proceed to a new page if the result of logging in has no errors.
const result = await signIn("credentials", {
redirect: false,
email: form.email,
password: form.password,
});
if (!result.error) {
console.log(true);
router.replace("/suggestions");
} else {
console.log(result.error);
setLoginResult(result.error);
}
If you see CLIENT_FETCH_ERROR make sure you have configured the NEXTAUTH_URL environment variable.
when developing you set it to localhost:3000, now you need to set that to your deployed url.

sending email with emailJS when deployed on Heroku

I'm having trouble sending email with emailJS when deploying the site on heroku.
it works perfectly fine in development
the error says that the service id is invalid but i tested it and it works...
init("user_dvXegxEb11cRFMAuFpf6J");
const ContactScreen = () => {
const [name, setName] = useState('');
const [subject, setSubject] = useState('');
const [emailsender, setEmailsender] = useState('');
const [question, setQuestion] = useState('');
const templateParams = {
from_name: emailsender,
name: name,
to_name:"Yves",
subject: subject,
message: question
};
////SEND FORM TO EMAIL => 'emailjs'////
const sendMessage = (e) => {
e.preventDefault();
setName("");
setEmailsender("");
setSubject("");
setQuestion("");
emailjs.send(process.env.REACT_APP_SERVICE_ID,process.env.REACT_APP_TEMPLATE_ID,templateParams,process.env.REACT_APP_USER_ID)
.then(
function(response) {
toast.success("📩 Your message has successfully sent!", {
position: toast.POSITION.TOP_RIGHT,
pauseOnHover: true
})
console.log("SUCCESS!", response.status, response.text);
console.log(process.env.REACT_APP_SERVICE_ID);
},
function(err) {
toast.error("Your message was not able to be sent");
console.log(err);
})
};```

Cannot Make POST or GET Request with Express API

I am trying to test my API and I am not sure what I am doing wrong. The only error I am getting is cannot post. After some research, I am suspecting something wrong with my controller class.
This is my first real large project and I have created an API similar to this just with mongo but this is my first time using seqealize, and MySQL (with node).
The api/student/register router just won't post, but when I remove the controller and but a function that returns just plain JSON it works, that is why I really do believe it has something to do with my controller class.
contoller/student.controller.js
const bcrypt = require('bcrypt');
const jwt = require('jsonwebtoken');
require('dotenv').config();
const secret = process.env.SERCRET_KEY;
const db = require('../models/index.js');
const Student = db.Student;
class StudentContoller {
static registerStudent(req, res) {
try {
let {
first_name,
last_name,
email,
password,
phone,
shirt_size,
grade,
teacher,
} = req.body;
Student.findAll({
where: {
email : email,
is_Archived: false,
}
})
.then(result => {
if (result.length > 0){
res.status(400).json({ message: 'Email is already registerd'});
} else {
let hashPassword = bcrypt.hashSync(password, 10);
let newStudent = {
first_name,
last_name,
email,
password: hashPassword,
phone,
shirt_size,
grade,
teacher,
school_id,
}
Student.Create(newStudent)
.then(data => {
if(data){
res.status(201).json({message: 'Student Created', student: data })
}
})
.catch(err => res.json({error : err.message}));
}
})
} catch (e) {
res.status(500).json({error: 'error caused in regiserted controller'})
}
}
static async login(req, res) {
let { email, password, } = req.body;
await Student.findAll({
where: {
email: email,
is_Archived: false,
}
})
.then(student => {
if(student.length === 0){
res.status(400).json({ message: 'Sorry, account does not exsist'})
} else {
let passwordIsValid = bcrypt.compareSync(req.body.password, student[0].password.trim());
if (passwordIsValid) {
let studentDetails = {
id: student[0].dataValues.id,
first_name: student[0].first_name,
last_name: student[0].last_name,
}
let token = jwt.sign({
student: studentDetails,
}, secret, {
expiresIn: '1d'
});
res.status(200).json({
success: true,
student: studentDetails,
message: 'Login successfull',
token: token,
});
} else {
res.status(401).json({
success: false,
message: 'Login failed',
});
}
}
})
.catch(err => res.status(500).json({error: err.message}));
}
static async updateStudent(req, res) {
try {
const {
first_name,
last_name,
email,
password,
phone,
shirt_size,
grade,
teacher,
} = req.body;
let hashpassword = bcrypt.hashSync(password, 10);
let updateStudent = {
first_name,
last_name,
email,
password : hashpassword,
phone,
shirt_size,
grade,
teacher,
}
Student.update(updateStudent, {
where: {
id: req.params.id
}
})
.then(response => {
res.status(200).json({success: true, message: "Student updated successfully"})
})
.then(err => res.json({err: err.message}));
} catch (e) {
res.status(500).json({ error: e});
}
}
static async archiveStudent(req, res) {
try{
let id = req.params.id
await Student.findAll({
where: {id: id}
})
.then(result => {
if (result.length == 1){
Student.update(
{is_Archived: true},
{ where: {id: id}}
)
}
})
} catch (e) {
res.status(500).json({ error: e});
}
}
}
module.exports = StudentContoller;
student.routs.js
const express = require('express');
const router = express.Router();
const jwt = require('jsonwebtoken');
const checkJWT = require('../middlewares/check-token');
const StudentController = require('../controllers/student.controller');
//
//
router.get('student/login', StudentController.login);
router.post('student/register', checkJWT,StudentController.registerStudent);
module.exports = router;
Sever js
const express = require('express');
const bodyParser = require('body-parser');
const cors = require('cors');
const morgan = require('morgan');
const helmet = require('helmet');
const app = express();
// Middlewars
app.use(cors()); // Enable Cors
app.use(morgan('dev')); // Enable Logging
app.use(helmet()); // Enables Security Headers
app.use(bodyParser.json()); // Parses requrests of type application/json
app.use(bodyParser.urlencoded({ extended: true})); // Parses request of application/x-www-form-urlencode
//Add database connection
const db = require('./models');
//db.sequelize.sync().then(()=> initial())
// Routing
app.get('/', (req, res)=> res.json({message: "Base API URL"}));
const studnetRoute = require('./routes/student.routes');
app.use('/', studnetRoute);
const PORT = process.env.PORT || 3300;
app.listen(PORT, () => console.log(`Server Running on port ${PORT}`));
you can do like this in your router file .
router.route('student/login')
.get(StudentController.login);
router.route('student/register')
.post(checkJWT, StudentController.registerStudent);

req.session.user gives 'undifined' as output

I am implementing a login authentication program in MERN stack.
When I enter correct user name and password, login function works fine.
There are some components which can be displayed only if the client is logged in. Therefore, to validate the client I have implemented authenticator function in the server which should return success message along with the session object.
Once I try to authenticate, req.session.user gives the output as 'undefined'. I referred several similar questions but couldn't solve my issue.How can I solve this issue?
Login function,
router.post('/login', (req, res) => {
const email = req.body.email;
const password = req.body.password;
if (!email || !password) {
return res.status(400).json({ msg: "Please enter all fields" });
}
//Find user
User.findOne({ email : email })
.then(user => {
if(!user){
console.log('Not a user')
}
//Password matching
bcrypt.compare(password, user.password, (err, isMatch) => {
if(err) throw err;
if(isMatch){
console.log('Logged in')
const userSession = {
id: user.id,
name : user.name,
email : user.email
};
req.session.user = userSession;
res.json({ msg: "Logged in successfully", userSession});
} else {
console.log('Incorrect username or password')
}
});
})
.catch(err => console.log(err));
});
server.js,
const express = require('express');
const expressLayouts = require('express-ejs-layouts');
const mongoose = require('mongoose');
const passport = require('passport');
const flash = require('connect-flash');
const session = require('express-session');
const cors = require('cors');
const MongoDBStore = require('connect-mongodb-session')(session);
const app = express();
const router = express.Router();
const {IS_PROD} = require('./config/config');
const MAX_AGE = 1000 * 60 * 2;
mongoose.connect("mongodb+srv://root:admin#cluster0-ynman.gcp.mongodb.net/test?retryWrites=true&w=majority", {useNewUrlParser:true, useCreateIndex:true, useUnifiedTopology:true})
.then(() => console.log('Mongo DB Connected'))
.catch(err => console.log(err));
//setting up connect-mongodb-session store
const mongoDBStore = new MongoDBStore({
uri: "mongodb+srv://root:admin#cluster0-ynman.gcp.mongodb.net/test?retryWrites=true&w=majority",
collection : "mySession"
})
//Bodyparser
app.use(express.urlencoded({extended:false}));
app.use(cors());
app.use(express.json());
//Express Session
app.use(session({
name: 'session',
secret: 'secret',
resave: true,
saveUninitialized: false,
store : mongoDBStore,
cookie :{
path : '/',
httpOnly: false,
maxAge : MAX_AGE,
sameSite: false,
secure : IS_PROD
}
}));
//Routes
app.use('/', require('./routes/index'));
app.use('/users', require('./routes/users'));
const PORT = process.env.PORT || 5000;
app.listen(PORT, console.log(`Server starts on port ${PORT}`));
Authenticate funtion,
router.get("/authenticator", (req, res) => {
const userSession = req.session.user;
console.log(userSession);
if(userSession){
return res.json({msg : "Authenticated successfully", userSession});
} else {
return res.status(401).json({msg : "Unauthorized"});
}
});

Passport: Error: passport.initialize() middleware not in use;

I'm have an express server with MongoDB and Mongoose, and using passport to authenticate with JWT, but getting an error as in the title.
I'm following the passport-jwt documentation, but am still getting the error. What am I doing wrong?
Here is the error message when doing GET call on localhost3090 with a valid JWT:
::1 - - [16/Mar/2018:05:35:47 +0000] "GET / HTTP/1.1" 500 1677 "-" "PostmanRuntime/7.1.1"
Error: passport.initialize() middleware not in use
at IncomingMessage.req.login.req.logIn (/Users/okadachikara/react-courses/projects/server/node_modules/passport/lib/http/request.js:46:34)
at JwtStrategy.strategy.success (/Users/okadachikara/react-courses/projects/server/node_modules/passport/lib/middleware/authenticate.js:248:13)
at verified (/Users/okadachikara/react-courses/projects/server/node_modules/passport-jwt/lib/strategy.js:115:41)
at /Users/okadachikara/react-courses/projects/server/services/passport.js:34:7
at /Users/okadachikara/react-courses/projects/server/node_modules/mongoose/lib/model.js:3930:16
at _init (/Users/okadachikara/react-courses/projects/server/node_modules/mongoose/lib/query.js:2007:5)
at model.Document.init (/Users/okadachikara/react-courses/projects/server/node_modules/mongoose/lib/document.js:393:5)
at completeOne (/Users/okadachikara/react-courses/projects/server/node_modules/mongoose/lib/query.js:1993:12)
at Immediate.<anonymous> (/Users/okadachikara/react-courses/projects/server/node_modules/mongoose/lib/query.js:1520:11)
at Immediate._onImmediate (/Users/okadachikara/react-courses/projects/server/node_modules/mquery/lib/utils.js:119:16)
at runCallback (timers.js:773:18)
at tryOnImmediate (timers.js:734:5)
at processImmediate [as _immediateCallback] (timers.js:711:5)
My server/controllers/authentication.js:
const User = require('../models/user');
const jwt = require('jwt-simple');
const config = require('../config');
function tokenForUser(user) {
const timestamp = new Date().getTime();
return jwt.encode({ sub: user.id, iat: timestamp }, config.secret);
}
exports.signup = function (req, res, next) {
const email = req.body.email;
const password = req.body.password;
if (!email || !password) {
return res.status(422).send({ error: 'You must provide an email and
password' });
}
// see if user with the given email exists
User.findOne({ email: email }, function (err, existingUser) {
if (err) { return next(err); }
if (existingUser) {
return res.status(422).send({ error: 'A user with that email
already exists' });
}
const user = new User({
email: email,
password: password
});
user.save(function (err) {
if (err) { return next(err); }
res.json({ token: tokenForUser(user), iat: jwt.iat });
});
});
};
My server/services/passport.js
const passport = require('passport');
const JwtStrategy = require('passport-jwt').Strategy;
const ExtractJwt = require('passport-jwt').ExtractJwt;
const User = require('../models/user');
const config = require('../config');
const jwtOptions = {
jwtFromRequest: ExtractJwt.fromHeader('authorization'),
secretOrKey: config.secret
};
const jwtLogin = new JwtStrategy(jwtOptions, function (payload, done) {
User.findById(payload.sub, function (err, user) {
if (err) { return done(err, false); }
if (user) {
done(null, user);
} else {
done(null, false);
}
});
});
passport.use(jwtLogin);
My server/router.js
const passport = require('passport');
const Authentication = require('./controllers/authentication');
const passportService = require('./services/passport');
const requireAuth = passport.authenticate('jwt', { sesssion: false });
module.exports = function (app) {
app.get('/', requireAuth, function (req, res) {
res.send({ hi: 'there' });
});
app.post('/signup', Authentication.signup);
};
You need to initialize the passport module before using it:
let app = express();
app.use(passport.initialize());