process.env.DEBUG = 'app*'; const express = require('express'); const app = express(); const jwt = require('jsonwebtoken'); const Debug = require('debug'); const path = require('path'); const cors = require('cors'); const bodyParser = require('body-parser'); const favicon = require('serve-favicon'); const cert = require('./cert'); let issuer = 'localhost:3333'; let jwksOrigin = `https://${issuer}/`; const audience = process.env.AUDIENCE || 'https://generic-audience'; const debug = Debug('app'); let {privateKey, certDer, thumbprint, exponent, modulus} = cert(jwksOrigin); // Configure our small auth0-mock-server app.options('*', cors()) .use(cors()) .use(bodyParser.json()) .use(bodyParser.urlencoded({extended: true})) .use(express.static(`${__dirname}/public`)) .use(favicon(path.join(__dirname, 'public', 'favicon.ico'))); // This route can be used to generate a valid jwt-token. app.post('/token', function (req, res) { if (!req.body.email || !req.body.password) { debug('Body is invalid!', req.body); return res.status(400).send('Email or password is missing!'); } let date = Math.floor(Date.now() / 1000); let accessToken = jwt.sign(Buffer.from(JSON.stringify({ iss: jwksOrigin, aud: [audience], sub: 'auth0|' + req.body.email, iat: date, exp: date + 7200, azp: req.body.clientId, 'https://unbound.se/email': req.body.email })), privateKey, { algorithm: 'RS256', keyid: thumbprint }); let idToken = jwt.sign(Buffer.from(JSON.stringify({ iss: jwksOrigin, aud: req.body.clientId, nonce: req.body.nonce, sub: 'auth0|' + req.body.email, iat: date, exp: date + 7200, azp: req.body.clientId })), privateKey, { algorithm: 'RS256', keyid: thumbprint }); debug('Signed token for ' + req.body.email); // res.json({ token }); res.redirect(`${req.body.redirect}?domain=${issuer}#access_token=${accessToken}&state=${req.body.state}&id_token=${idToken}&scope=openid%20profile%20email&expires_in=7200&token_type=Bearer`) }); // This route can be used to generate a valid jwt-token. app.get('/token/:email', function (req, res) { if (!req.params.email) { debug('No user was given!'); return res.status(400).send('user is missing'); } const token = jwt.sign({ user_id: 'auth0|' + req.params.email, }, privateKey); debug('Signed token for ' + req.params.email); res.json({token}); }); app.get('/authorize', function (req, res) { let redirect = req.query.redirect_uri; let state = req.query.state; let nonce = req.query.nonce; let clientId = req.query.client_id; res.send(` Auth
`) }); app.get('/userinfo', function (req, res) { res.contentType("application/json").send(JSON.stringify({picture: 'https://cdn.playbuzz.com/cdn/5458360f-32ea-460e-a707-1a2d26760558/70bda687-cb84-4756-8a44-8cf735ed87b3.jpg'})) }); app.get('/.well-known/jwks.json', function (req, res) { res .contentType("application/json") .send(JSON.stringify({ keys: [ { alg: 'RS256', // e: 'AQAB', e: exponent, kid: thumbprint, kty: 'RSA', n: modulus, use: 'sig', x5c: [certDer], x5t: thumbprint, }, ], })); }); // This route returns the inside of a jwt-token. Your main application // should use this route to keep the auth0-flow app.post('/tokeninfo', function (req, res) { if (!req.body.id_token) { debug('No token given in the body!'); return res.status(401).send('missing id_token'); } const data = jwt.decode(req.body.id_token); if (data) { debug('Return token data from ' + data.user_id); res.json(data); } else { debug('The token was invalid and could not be decoded!'); res.status(401).send('invalid id_token'); } }); app.post('/issuer', (req, res) => { if (!req.body.issuer) { debug('No issuer given in the body!'); return res.status(401).send('missing issuer'); } issuer = req.body.issuer; jwksOrigin = `https://${issuer}/`; const {privateKey: key, certDer: der, thumbPrint: thumb, exponent: exp, modulus: mod} = cert(jwksOrigin); privateKey = key; certDer = der; thumbprint = thumb; exponent = exp; modulus = mod; debug('Issuer set to ' + req.body.issuer); res.send('ok') }); app.listen(3333, function () { debug('Auth0-Mock-Server listening on port 3333!'); });