UNPKG

authkit-js

Version:

Express auth toolkit (JWT, Sessions with Redis, Google/GitHub OAuth) in JavaScript

150 lines (128 loc) 5.34 kB
const express = require('express'); const { makeCors } = require('../middleware/cors'); // Create an opinionated auth router that wires up what is available on the kit // Routes provided (when strategy present): // - GET /me → returns { user } // - POST /jwt/refresh → refresh JWT using refresh cookie // - POST /jwt/logout → clears JWT cookies // - POST /session/logout → destroys session and clears cookies // - GET /oauth/google → redirect to Google OAuth // - GET /oauth/google/callback → handle Google callback // - GET /oauth/github → redirect to GitHub OAuth // - GET /oauth/github/callback → handle GitHub callback // // You are expected to implement your own login that calls kit.jwt.login or kit.session.login. function makeAuthRouter(kit, options = {}) { const router = express.Router(); // Optional CORS for all auth routes if (options.cors) { const corsMw = makeCors(typeof options.cors === 'object' ? options.cors : {}); router.use(corsMw); } // Attach auth context on each request (non-failing) router.use(async (req, _res, next) => { try { req.auth = await kit.authenticate(req) || undefined; } catch { /* ignore and continue */ } next(); }); // Me endpoint router.get('/me', (req, res) => { if (!req.auth || !req.auth.user) return res.status(401).json({ error: 'Unauthorized' }); res.json({ user: req.auth.user }); }); // JWT routes when configured if (kit.jwt) { router.post('/jwt/refresh', async (req, res, next) => { try { const tokens = await kit.jwt.refresh(req, res); res.json({ ok: true, tokens }); } catch (e) { next(e); } }); router.post('/jwt/logout', async (_req, res) => { await kit.jwt.logout(res); res.json({ ok: true }); }); } // Session routes when configured if (kit.session) { router.post('/session/logout', async (req, res) => { await kit.session.logout(req, res); res.json({ ok: true }); }); } // Google OAuth (optional) if (kit.google) { router.get('/oauth/google', (_req, res) => { const url = kit.google.getAuthUrl(); res.redirect(url); }); router.get('/oauth/google/callback', async (req, res, next) => { try { const code = req.query && req.query.code; if (!code) return res.status(400).json({ error: 'Missing code' }); const { user, tokens, profile } = await kit.google.handleCallback(code); // Delegate to whichever strategy is default for persistence if (kit.jwt) await kit.jwt.login(res, user); else if (kit.session) await kit.session.login(res, user); res.json({ ok: true, user, profile }); } catch (e) { next(e); } }); } // GitHub OAuth (optional) if (kit.github) { router.get('/oauth/github', (_req, res) => { const url = kit.github.getAuthUrl(); res.redirect(url); }); router.get('/oauth/github/callback', async (req, res, next) => { try { const code = req.query && req.query.code; if (!code) return res.status(400).json({ error: 'Missing code' }); const { user, accessToken, profile } = await kit.github.handleCallback(code); if (kit.jwt) await kit.jwt.login(res, user); else if (kit.session) await kit.session.login(res, user); res.json({ ok: true, user, profile }); } catch (e) { next(e); } }); } // Facebook OAuth (optional) if (kit.facebook) { router.get('/oauth/facebook', (_req, res) => { const url = kit.facebook.getAuthUrl(); res.redirect(url); }); router.get('/oauth/facebook/callback', async (req, res, next) => { try { const code = req.query && req.query.code; if (!code) return res.status(400).json({ error: 'Missing code' }); const { user, accessToken, profile } = await kit.facebook.handleCallback(code); if (kit.jwt) await kit.jwt.login(res, user); else if (kit.session) await kit.session.login(res, user); res.json({ ok: true, user, profile }); } catch (e) { next(e); } }); } // Apple OAuth (optional) if (kit.apple) { router.get('/oauth/apple', (_req, res) => { const url = kit.apple.getAuthUrl(); res.redirect(url); }); // Apple commonly posts back; this handler uses GET for simplicity here router.get('/oauth/apple/callback', async (req, res, next) => { try { const code = req.query && req.query.code; if (!code) return res.status(400).json({ error: 'Missing code' }); const { user, tokens, profile } = await kit.apple.handleCallback(code); if (kit.jwt) await kit.jwt.login(res, user); else if (kit.session) await kit.session.login(res, user); res.json({ ok: true, user, profile }); } catch (e) { next(e); } }); } // Generic error handler for this router router.use((err, _req, res, _next) => { const status = err && (err.status || err.statusCode) || 500; res.status(status).json({ error: err.message || 'Internal Server Error' }); }); return router; } module.exports = { makeAuthRouter };