From 5e3dd46a37c24734e590e250776b769432fd17fc Mon Sep 17 00:00:00 2001 From: Roman-hal <85693082+Roman-Hal@users.noreply.github.com> Date: Sun, 7 May 2023 09:59:57 +0100 Subject: [PATCH] added_login_logic_frontend_backend added oauth2 login logic for the front end and backend. Some corrections to the frontend. --- client/src/App.js | 58 +++++++-- client/src/Components/Header.js | 23 ++-- client/src/Components/ProfileIcone.js | 16 ++- client/src/pages/Home.js | 4 +- client/src/pages/LandingPage.js | 12 +- package-lock.json | 172 ++++++++++++++++++++++++++ package.json | 3 + server/api.js | 45 +++++++ server/app.js | 18 ++- server/passport.js | 40 ++++++ 10 files changed, 356 insertions(+), 35 deletions(-) create mode 100644 server/passport.js diff --git a/client/src/App.js b/client/src/App.js index 15e8d4d..b3cbb21 100644 --- a/client/src/App.js +++ b/client/src/App.js @@ -1,4 +1,5 @@ import { Route, Routes } from "react-router-dom"; +import { useEffect, useState } from "react"; import About from "./pages/About"; import Home from "./pages/Home"; @@ -7,17 +8,50 @@ import History from "./pages/History"; // import Header from "./Components/Header"; // import Footer from "./Components/Footer"; -const App = () => ( -
- {/*
*/} - - } /> - } /> - } /> - } /> - - {/*
-); +const App = () => { + const [user, setUser] = useState(); + + useEffect(() => { + const fetchUser = async () => { + try { + const response = await fetch( + "http://localhost:3000/api/auth/login/success" ?? + "/api/auth/login/success", + { + method: "GET", + credentials: "include", + headers: { + Accept: "application/json", + "Content-type": "application/json", + "Access-Control-Allow-Credentials": true, + }, + } + ); + const json = await response.json(); + const result = json; + //console.log(result); + //console.log("hey"); + setUser(result); + } catch (error) { + //console.log("error", error); + return error; + } + }; + fetchUser(); + }, []); + + return ( +
+ {/*
*/} + + } /> + } /> + } /> + } /> + + {/*
+ ); +}; export default App; diff --git a/client/src/Components/Header.js b/client/src/Components/Header.js index 1867de9..0ba1c7c 100644 --- a/client/src/Components/Header.js +++ b/client/src/Components/Header.js @@ -1,9 +1,9 @@ import React from "react"; import logo from "../assets/cyf_brand.png"; -import { Navbar, Button, Col } from "react-bootstrap"; +import { Navbar, Button, Col, Card } from "react-bootstrap"; import ProfileIcone from "./ProfileIcone"; //header component -const Header = () => { +const Header = ({ user }) => { return ( <> @@ -21,7 +21,10 @@ const Header = () => { xxl={2} className="ms-auto justify-content-end d-flex" > - + {user ? ( + {user.username} + ) : null} +
{ gridTemplateColumns: "1fr 4fr 1fr", }} > -
-
- Our all-in-one writing helper tool is designed to reduce mistake, - improve grammar and suggest phrases -
+ + +
+
+ Our all-in-one writing helper tool is designed to reduce mistake, + improve grammar and suggest phrases +
+
+ { +const ProfileIcone = ({ user }) => { const [show, setShow] = useState(false); + const logout = () => { + window.open("http://localhost:3000/api/auth/logout", "_self"); + }; + return ( <> + {user ? ( + + ) : null} diff --git a/client/src/pages/Home.js b/client/src/pages/Home.js index 275efe3..96136f4 100644 --- a/client/src/pages/Home.js +++ b/client/src/pages/Home.js @@ -10,7 +10,7 @@ import MainContent from "../Components/MainContent"; import "./Home.css"; // import logo from "./logo.svg"; //import for a logo -export function Home() { +export function Home({ user }) { /* const [val, setVal] = useState(""); const [content, setContent] = useState("");*/ /*const [message, setMessage] = useState("Loading..."); @@ -73,7 +73,7 @@ export function Home() { return (
-
+
{/*

Hello World

this the label
diff --git a/client/src/pages/LandingPage.js b/client/src/pages/LandingPage.js index 9488725..5547e57 100644 --- a/client/src/pages/LandingPage.js +++ b/client/src/pages/LandingPage.js @@ -4,6 +4,10 @@ import Footer from "../Components/Footer"; import TeamLogo from "../assets/TeamLogo.png"; import Header from "../Components/Header"; const LandingPage = () => { + const github = () => { + window.open("http://localhost:3000/api/auth/github", "_self"); + }; + return ( <>
@@ -22,14 +26,14 @@ const LandingPage = () => { Welcome to TOOT -
- Log in with your GitHub account to
continue -
+ Log in with your GitHub account to
continue
diff --git a/package-lock.json b/package-lock.json index 8072dba..4306d2a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,6 +11,7 @@ "dependencies": { "@babel/runtime": "^7.21.0", "bootstrap": "^5.2.3", + "cookie-parser": "^1.4.6", "cookie-session": "^2.0.0", "cors": "^2.8.5", "dotenv": "^16.0.3", @@ -19,6 +20,8 @@ "knex": "^2.4.2", "morgan": "^1.10.0", "openai": "^3.2.1", + "passport": "^0.6.0", + "passport-github2": "^0.1.12", "pg": "^8.9.0", "react-bootstrap": "^2.7.4", "react-icons": "^4.8.0", @@ -3449,6 +3452,14 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, + "node_modules/base64url": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/base64url/-/base64url-3.0.1.tgz", + "integrity": "sha512-ir1UPr3dkwexU7FdV8qBBbNDRUhMmIekYMFZfi+C/sLNnRESKPl23nB9b2pltqfOQNnGzsDdId90AEtG5tCx4A==", + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/basic-auth": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", @@ -4170,6 +4181,26 @@ "node": ">= 0.6" } }, + "node_modules/cookie-parser": { + "version": "1.4.6", + "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.6.tgz", + "integrity": "sha512-z3IzaNjdwUC2olLIB5/ITd0/setiaFMLYiZJle7xg5Fe9KWAceil7xszYfHHBtDFYLSgJduS2Ty0P1uJdPDJeA==", + "dependencies": { + "cookie": "0.4.1", + "cookie-signature": "1.0.6" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/cookie-parser/node_modules/cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/cookie-session": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/cookie-session/-/cookie-session-2.0.0.tgz", @@ -8505,6 +8536,11 @@ "integrity": "sha512-90yv+6538zuvUMnN+zCr8LuV6bPFdq50304114vJYJ8RDyK8D5O9Phpbd6SZWgI7PwzmmfN1upeOJlvybDSgCw==", "dev": true }, + "node_modules/oauth": { + "version": "0.9.15", + "resolved": "https://registry.npmjs.org/oauth/-/oauth-0.9.15.tgz", + "integrity": "sha512-a5ERWK1kh38ExDEfoO6qUHJb32rd7aYmPHuyCu3Fta/cnICvYmgd2uhuKXvPD+PXB+gCEYYEaQdIRAjCOwAKNA==" + }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -8902,6 +8938,61 @@ "tslib": "^2.0.3" } }, + "node_modules/passport": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/passport/-/passport-0.6.0.tgz", + "integrity": "sha512-0fe+p3ZnrWRW74fe8+SvCyf4a3Pb2/h7gFkQ8yTJpAO50gDzlfjZUZTO1k5Eg9kUct22OxHLqDZoKUWRHOh9ug==", + "dependencies": { + "passport-strategy": "1.x.x", + "pause": "0.0.1", + "utils-merge": "^1.0.1" + }, + "engines": { + "node": ">= 0.4.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/jaredhanson" + } + }, + "node_modules/passport-github2": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/passport-github2/-/passport-github2-0.1.12.tgz", + "integrity": "sha512-3nPUCc7ttF/3HSP/k9sAXjz3SkGv5Nki84I05kSQPo01Jqq1NzJACgMblCK0fGcv9pKCG/KXU3AJRDGLqHLoIw==", + "dependencies": { + "passport-oauth2": "1.x.x" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/passport-oauth2": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/passport-oauth2/-/passport-oauth2-1.7.0.tgz", + "integrity": "sha512-j2gf34szdTF2Onw3+76alNnaAExlUmHvkc7cL+cmaS5NzHzDP/BvFHJruueQ9XAeNOdpI+CH+PWid8RA7KCwAQ==", + "dependencies": { + "base64url": "3.x.x", + "oauth": "0.9.x", + "passport-strategy": "1.x.x", + "uid2": "0.0.x", + "utils-merge": "1.x.x" + }, + "engines": { + "node": ">= 0.4.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/jaredhanson" + } + }, + "node_modules/passport-strategy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz", + "integrity": "sha512-CB97UUvDKJde2V0KDWWB3lyf6PC3FaZP7YxZ2G8OAtn9p4HI9j9JLP9qjOGZFvyl8uwNT8qM+hGnz/n16NI7oA==", + "engines": { + "node": ">= 0.4.0" + } + }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -8948,6 +9039,11 @@ "node": ">=8" } }, + "node_modules/pause": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", + "integrity": "sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg==" + }, "node_modules/pg": { "version": "8.9.0", "resolved": "https://registry.npmjs.org/pg/-/pg-8.9.0.tgz", @@ -10901,6 +10997,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/uid2": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/uid2/-/uid2-0.0.4.tgz", + "integrity": "sha512-IevTus0SbGwQzYh3+fRsAMTVVPOoIVufzacXcHPmdlle1jUpq7BRL+mw3dgeLanvGZdwwbWhRV6XrcFNdBmjWA==" + }, "node_modules/unbox-primitive": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", @@ -14280,6 +14381,11 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, + "base64url": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/base64url/-/base64url-3.0.1.tgz", + "integrity": "sha512-ir1UPr3dkwexU7FdV8qBBbNDRUhMmIekYMFZfi+C/sLNnRESKPl23nB9b2pltqfOQNnGzsDdId90AEtG5tCx4A==" + }, "basic-auth": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", @@ -14816,6 +14922,22 @@ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==" }, + "cookie-parser": { + "version": "1.4.6", + "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.6.tgz", + "integrity": "sha512-z3IzaNjdwUC2olLIB5/ITd0/setiaFMLYiZJle7xg5Fe9KWAceil7xszYfHHBtDFYLSgJduS2Ty0P1uJdPDJeA==", + "requires": { + "cookie": "0.4.1", + "cookie-signature": "1.0.6" + }, + "dependencies": { + "cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==" + } + } + }, "cookie-session": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/cookie-session/-/cookie-session-2.0.0.tgz", @@ -18017,6 +18139,11 @@ "integrity": "sha512-90yv+6538zuvUMnN+zCr8LuV6bPFdq50304114vJYJ8RDyK8D5O9Phpbd6SZWgI7PwzmmfN1upeOJlvybDSgCw==", "dev": true }, + "oauth": { + "version": "0.9.15", + "resolved": "https://registry.npmjs.org/oauth/-/oauth-0.9.15.tgz", + "integrity": "sha512-a5ERWK1kh38ExDEfoO6qUHJb32rd7aYmPHuyCu3Fta/cnICvYmgd2uhuKXvPD+PXB+gCEYYEaQdIRAjCOwAKNA==" + }, "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -18308,6 +18435,41 @@ "tslib": "^2.0.3" } }, + "passport": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/passport/-/passport-0.6.0.tgz", + "integrity": "sha512-0fe+p3ZnrWRW74fe8+SvCyf4a3Pb2/h7gFkQ8yTJpAO50gDzlfjZUZTO1k5Eg9kUct22OxHLqDZoKUWRHOh9ug==", + "requires": { + "passport-strategy": "1.x.x", + "pause": "0.0.1", + "utils-merge": "^1.0.1" + } + }, + "passport-github2": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/passport-github2/-/passport-github2-0.1.12.tgz", + "integrity": "sha512-3nPUCc7ttF/3HSP/k9sAXjz3SkGv5Nki84I05kSQPo01Jqq1NzJACgMblCK0fGcv9pKCG/KXU3AJRDGLqHLoIw==", + "requires": { + "passport-oauth2": "1.x.x" + } + }, + "passport-oauth2": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/passport-oauth2/-/passport-oauth2-1.7.0.tgz", + "integrity": "sha512-j2gf34szdTF2Onw3+76alNnaAExlUmHvkc7cL+cmaS5NzHzDP/BvFHJruueQ9XAeNOdpI+CH+PWid8RA7KCwAQ==", + "requires": { + "base64url": "3.x.x", + "oauth": "0.9.x", + "passport-strategy": "1.x.x", + "uid2": "0.0.x", + "utils-merge": "1.x.x" + } + }, + "passport-strategy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz", + "integrity": "sha512-CB97UUvDKJde2V0KDWWB3lyf6PC3FaZP7YxZ2G8OAtn9p4HI9j9JLP9qjOGZFvyl8uwNT8qM+hGnz/n16NI7oA==" + }, "path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -18342,6 +18504,11 @@ "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", "dev": true }, + "pause": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", + "integrity": "sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg==" + }, "pg": { "version": "8.9.0", "resolved": "https://registry.npmjs.org/pg/-/pg-8.9.0.tgz", @@ -19787,6 +19954,11 @@ "is-typed-array": "^1.1.9" } }, + "uid2": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/uid2/-/uid2-0.0.4.tgz", + "integrity": "sha512-IevTus0SbGwQzYh3+fRsAMTVVPOoIVufzacXcHPmdlle1jUpq7BRL+mw3dgeLanvGZdwwbWhRV6XrcFNdBmjWA==" + }, "unbox-primitive": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", diff --git a/package.json b/package.json index 501e971..978d00a 100644 --- a/package.json +++ b/package.json @@ -73,6 +73,7 @@ "dependencies": { "@babel/runtime": "^7.21.0", "bootstrap": "^5.2.3", + "cookie-parser": "^1.4.6", "cookie-session": "^2.0.0", "cors": "^2.8.5", "dotenv": "^16.0.3", @@ -81,6 +82,8 @@ "knex": "^2.4.2", "morgan": "^1.10.0", "openai": "^3.2.1", + "passport": "^0.6.0", + "passport-github2": "^0.1.12", "pg": "^8.9.0", "react-bootstrap": "^2.7.4", "react-icons": "^4.8.0", diff --git a/server/api.js b/server/api.js index 15551e4..7640c63 100644 --- a/server/api.js +++ b/server/api.js @@ -1,5 +1,7 @@ import { Router } from "express"; import { Configuration, OpenAIApi } from "openai"; +import passport from "passport"; +import "./passport"; //import db from "./db"; @@ -7,6 +9,49 @@ import logger from "./utils/logger"; const router = Router(); +//auth +router.get("/auth/login/success", (req, res) => { + try { + if (!req.session.user) { + res.json(); + throw new Error("no user"); + } else { + res.json(req.session.user); + } + } catch (err) { + return err; + } +}); + +router.get("/auth/logout", (req, res) => { + req.session = null; + res.redirect("/LandingPage"); + res.end(); +}); + +router.get("/auth/login/failed", (req, res) => { + res.status(401).json({ + success: false, + message: "Login failed!", + }); + res.redirect("/LandingPage"); +}); + +router.get( + "/auth/github", + passport.authenticate("github", { scope: ["profiel"] }) +); + +router.get("/auth/github/callback", function (req, res, next) { + passport.authenticate("github", function (err, user) { + req.session.user = user; + if (err) { + return next(err); + } + res.redirect("/"); + })(req, res, next); +}); + router.get("/", (_, res) => { logger.debug("Welcoming everyone..."); res.json({ message: "Hello, world!" }); diff --git a/server/app.js b/server/app.js index 102acb7..96c9e6a 100644 --- a/server/app.js +++ b/server/app.js @@ -1,6 +1,10 @@ import express from "express"; import cors from "cors"; import cookieSession from "cookie-session"; +import cookieParser from "cookie-parser"; +import passport from "passport"; +import "./passport"; +import "dotenv/config"; import apiRouter from "./api"; import config from "./utils/config"; @@ -16,19 +20,23 @@ const apiRoot = "/api"; const app = express(); -app.use(cors()); -app.use(express.json()); -app.use(configuredHelmet()); -app.use(configuredMorgan()); +app.use(cookieParser()); app.use( cookieSession({ name: "session", - keys: ["super_secret_key_dont_hack_please"], + keys: [process.env.SECRET], // Cookie Options maxAge: 7 * 24 * 60 * 60 * 1000, // 1 Week }) ); +app.use(passport.initialize()); +app.use(passport.session()); + +app.use(cors()); +app.use(express.json()); +app.use(configuredHelmet()); +app.use(configuredMorgan()); if (config.production) { app.enable("trust proxy"); diff --git a/server/passport.js b/server/passport.js new file mode 100644 index 0000000..bf9a842 --- /dev/null +++ b/server/passport.js @@ -0,0 +1,40 @@ +import "express"; +import passport from "passport"; +import "dotenv/config"; + +const GitHubStrategy = require("passport-github2").Strategy; + +const users = []; + +passport.serializeUser((user, done) => { + done(null, user.id); +}); + +passport.deserializeUser((id, done) => { + const user = users.find((u) => u.id === id); + done(null, user); +}); + +passport.use( + new GitHubStrategy( + { + clientID: process.env.GITHUB_CLIENT_ID ?? "", + clientSecret: process.env.GITHUB_CLIENT_SECRET ?? "", + callbackURLa: + "http://localhost:3000/api/auth/github/callback" ?? + "api/auth/github/callback", + }, + function (accessToken, refreshToken, profile, done) { + const user = { + username: profile.username, + id: profile.id, + avatar: profile.photos[0].value, + }; + const exist = users.find((u) => u.id === user.id); + if (!exist) { + users.push(user); + } + done(null, user); + } + ) +);