Skip to content

Instantly share code, notes, and snippets.

@FBosler
Last active January 19, 2023 11:19
Show Gist options
  • Save FBosler/513a0f5f845fbf6e937ab768ed88e183 to your computer and use it in GitHub Desktop.
Save FBosler/513a0f5f845fbf6e937ab768ed88e183 to your computer and use it in GitHub Desktop.
Backend
const express = require("express");
const router = express.Router();
const passport = require("passport");
router.post("/register_login", (req, res, next) => {
passport.authenticate("local", function(err, user, info) {
if (err) {
return res.status(400).json({ errors: err });
}
if (!user) {
return res.status(400).json({ errors: "No user found" });
}
req.logIn(user, function(err) {
if (err) {
return res.status(400).json({ errors: err });
}
return res.status(200).json({ success: `logged in ${user.id}` });
});
})(req, res, next);
});
module.exports = router;
const express = require("express");
const app = express();
const port = 3000;
app.get("/", (req, res) => res.send("Hello World!"));
app.listen(port, () => console.log(`Example app listening on port ${port}!`));
{
"name": "social-login-root-folder",
"version": "1.0.0",
"description": "This is the root project for our frontend and backend",
"main": "index.js",
"repository": "https://github.com/FBosler/fb-tutorial-social-login",
"author": "Fabian Bosler",
"license": "MIT",
"private": true,
"scripts": {
"dev-start": "concurrently \"cd server && yarn nodemon server.js\" \"cd client && yarn start\""
},
"devDependencies": {
"concurrently": "^5.1.0"
}
}
const bcrypt = require("bcryptjs");
const User = require("../models/Users");
const passport = require("passport");
const LocalStrategy = require("passport-local").Strategy;
passport.serializeUser((user, done) => {
done(null, user.id);
});
passport.deserializeUser((id, done) => {
User.findById(id, (err, user) => {
done(err, user);
});
});
// Local Strategy
passport.use(
new LocalStrategy({ usernameField: "email" }, (email, password, done) => {
// Match User
User.findOne({ email: email })
.then(user => {
// Create new User
if (!user) {
const newUser = new User({ email, password });
// Hash password before saving in database
bcrypt.genSalt(10, (err, salt) => {
bcrypt.hash(newUser.password, salt, (err, hash) => {
if (err) throw err;
newUser.password = hash;
newUser
.save()
.then(user => {
return done(null, user);
})
.catch(err => {
return done(null, false, { message: err });
});
});
});
// Return other user
} else {
// Match password
bcrypt.compare(password, user.password, (err, isMatch) => {
if (err) throw err;
if (isMatch) {
return done(null, user);
} else {
return done(null, false, { message: "Wrong password" });
}
});
}
})
.catch(err => {
return done(null, false, { message: err });
});
})
);
module.exports = passport;
const express = require("express");
const session = require("express-session");
const MongoStore = require("connect-mongo")(session);
const mongoose = require("mongoose");
const passport = require("./passport/setup");
const auth = require("./routes/auth");
const app = express();
const PORT = 5000;
const MONGO_URI = "mongodb://127.0.0.1:27017/tutorial_social_login";
mongoose
.connect(MONGO_URI, { useNewUrlParser: true })
.then(console.log(`MongoDB connected ${MONGO_URI}`))
.catch(err => console.log(err));
// Bodyparser middleware, extended false does not allow nested payloads
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
// Express Session
app.use(
session({
secret: "very secret this is",
resave: false,
saveUninitialized: true,
store: new MongoStore({ mongooseConnection: mongoose.connection })
})
);
// Passport middleware
app.use(passport.initialize());
app.use(passport.session());
// Routes
app.use("/api/auth", auth);
app.get("/", (req, res) => res.send("Good monring sunshine!"));
app.listen(PORT, () => console.log(`Backend listening on port ${PORT}!`));
import React, { useState } from "react";
import { Modal, Form, Col, Row } from "react-bootstrap";
import axios from "axios";
import DelegatedAuthList from "../DelegatedAuthList";
import {
PaddedContainer,
EmailSymbol,
PasswordSymbol,
ResponsiveHeader4,
MutedSpan,
VerticalCenterWrapper,
SubmitButtom
} from "./styles";
const SignUpLoginForm = () => {
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const onSubmit = e => {
e.preventDefault();
const userData = {
email,
password
};
axios
.post("/api/auth/register_login", userData)
.then(res => {
console.log(res);
})
.catch(err => {
console.log(err);
console.log(err.response);
});
};
return (
<Form onSubmit={onSubmit}>
<Form.Group controlId="formBasicEmail">
<Row>
<Form.Label column xs="2" sm="1">
<EmailSymbol />
</Form.Label>
<Col xs="10" sm="11">
<Form.Control
type="email"
placeholder="Enter email"
onChange={e => {
setEmail(e.target.value);
console.log(email);
}}
required
/>
<Form.Control.Feedback>Looks good!</Form.Control.Feedback>
<Form.Text className="text-muted">We'll never share your email with anyone else.</Form.Text>
</Col>
</Row>
</Form.Group>
<Form.Group controlId="formBasicPassword">
<Row>
<Form.Label column xs="2" sm="1">
<PasswordSymbol />
</Form.Label>
<Col xs="10" sm="11">
<Form.Control
type="password"
placeholder="Password"
onChange={e => setPassword(e.target.value)}
/>
<Form.Control.Feedback>Looks good!</Form.Control.Feedback>
</Col>
</Row>
</Form.Group>
<Form.Group controlId="formBasicCheckbox">
<Row>
<Col xs="2" sm="1">
<Form.Check type="checkbox" />
</Col>
<Col xs="10" sm="11">
<Form.Label>
<MutedSpan>
I hereby confirm that the referral app is allowed to send me emails, up until I
unsuscribe
</MutedSpan>
</Form.Label>
</Col>
</Row>
</Form.Group>
<VerticalCenterWrapper>
<SubmitButtom type="submit">Submit</SubmitButtom>
</VerticalCenterWrapper>
</Form>
);
};
const SignupLoginModal = props => {
return (
<Modal show={props.show} onHide={() => props.setShow(false)}>
<Modal.Header closeButton>
<Modal.Title>Sign up / Login</Modal.Title>
</Modal.Header>
<PaddedContainer>
<ResponsiveHeader4>With email:</ResponsiveHeader4>
<br />
<SignUpLoginForm />
<Row style={{ borderBottom: "1px solid #dee2e6" }} />
<ResponsiveHeader4>Or with your favorite third party provider:</ResponsiveHeader4>
<br />
<DelegatedAuthList />
</PaddedContainer>
</Modal>
);
};
export default SignupLoginModal;
const mongoose = require("mongoose");
const ThirdPartyProviderSchema = new mongoose.Schema({
provider_name: {
type: String,
default: null
},
provider_id: {
type: String,
default: null
},
provider_data: {
type: {},
default: null
}
})
// Create Schema
const UserSchema = new mongoose.Schema(
{
name: {
type: String
},
email: {
type: String,
required: true,
unique: true
},
email_is_verified: {
type: Boolean,
default: false
},
password: {
type: String
},
referral_code: {
type: String,
default: function() {
let hash = 0;
for (let i = 0; i < this.email.length; i++) {
hash = this.email.charCodeAt(i) + ((hash << 5) - hash);
}
let res = (hash & 0x00ffffff).toString(16).toUpperCase();
return "00000".substring(0, 6 - res.length) + res;
}
},
referred_by: {
type: String,
default: null
},
third_party_auth: [ThirdPartyProviderSchema],
date: {
type: Date,
default: Date.now
}
},
{ strict: false }
);
module.exports = User = mongoose.model("users", UserSchema);
@alberto56
Copy link

node_1   | const MongoStore = require("connect-mongo")(session);
node_1   |                                            ^
node_1   | 
node_1   | TypeError: Class constructor MongoStore cannot be invoked without 'new'

A fix can be found at https://www.npmjs.com/package/connect-mongo

@JIBSIL
Copy link

JIBSIL commented May 19, 2021

Note: change the mongoose section of server.js to make it work like so:


mongoose
    .connect(MONGO_URI, { useNewUrlParser: true, useUnifiedTopology: true})
    .then(console.log(`MongoDB connected ${MONGO_URI}`))
    .catch(err => console.log(err));

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment