166 lines
5.2 KiB
JavaScript
166 lines
5.2 KiB
JavaScript
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(`
|
|
<html lang="en">
|
|
<head>
|
|
<title>Auth</title>
|
|
</head>
|
|
<body>
|
|
<form method="post" action="/token">
|
|
<input type="text" name="email">
|
|
<input type="password" name="password">
|
|
<input type="submit" value="Login">
|
|
<input type="hidden" value="${redirect}" name="redirect">
|
|
<input type="hidden" value="${state}" name="state">
|
|
<input type="hidden" value="${nonce}" name="nonce">
|
|
<input type="hidden" value="${clientId}" name="clientId">
|
|
</form>
|
|
</body>
|
|
</html>
|
|
`)
|
|
});
|
|
|
|
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!');
|
|
});
|