const passport = require('passport'); const OpenIDConnectStrategy = require('passport-openidconnect'); const dotenv = require('dotenv'); dotenv.config(); const express = require('express'); const { param } = require('./applications'); const router = express.Router(); import pool from '../db'; const querystring = require('querystring'); passport.use(new OpenIDConnectStrategy({ issuer: process.env.AUTH_ISSUER, authorizationURL: process.env.AUTH_DOMAIN + '/authorize/', tokenURL: process.env.AUTH_DOMAIN + '/token/', userInfoURL: process.env.AUTH_DOMAIN + '/userinfo/', clientID: process.env.AUTH_CLIENT_ID, clientSecret: process.env.AUTH_CLIENT_SECRET, callbackURL: process.env.AUTH_REDIRECT_URI, scope: ['openid', 'profile'] }, async function verify(issuer, sub, profile, jwtClaims, accessToken, refreshToken, params, cb) { // console.log('--- OIDC verify() called ---'); // console.log('issuer:', issuer); // console.log('sub:', sub); // console.log('profile:', JSON.stringify(profile, null, 2)); // console.log('id_token claims:', JSON.stringify(jwtClaims, null, 2)); // console.log('preferred_username:', jwtClaims?.preferred_username); const con = await pool.getConnection(); try { await con.beginTransaction(); //lookup existing user const existing = await con.query(`SELECT id FROM members WHERE authentik_issuer = ? AND authentik_sub = ? LIMIT 1;`, [issuer, sub]); let memberId; //if member exists if (existing.length > 0) { memberId = existing[0].id; } else { //otherwise: create account const username = sub.username; const result = await con.query( `INSERT INTO members (name, authentik_sub, authentik_issuer) VALUES (?, ?, ?)`, [username, sub, issuer] ) memberId = Number(result.insertId); } await con.commit(); return cb(null, { memberId }); } catch (error) { await con.rollback(); return cb(error); } finally { con.release(); } })); router.get('/login', (req, res, next) => { // Store redirect target in session if provided req.session.redirectTo = req.query.redirect; next(); }, passport.authenticate('openidconnect')); // router.get('/callback', (req, res, next) => { // passport.authenticate('openidconnect', { // successRedirect: req.session.redirectTo, // failureRedirect: process.env.CLIENT_URL // }) // }); router.get('/callback', (req, res, next) => { const redirectURI = req.session.redirectTo; passport.authenticate('openidconnect', (err, user) => { if (err) return next(err); if (!user) return res.redirect(process.env.CLIENT_URL); req.logIn(user, err => { if (err) return next(err); // Use redirect saved from session const redirectTo = redirectURI || process.env.CLIENT_URL; delete req.session.redirectTo; return res.redirect(redirectTo); }); })(req, res, next); }); router.get('/logout', function (req, res, next) { req.logout(function (err) { if (err) { return next(err); } var params = { client_id: process.env.AUTH_CLIENT_ID, returnTo: process.env.CLIENT_URL }; res.redirect(process.env.AUTH_END_SESSION_URI + '?' + querystring.stringify(params)); }); }); passport.serializeUser(function (user, cb) { process.nextTick(function () { cb(null, user); }); }); passport.deserializeUser(function (user, cb) { process.nextTick(async function () { const memberID = user.memberId; const con = await pool.getConnection(); var userData; try { let userResults = await con.query(`SELECT id, name FROM members WHERE id = ?;`, [memberID]) userData = userResults[0]; } catch (error) { console.error(error) } finally { con.release(); } return cb(null, userData); }); }); module.exports = router;