diff --git a/public/javascripts/index.js b/public/javascripts/index.js index 2a6528c..cf0f036 100644 --- a/public/javascripts/index.js +++ b/public/javascripts/index.js @@ -1,4 +1,3 @@ -const CODE = "code_abc123"; const SCOPE = "some scope stuff"; function onSubmit() { @@ -7,9 +6,12 @@ function onSubmit() { const redirect_uri = params.get("redirect_uri"); const state = params.get("state"); + const profileSelect = document.getElementById("profile-select"); + const profile = profileSelect?.value; + const newParams = new URLSearchParams(); newParams.append("state", state); - newParams.append("code", CODE); + newParams.append("code", profile); newParams.append("scope", SCOPE); newParams.append("authuser", "0"); newParams.append("prompt", "none"); diff --git a/public/stylesheets/style.css b/public/stylesheets/style.css index 92936b1..d25947e 100644 --- a/public/stylesheets/style.css +++ b/public/stylesheets/style.css @@ -24,3 +24,14 @@ button { font-size: 16px; max-width: 150px; } + +label#profile-select-label { + display: block; + margin-bottom: 10px; +} + +select#profile-select { + padding: 8px; + font-size: 16px; + margin-bottom: 30px; +} \ No newline at end of file diff --git a/routes/index.js b/routes/index.js index 07701bd..ae5c70f 100644 --- a/routes/index.js +++ b/routes/index.js @@ -1,23 +1,29 @@ const express = require("express"); const router = express.Router(); const { createIdToken } = require("../utils/createIdToken"); +const { getProfiles } = require("../utils/profiles"); // GET home page router.get("/", (_req, res) => { - res.render("index", { title: "Fake SSO" }); + res.render("index", { title: "Fake SSO", profiles: getProfiles() }); }); // The authorization endpoint, same as homepage router.get("/oauth2/authorize", (_req, res) => { - res.render("index", { title: "Fake SSO" }); + res.render("index", { title: "Fake SSO", profiles: getProfiles() }); }); // The token endpoint: receives code, returns id token and access token. // The id token contains all the verified information about the user. // The access token can be used to request extra information using // the /userinfo endpoint. -router.post("/oauth2/token", async (_req, res) => { - const idToken = await createIdToken(); +router.post("/oauth2/token", async (req, res) => { + // This is the code that was passed to the redirect_uri. + // See public/javascripts/index.js + const profileId = req.body.code; + + // We then use this profile to create an id token. + const idToken = await createIdToken(profileId); res.json({ token_type: "Bearer", diff --git a/utils/createIdToken.js b/utils/createIdToken.js index 6ef0bc3..5232b28 100644 --- a/utils/createIdToken.js +++ b/utils/createIdToken.js @@ -1,6 +1,7 @@ const jose = require("jose"); const { v4: uuidv4 } = require("uuid"); const { randomBytes } = require("crypto"); +const { getProfileById } = require("./profiles"); require('dotenv').config({ path: './env_files/back-secret.env' }); @@ -9,22 +10,24 @@ const issuer = process.env.FAKE_SSO_ISSUER ?? "http://host.docker.internal"; const alg = "HS256"; -const createIdToken = () => { +const createIdToken = (profileId) => { const uid = uuidv4(); const randomString = randomBytes(6).toString("hex"); + const profile = getProfileById(profileId); + // https://www.iana.org/assignments/jwt/jwt.xhtml return new jose.SignJWT({ uid, sub: uid, azp: "govocal_client", - email: `${randomString}@example.com`, - email_verified: true, - name: "John Doe", - given_name: "John", - family_name: "Doe", - gender: "male", - birthdate: "2000-01-01", + email: profile.has_email ? `${randomString}@example.com` : undefined, + email_verified: profile.verified_email, + name: `${profile.first_name} ${profile.last_name}`, + given_name: profile.first_name, + family_name: profile.last_name, + gender: profile.gender, + birthdate: profile.birthdate, }) .setProtectedHeader({ alg }) .setIssuedAt() diff --git a/utils/profiles.js b/utils/profiles.js new file mode 100644 index 0000000..06a034a --- /dev/null +++ b/utils/profiles.js @@ -0,0 +1,43 @@ +const PROFILES = [ + { + id: 'john_doe', + description: "John Doe (random email, has name, has custom fields)", + first_name: "John", + last_name: "Doe", + has_email: true, + verified_email: true, + gender: "male", + birthdate: "2000-01-01", + }, + { + id: 'jane_doe', + description: "Jane Doe (no email, has name, has custom fields)", + first_name: "Jane", + last_name: "Doe", + has_email: false, + verified_email: false, + gender: "female", + birthdate: "2001-02-02", + }, + { + id: 'tracy_smith', + description: "Tracy Smith (random unverified email, has name, has custom fields)", + first_name: "Tracy", + last_name: "Smith", + has_email: true, + verified_email: false, + gender: "female", + birthdate: "2002-03-03", + } +] + +const getProfiles = () => PROFILES; + +const getProfileById = (id) => { + return PROFILES.find(p => p.id === id); +} + +module.exports = { + getProfiles, + getProfileById, +}; diff --git a/views/index.ejs b/views/index.ejs index d825fef..ce3240b 100644 --- a/views/index.ejs +++ b/views/index.ejs @@ -15,6 +15,16 @@ <%= title %>
+
+ + +