mirror of
https://gitea.smigz.com/smiggiddy/odin-codeprojects.git
synced 2025-04-04 11:00:58 -04:00
auth: learning express auth
This commit is contained in:
parent
0647b4af89
commit
518abdc55e
6 changed files with 363 additions and 0 deletions
14
auth-expressjs/migrations/init.sql
Normal file
14
auth-expressjs/migrations/init.sql
Normal file
|
@ -0,0 +1,14 @@
|
|||
CREATE TABLE IF NOT EXISTS users (
|
||||
id INTEGER PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
username VARCHAR ( 255 ),
|
||||
password VARCHAR (255)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS federated_credentials (
|
||||
user_id INTEGER NOT NULL,
|
||||
provider TEXT NOT NULL,
|
||||
subject TEXT NOT NULL,
|
||||
PRIMARY KEY (provider, subject)
|
||||
);
|
||||
|
||||
|
189
auth-expressjs/src/app.js
Normal file
189
auth-expressjs/src/app.js
Normal file
|
@ -0,0 +1,189 @@
|
|||
const path = require("node:path");
|
||||
const { Pool } = require("pg");
|
||||
const express = require("express");
|
||||
const session = require("express-session");
|
||||
const passport = require("passport");
|
||||
const LocalStrategy = require("passport-local");
|
||||
const GoogleStrategy = require("passport-google-oauth").OAuth2Strategy;
|
||||
const fs = require("node:fs");
|
||||
const bcryptjs = require("bcryptjs");
|
||||
|
||||
const pool = new Pool({
|
||||
connectionString: process.env.CONNECTION_STRING,
|
||||
});
|
||||
|
||||
const initSQL = path.join(__dirname, "../migrations/init.sql");
|
||||
|
||||
fs.readFile(initSQL, "utf8", (err, data) => {
|
||||
if (err) {
|
||||
console.error(err);
|
||||
return;
|
||||
}
|
||||
pool.query(data);
|
||||
});
|
||||
|
||||
console.log(process.env.DEEZNUTS);
|
||||
const app = express();
|
||||
app.set("views", path.join(__dirname, "views"));
|
||||
app.set("view engine", "ejs");
|
||||
|
||||
//app.use(session({ secret: "cats", resave: false, saveUninitialized: false }));
|
||||
app.use(
|
||||
session({
|
||||
store: new (require("connect-pg-simple")(session))({
|
||||
pool: pool,
|
||||
tableName: "user_sessions",
|
||||
createTableIfMissing: true,
|
||||
}),
|
||||
resave: false,
|
||||
cookie: { maxAge: 30 * 24 * 60 * 60 * 1000 },
|
||||
saveUninitialized: false,
|
||||
secret: "deezNuts",
|
||||
}),
|
||||
);
|
||||
app.use(passport.session());
|
||||
app.use(express.urlencoded({ extended: false }));
|
||||
|
||||
app.listen(3000, () => console.log("app running on port 3000"));
|
||||
|
||||
passport.use(
|
||||
new LocalStrategy(async (username, password, done) => {
|
||||
try {
|
||||
const { rows } = await pool.query(
|
||||
"SELECT * FROM users WHERE username = $1",
|
||||
[username],
|
||||
);
|
||||
const user = rows[0];
|
||||
const match = await bcryptjs.compare(password, user.password);
|
||||
|
||||
if (!user) {
|
||||
return done(null, false, { message: "Incorrect username/password." });
|
||||
}
|
||||
|
||||
if (!match) {
|
||||
return done(null, false, { message: "incorrect username/password" });
|
||||
}
|
||||
|
||||
return done(null, user);
|
||||
} catch (err) {
|
||||
return done(err);
|
||||
}
|
||||
}),
|
||||
);
|
||||
|
||||
passport.use(
|
||||
new GoogleStrategy(
|
||||
{
|
||||
clientID: process.env["GOOGLE_CLIENT_ID"],
|
||||
clientSecret: process.env["GOOGLE_CLIENT_SECRET"],
|
||||
callbackURL: "/oauth2/redirect/google",
|
||||
scope: ["profile"],
|
||||
},
|
||||
async function verify(accessToken, refreshToken, profile, cb) {
|
||||
try {
|
||||
await pool.query("BEGIN");
|
||||
const { rows: federatedRows } = await pool.query(
|
||||
"SELECT * FROM federated_credentials WHERE provider = $1 AND subject = $2",
|
||||
["https://accounts.google.com", profile.id],
|
||||
);
|
||||
let id = federatedRows.length > 0 ? federatedRows[0].user_id : null;
|
||||
if (federatedRows.length === 0) {
|
||||
const { rows: newUserRows } = await pool.query(
|
||||
"INSERT INTO users (username) VALUES ($1) RETURNING *",
|
||||
[profile.displayName],
|
||||
);
|
||||
id = newUserRows[0].id;
|
||||
await pool.query(
|
||||
"INSERT INTO federated_credentials (user_id, provider, subject) VALUES ($1, $2, $3)",
|
||||
[id, "https://accounts.google.com", profile.id],
|
||||
);
|
||||
const user = {
|
||||
id: id,
|
||||
name: profile.displayName,
|
||||
};
|
||||
pool.query("COMMIT");
|
||||
cb(null, user);
|
||||
} else {
|
||||
const { rows: userRows } = await pool.query(
|
||||
"SELECT * FROM users WHERE id = $1",
|
||||
[id],
|
||||
);
|
||||
cb(null, userRows[0]);
|
||||
}
|
||||
} catch (e) {
|
||||
await pool.query("ROLLBACK");
|
||||
cb(e);
|
||||
}
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
passport.serializeUser((user, done) => {
|
||||
done(null, user.id);
|
||||
});
|
||||
|
||||
passport.deserializeUser(async (id, done) => {
|
||||
try {
|
||||
const { rows } = await pool.query("SELECT * FROM users WHERE id= $1", [id]);
|
||||
const user = rows[0];
|
||||
done(null, user);
|
||||
} catch (e) {
|
||||
done(e);
|
||||
}
|
||||
});
|
||||
|
||||
app.use((req, res, next) => {
|
||||
console.log(req.user);
|
||||
console.table(req.session.passport);
|
||||
next();
|
||||
});
|
||||
|
||||
app.get("/", (req, res) => {
|
||||
if (req.session.viewCount) {
|
||||
req.session.viewCount++;
|
||||
} else {
|
||||
req.session.viewCount = 1;
|
||||
req.session.deezNuts = "big AF dog";
|
||||
}
|
||||
res.render("index", { user: req.user, sessions: req.session.viewCount });
|
||||
});
|
||||
|
||||
app.get("/sign-up", (req, res) => res.render("sign-up-form"));
|
||||
app.post("/sign-up", async (req, res, next) => {
|
||||
try {
|
||||
const hashedPassword = await bcryptjs.hash(req.body.password, 10);
|
||||
await pool.query("INSERT INTO users (username, password) VALUES ($1, $2)", [
|
||||
req.body.username,
|
||||
hashedPassword,
|
||||
]);
|
||||
res.redirect("/");
|
||||
} catch (err) {
|
||||
next(err);
|
||||
}
|
||||
});
|
||||
|
||||
app.post(
|
||||
"/log-in",
|
||||
passport.authenticate("local", {
|
||||
successRedirect: "/",
|
||||
failureRedirect: "/",
|
||||
}),
|
||||
);
|
||||
|
||||
app.get("/log-out", (req, res, next) => {
|
||||
req.logout((err) => {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
res.redirect("/");
|
||||
});
|
||||
});
|
||||
|
||||
app.get("/login/federated/google", passport.authenticate("google"));
|
||||
app.get(
|
||||
"/oauth2/redirect/google",
|
||||
passport.authenticate("google", {
|
||||
successRedirect: "/",
|
||||
failureRedirect: "/login",
|
||||
}),
|
||||
);
|
104
auth-expressjs/src/app.js.bak
Normal file
104
auth-expressjs/src/app.js.bak
Normal file
|
@ -0,0 +1,104 @@
|
|||
const path = require("node:path");
|
||||
const { Pool } = require("pg");
|
||||
const express = require("express");
|
||||
const session = require("express-session");
|
||||
const passport = require("passport");
|
||||
const LocalStrategy = require("passport-local");
|
||||
const fs = require("node:fs");
|
||||
const bcryptjs = require("bcryptjs");
|
||||
|
||||
const pool = new Pool({
|
||||
connectionString: "postgres://deez:postgres@smig-ca01:31450/deez",
|
||||
});
|
||||
|
||||
const initSQL = path.join(__dirname, "../migrations/init.sql");
|
||||
|
||||
fs.readFile(initSQL, "utf8", (err, data) => {
|
||||
if (err) {
|
||||
console.error(err);
|
||||
return;
|
||||
}
|
||||
pool.query(data);
|
||||
});
|
||||
|
||||
const app = express();
|
||||
app.set("views", path.join(__dirname, "views"));
|
||||
app.set("view engine", "ejs");
|
||||
|
||||
app.use(session({ secret: "cats", resave: false, saveUninitialized: false }));
|
||||
app.use(passport.session());
|
||||
app.use(express.urlencoded({ extended: false }));
|
||||
|
||||
app.get("/", (req, res) => res.render("index", { user: req.user }));
|
||||
|
||||
app.get("/sign-up", (req, res) => res.render("sign-up-form"));
|
||||
app.post("/sign-up", async (req, res, next) => {
|
||||
try {
|
||||
const hashedPassword = await bcryptjs.hash(req.body.password, 10);
|
||||
await pool.query("INSERT INTO users (username, password) VALUES ($1, $2)", [
|
||||
req.body.username,
|
||||
hashedPassword,
|
||||
]);
|
||||
res.redirect("/");
|
||||
} catch (err) {
|
||||
next(err);
|
||||
}
|
||||
});
|
||||
|
||||
app.listen(3000, () => console.log("app running on port 3000"));
|
||||
|
||||
passport.use(
|
||||
new LocalStrategy(async (username, password, done) => {
|
||||
try {
|
||||
const { rows } = await pool.query(
|
||||
"SELECT * FROM users WHERE username = $1",
|
||||
[username],
|
||||
);
|
||||
const user = rows[0];
|
||||
const match = await bcryptjs.compare(password, user.password);
|
||||
|
||||
if (!user) {
|
||||
return done(null, false, { message: "Incorrect username/password." });
|
||||
}
|
||||
|
||||
if (!match) {
|
||||
return done(null, false, { message: "incorrect username/password" });
|
||||
}
|
||||
|
||||
return done(null, user);
|
||||
} catch (err) {
|
||||
return done(err);
|
||||
}
|
||||
}),
|
||||
);
|
||||
|
||||
passport.serializeUser((user, done) => {
|
||||
done(null, user.id);
|
||||
});
|
||||
|
||||
passport.deserializeUser(async (id, done) => {
|
||||
try {
|
||||
const { rows } = await pool.query("SELECT * FROM users WHERE id= $1", [id]);
|
||||
const user = rows[0];
|
||||
done(null, user);
|
||||
} catch (e) {
|
||||
done(e);
|
||||
}
|
||||
});
|
||||
|
||||
app.post(
|
||||
"/log-in",
|
||||
passport.authenticate("local", {
|
||||
successRedirect: "/",
|
||||
failureRedirect: "/",
|
||||
}),
|
||||
);
|
||||
|
||||
app.get("/log-out", (req, res, next) => {
|
||||
req.logout((err) => {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
res.redirect("/");
|
||||
});
|
||||
});
|
29
auth-expressjs/src/views/index.ejs
Normal file
29
auth-expressjs/src/views/index.ejs
Normal file
|
@ -0,0 +1,29 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title></title>
|
||||
</head>
|
||||
<body>
|
||||
<% if (locals.user) {%>
|
||||
MY PERSON <%= user.username %>
|
||||
<a href="/log-out">LOG OUT</a>
|
||||
<p> Views: <%= sessions %></p>
|
||||
|
||||
<% } else { %>
|
||||
<p> you should log in man </P
|
||||
<h1>please log in</h1>
|
||||
|
||||
<form action="/log-in" method="POST">
|
||||
<label for="username">Username</label>
|
||||
<input id="username" name="username" placeholder="username" type="text" />
|
||||
<label for="password">Password</label>
|
||||
<input id="password" name="password" type="password" />
|
||||
<button>Log In</button>
|
||||
</form>
|
||||
<% } %>
|
||||
|
||||
<a type="button" href="/login/federated/google">Sign in with Google</a>
|
||||
</body>
|
||||
</html>
|
||||
|
9
auth-expressjs/src/views/log-in.ejs
Normal file
9
auth-expressjs/src/views/log-in.ejs
Normal file
|
@ -0,0 +1,9 @@
|
|||
<h1>please log in</h1>
|
||||
<form action="/log-in" method="POST">
|
||||
<label for="username">Username</label>
|
||||
<input id="username" name="username" placeholder="username" type="text" />
|
||||
<label for="password">Password</label>
|
||||
<input id="password" name="password" type="password" />
|
||||
<button>Log In</button>
|
||||
</form>
|
||||
|
18
auth-expressjs/src/views/sign-up-form.ejs
Normal file
18
auth-expressjs/src/views/sign-up-form.ejs
Normal file
|
@ -0,0 +1,18 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title></title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Sign Up</h1>
|
||||
<form action="" method="POST">
|
||||
<label for="username">Username</label>
|
||||
<input id="username" name="username" placeholder="username" type="text" />
|
||||
<label for="password">Password</label>
|
||||
<input id="password" name="password" type="password" />
|
||||
<button>Sign Up</button>
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
||||
|
Loading…
Add table
Reference in a new issue