var express = require("express"); var passport = require("passport"); var TeamsnapStrategy = require("passport-teamsnap"); // const {teamsnap} = require("../app"); // Configure the TeamSnap strategy for use by Passport. // // OAuth 2.0-based strategies require a `verify` function which receives the // credential (`accessToken`) for accessing the TeamSnap API on the user's // behalf, along with the user's profile. The function must invoke `cb` // with a user object, which will be set at `req.user` in route handlers after // authentication. passport.use( new TeamsnapStrategy( { apiVersion: "3", clientID: process.env["TEAMSNAP_CLIENT_ID"], clientSecret: process.env["TEAMSNAP_CLIENT_SECRET"], callbackURL: "/auth/teamsnap/callback", passReqToCallback: true, scope: ["read", "write"], proxy: true }, async function (req, accessToken, refreshToken, profile, done) { json = JSON.parse(profile._raw); field_from_collection = (field_name) => { return json.collection.items[0].data.filter( (e) => e.name == field_name )[0].value; } const new_profile = { access_token: accessToken }; new_profile["id"] = field_from_collection("id") new_profile["email"] = field_from_collection("email") new_profile["first_name"] = field_from_collection("first_name") new_profile["last_name"] = field_from_collection("last_name") req.session.teamsnap_access_token = accessToken; await initTeamsnap(process.env["TEAMSNAP_CLIENT_ID"], accessToken) return done(null, new_profile); } ) ); // Configure Passport authenticated session persistence. // // In order to restore authentication state across HTTP requests, Passport needs // to serialize users into and deserialize users out of the session. In a // production-quality application, this would typically be as simple as // supplying the user ID when serializing, and querying the user record by ID // from the database when deserializing. However, due to the fact that this // example does not have a database, the complete Facebook profile is serialized // and deserialized. passport.serializeUser(function (user, cb) { process.nextTick(function () { console.log("L#56 serializing user id", user.id); cb(null, { id: user.id, username: user.email, email: user.email, first_name: user.first_name, last_name: user.last_name, accessToken: user.access_token, }); }); }); passport.deserializeUser(function (user, cb) { process.nextTick(async function () { console.log("L#68 deserializing user id", user.id); if (!teamsnap.isAuthed()){ await initTeamsnap(process.env["TEAMSNAP_CLIENT_ID"], user.accessToken) } return cb(null, user); }); }); var router = express.Router(); /* GET /login * * This route prompts the user to log in. * * The 'login' view renders an HTML page, which contain a button prompting the * user to sign in with TeamSnap. When the user clicks this button, a request * will be sent to the `GET /login/federated/teamsnap` route. */ router.get("/login", function (req, res, next) { // https://stackoverflow.com/a/73056806/20522015 returnTo = req.session.returnTo; // req.session.regenerate(); // this is not working right as of now... req.session.returnTo = returnTo; res.render("login", {layout:"layouts/main"}); }); /* GET /login/federated/teamsnap * * This route redirects the user to TeamSnap, where they will authenticate. * * Signing in with TeamSnap is implemented using OAuth 2.0. This route initiates * an OAuth 2.0 flow by redirecting the user to TeamSnap's identity server. * Once there, TeamSnap will authenticate the user * and obtain their consent to release identity information to this app. * * Once TeamSnap has completed their interaction with the user, the user will be * redirected back to the app. */ router.get("/login/federated/teamsnap", passport.authenticate("teamsnap")); /* This route completes the authentication sequence when TeamSnap redirects the user back to the application. When a new user signs in, a user account is automatically created and their TeamSnap account is linked. When an existing user returns, they are signed in to their linked account. */ router.get( "/auth/teamsnap", passport.authenticate("teamsnap", function (err, user, info, status) {}) ); router.get( "/auth/teamsnap/callback", passport.authenticate("teamsnap", { successReturnToOrRedirect: "/", failureRedirect: "/login", keepSessionInfo: true, }) ); const initTeamsnap = async (clientID, accessToken) => { teamsnap.init(clientID); teamsnap.auth(accessToken); await teamsnap.loadCollections(); await teamsnap.enablePersistence(); } const ensureLoggedIn = (req, res, next) => { if (!req.isAuthenticated()){ req.session.returnTo = req.originalUrl res.redirect("/login"); // return next(); } else{ req.user = req.session.passport.user next(); } } router.get('/auth/teamsnap/session_storage', (req,res)=>{ res.status(200).json({"teamsnap.authToken":req.user?.accessToken}) } ) router.post('/logout', function(req, res, next){ req.logout(function(err) { if (err) { return next(err); } res.redirect('/'); }); }); module.exports = {router, ensureLoggedIn};