Bläddra i källkod

Added GitHub authentication.

KrisVos130 8 år sedan
förälder
incheckning
0115d0e0c4

+ 3 - 1
backend/config/template.json

@@ -1,6 +1,7 @@
 {
 	"secret": "",
 	"domain": "",
+	"serverDomain": "",
   	"isDocker": true,
 	"apis": {
 		"youtube": {
@@ -11,7 +12,8 @@
 		},
 		"github": {
 			"client": "",
-			"secret": ""
+			"secret": "",
+			"redirect_uri": ""
 		},
 		"discord": {
 			"client": "",

+ 3 - 1
backend/logic/actions/users.js

@@ -64,6 +64,7 @@ module.exports = {
 	},
 
 	register: function(session, username, email, password, recaptcha, cb) {
+		email = email.toLowerCase();
 		async.waterfall([
 
 			// verify the request with google recaptcha
@@ -83,7 +84,7 @@ module.exports = {
 			(/*response, body, */next) => {
 				/*let json = JSON.parse(body);*/
 				//if (json.success !== true) return next('Response from recaptcha was not successful');
-				db.models.user.findOne({ username }, next);
+				db.models.user.findOne({ username: new RegExp(`^${username}$`, 'i') }, next);
 			},
 
 			// if the user already exists, respond with that
@@ -123,6 +124,7 @@ module.exports = {
 
 			// respond with the new user
 			(newUser, next) => {
+				//TODO Send verification email
 				next(null, { status: 'success', user: newUser })
 			}
 

+ 112 - 0
backend/logic/app.js

@@ -6,6 +6,13 @@ const express = require('express');
 const bodyParser = require('body-parser');
 const cors = require('cors');
 const config = require('config');
+const request = require('request');
+const cache = require('./cache');
+const db = require('./db');
+let utils;
+const OAuth2 = require('oauth').OAuth2;
+
+
 
 const lib = {
 
@@ -14,6 +21,8 @@ const lib = {
 
 	init: (cb) => {
 
+		utils = require('./utils');
+
 		let app = lib.app = express();
 
 		lib.server = app.listen(80);
@@ -26,6 +35,109 @@ const lib = {
 		app.use(cors(corsOptions));
 		app.options('*', cors(corsOptions));
 
+		let oauth2 = new OAuth2(
+			config.get("apis.github.client"),
+			config.get("apis.github.secret"),
+			'https://github.com/',
+			'login/oauth/authorize',
+			'login/oauth/access_token',
+			null
+		);
+
+		let redirect_uri = config.get("serverDomain") + "/auth/github/authorize/callback";
+
+		app.get('/auth/github/authorize', (req, res) => {
+			let params = [
+				`client_id=${config.get("apis.github.client")}`,
+				`redirect_uri=http://localhost/auth/github/authorize/callback`,
+				`scope=user:email`
+			].join('&');
+			res.redirect(`https://github.com/login/oauth/authorize?${params}`);
+		});
+
+		app.get('/auth/github/authorize/callback', (req, res) => {
+			let code = req.query.code;
+			oauth2.getOAuthAccessToken(code, {'redirect_uri': redirect_uri}, (error, access_token, refresh_token, results) => {
+				if (!error) {
+					request.get({
+						url: `https://api.github.com/user?access_token=${access_token}`,
+						headers: {'User-Agent': 'request'}
+					}, (error, httpResponse, body) => {
+						if (error) return res.redirect(`http://localhost:8080/?err=${encodeURIComponent("Something went wrong while logging in1.")}`);
+						body = JSON.parse(body);
+						db.models.user.findOne({"services.github.id": body.id}, (err, user) => {
+							if (err) return res.redirect(`http://localhost:8080/?err=${encodeURIComponent("Something went wrong while logging in2.")}`);
+							if (user) {
+								user.services.github.access_token = access_token;
+								user.save((err) => {
+									if (err) return res.redirect(`http://localhost:8080/?err=${encodeURIComponent("Something went wrong while logging in3.")}`);
+									let userSessionId = utils.guid();
+									cache.hset('userSessions', userSessionId, cache.schemas.userSession(user._id), (err) => {
+										if (err) return res.redirect(`http://localhost:8080/?err=${encodeURIComponent("Something went wrong while logging in3.")}`);
+										res.cookie("SID", userSessionId);
+										res.redirect(`http://localhost:8080/`);
+									});
+								});
+							} else {
+								db.models.user.findOne({username: new RegExp(`^${body.login}$`, 'i')}, (err, user) => {
+									if (err) return res.redirect(`http://localhost:8080/?err=${encodeURIComponent("Something went wrong while logging in4.")}`);
+									if (user) {
+										res.redirect(`http://localhost:8080/?err=${encodeURIComponent("Something went wrong while logging in5.")}`);
+									} else {
+										request.get({
+											url: `https://api.github.com/user/emails?access_token=${access_token}`,
+											headers: {'User-Agent': 'request'}
+										}, (error, httpResponse, body2) => {
+											if (error) return res.redirect(`http://localhost:8080/?err=${encodeURIComponent("Something went wrong while logging in6.")}`);
+											body2 = JSON.parse(body2);
+											let primaryEmail;
+											body2.forEach((email) => {
+												if (email.primary) {
+													primaryEmail = email.email.toLowerCase();
+												}
+											});
+											db.models.user.findOne({"email.address": primaryEmail}, (err, user) => {
+												if (err) return res.redirect(`http://localhost:8080/?err=${encodeURIComponent("Something went wrong while logging in7.")}`);
+												if (user) {
+													if (err) return res.redirect(`http://localhost:8080/?err=${encodeURIComponent("Something went wrong while logging in8.")}`);
+												} else {
+													db.models.user.create({
+														username: body.login,
+														email: {
+															address: primaryEmail,
+															verificationToken: utils.generateRandomString(64)
+														},
+														services: {
+															github: {
+																id: body.id,
+																access_token: access_token
+															}
+														}
+													}, (err, user) => {
+														if (err) return res.redirect(`http://localhost:8080/?err=${encodeURIComponent("Something went wrong while logging in9.")}`);
+														//TODO Send verification email
+														let userSessionId = utils.guid();
+														cache.hset('userSessions', userSessionId, cache.schemas.userSession(user._id), (err) => {
+															if (err) return res.redirect(`http://localhost:8080/?err=${encodeURIComponent("Something went wrong while logging in3.")}`);
+															res.cookie("SID", userSessionId);
+															res.redirect(`http://localhost:8080/`);
+														});
+													});
+												}
+											});
+										});
+									}
+								});
+							}
+						});
+					});
+
+				} else {
+					res.redirect(`http://localhost:8080/?err=${encodeURIComponent("Something went wrong while logging in2.")}`);
+				}
+			});
+		});
+
 		cb();
 	}
 };

+ 3 - 0
backend/logic/db/schemas/user.js

@@ -9,6 +9,9 @@ module.exports = {
 	services: {
 		password: {
 			password: String
+		},
+		github: {
+			id: Number,
 		}
 	},
 	ban: {

+ 1 - 0
backend/package.json

@@ -22,6 +22,7 @@
     "express-session": "^1.14.0",
     "moment": "^2.15.2",
     "mongoose": "^4.6.0",
+    "oauth": "^0.9.14",
     "passport": "^0.3.2",
     "passport-discord": "^0.1.1",
     "passport-github": "^1.1.0",

+ 5 - 1
frontend/App.vue

@@ -33,7 +33,8 @@
 				role: '',
 				username: '',
 				isRegisterActive: false,
-				isLoginActive: false
+				isLoginActive: false,
+				serverDomain: ''
 			}
 		},
 		methods: {
@@ -62,6 +63,9 @@
 				_this.role = role;
 				_this.username = username;
 			});
+			lofig.get("serverDomain", (res) => {
+				_this.serverDomain = res;
+			});
 		},
 		events: {
 			'register': function () {

+ 2 - 1
frontend/build/config/template.json

@@ -4,5 +4,6 @@
 	},
 	"recaptcha": {
 		"key": ""
-	}
+	},
+  	"serverDomain": ""
 }

+ 1 - 1
frontend/components/Modals/Login.vue

@@ -18,7 +18,7 @@
 				</p>
 			</section>
 			<footer class="modal-card-foot">
-				<a class="button is-primary" @click="submitModal('login')">Submit</a>
+				<a class="button is-primary" @click="submitModal('login')">Submit</a><a class="button is-primary" v-bind:href="$parent.serverDomain + '/auth/github/authorize'">Log in in GitHub</a>
 			</footer>
 		</div>
 	</div>

+ 1 - 1
frontend/components/Modals/Register.vue

@@ -23,7 +23,7 @@
 				<div class="g-recaptcha" :data-sitekey="recaptcha.key"></div>
 			</section>
 			<footer class="modal-card-foot">
-				<a class="button is-primary" @click="submitModal()">Submit</a>
+				<a class="button is-primary" @click="submitModal()">Submit</a><a class="button is-primary" v-bind:href="$parent.serverDomain + '/auth/github/authorize'">Register in GitHub</a>
 			</footer>
 		</div>
 	</div>