Compare commits

..

28 Commits

Author SHA1 Message Date
argoyle 6dda660e78 chore(deps): bump jsonwebtoken from 8.5.1 to 9.0.0
Bumps [jsonwebtoken](https://github.com/auth0/node-jsonwebtoken) from 8.5.1 to 9.0.0.
- [Release notes](https://github.com/auth0/node-jsonwebtoken/releases)
- [Changelog](https://github.com/auth0/node-jsonwebtoken/blob/master/CHANGELOG.md)
- [Commits](https://github.com/auth0/node-jsonwebtoken/compare/v8.5.1...v9.0.0)
2022-12-22 06:52:39 +00:00
argoyle 534772b315 chore(deps): bump express from 4.18.1 to 4.18.2
Bumps [express](https://github.com/expressjs/express) from 4.18.1 to 4.18.2.
- [Release notes](https://github.com/expressjs/express/releases)
- [Changelog](https://github.com/expressjs/express/blob/master/History.md)
- [Commits](https://github.com/expressjs/express/compare/4.18.1...4.18.2)
2022-10-09 06:52:35 +00:00
argoyle 3bdfe7bf0e chore(deps): bump body-parser from 1.20.0 to 1.20.1
Bumps [body-parser](https://github.com/expressjs/body-parser) from 1.20.0 to 1.20.1.
- [Release notes](https://github.com/expressjs/body-parser/releases)
- [Changelog](https://github.com/expressjs/body-parser/blob/master/HISTORY.md)
- [Commits](https://github.com/expressjs/body-parser/compare/1.20.0...1.20.1)
2022-10-07 06:52:24 +00:00
argoyle edba76d0ab chore(deps): bump nodemon from 2.0.19 to 2.0.20
Bumps [nodemon](https://github.com/remy/nodemon) from 2.0.19 to 2.0.20.
- [Release notes](https://github.com/remy/nodemon/releases)
- [Commits](https://github.com/remy/nodemon/compare/v2.0.19...v2.0.20)
2022-09-17 06:52:27 +00:00
argoyle 5289b4fa23 chore(deps): bump nodemon from 2.0.18 to 2.0.19
Bumps [nodemon](https://github.com/remy/nodemon) from 2.0.18 to 2.0.19.
- [Release notes](https://github.com/remy/nodemon/releases)
- [Commits](https://github.com/remy/nodemon/compare/v2.0.18...v2.0.19)
2022-07-06 06:52:23 +00:00
argoyle eef7168f37 chore(deps): bump nodemon from 2.0.16 to 2.0.18
Bumps [nodemon](https://github.com/remy/nodemon) from 2.0.16 to 2.0.18.
- [Release notes](https://github.com/remy/nodemon/releases)
- [Commits](https://github.com/remy/nodemon/compare/v2.0.16...v2.0.18)
2022-06-24 06:52:29 +00:00
argoyle 596967ff72 Merge branch 'dependabot-npm_and_yarn-normalize-url-4.5.1' into 'main'
chore(deps): [security] bump normalize-url from 4.5.0 to 4.5.1

See merge request unboundsoftware/auth0mock!41
2022-05-02 07:01:46 +00:00
argoyle 5f2385a92f chore(deps): [security] bump normalize-url from 4.5.0 to 4.5.1
Bumps [normalize-url](https://github.com/sindresorhus/normalize-url) from 4.5.0 to 4.5.1. **This update includes a security fix.**
- [Release notes](https://github.com/sindresorhus/normalize-url/releases)
- [Commits](https://github.com/sindresorhus/normalize-url/commits)
2022-05-02 07:00:02 +00:00
argoyle a5653c8ea6 Merge branch 'dependabot-npm_and_yarn-ini-1.3.8' into 'main'
chore(deps): [security] bump ini from 1.3.5 to 1.3.8

See merge request unboundsoftware/auth0mock!39
2022-05-02 06:59:59 +00:00
argoyle 75ec899c99 chore(deps): [security] bump ini from 1.3.5 to 1.3.8
Bumps [ini](https://github.com/npm/ini) from 1.3.5 to 1.3.8. **This update includes a security fix.**
- [Release notes](https://github.com/npm/ini/releases)
- [Changelog](https://github.com/npm/ini/blob/main/CHANGELOG.md)
- [Commits](https://github.com/npm/ini/compare/v1.3.5...v1.3.8)
2022-05-02 06:58:19 +00:00
argoyle cb31381be2 Merge branch 'dependabot-npm_and_yarn-minimist-1.2.6' into 'main'
chore(deps): [security] bump minimist from 1.2.0 to 1.2.6

See merge request unboundsoftware/auth0mock!40
2022-05-02 06:58:17 +00:00
argoyle 9ee344311a chore(deps): [security] bump minimist from 1.2.0 to 1.2.6
Bumps [minimist](https://github.com/substack/minimist) from 1.2.0 to 1.2.6. **This update includes security fixes.**
- [Release notes](https://github.com/substack/minimist/releases)
- [Commits](https://github.com/substack/minimist/compare/1.2.0...1.2.6)
2022-05-02 06:56:54 +00:00
argoyle d7e3b10e80 Merge branch 'dependabot-npm_and_yarn-ansi-regex-4.1.1' into 'main'
chore(deps): [security] bump ansi-regex from 4.1.0 to 4.1.1

See merge request unboundsoftware/auth0mock!38
2022-05-02 06:56:51 +00:00
argoyle 7b306dd500 chore(deps): [security] bump ansi-regex from 4.1.0 to 4.1.1
Bumps [ansi-regex](https://github.com/chalk/ansi-regex) from 4.1.0 to 4.1.1. **This update includes a security fix.**
- [Release notes](https://github.com/chalk/ansi-regex/releases)
- [Commits](https://github.com/chalk/ansi-regex/compare/v4.1.0...v4.1.1)
2022-05-02 06:52:21 +00:00
argoyle 22d096a2be Merge branch 'dependabot-npm_and_yarn-nodemon-2.0.16' into 'main'
chore(deps): bump nodemon from 2.0.15 to 2.0.16

See merge request unboundsoftware/auth0mock!37
2022-05-01 17:27:31 +00:00
argoyle 858cb96e10 chore(deps): bump nodemon from 2.0.15 to 2.0.16
Bumps [nodemon](https://github.com/remy/nodemon) from 2.0.15 to 2.0.16.
- [Release notes](https://github.com/remy/nodemon/releases)
- [Commits](https://github.com/remy/nodemon/compare/v2.0.15...v2.0.16)
2022-05-01 17:26:04 +00:00
argoyle e8dd55208c Merge branch 'dependabot-npm_and_yarn-express-4.18.1' into 'main'
chore(deps): bump express from 4.18.0 to 4.18.1

See merge request unboundsoftware/auth0mock!36
2022-05-01 17:25:57 +00:00
argoyle dbf5206c1b chore(deps): bump express from 4.18.0 to 4.18.1
Bumps [express](https://github.com/expressjs/express) from 4.18.0 to 4.18.1.
- [Release notes](https://github.com/expressjs/express/releases)
- [Changelog](https://github.com/expressjs/express/blob/master/History.md)
- [Commits](https://github.com/expressjs/express/compare/4.18.0...4.18.1)
2022-04-30 06:52:18 +00:00
argoyle 4229508bba feat: add support for client id and secret tokens 2022-04-28 09:38:05 +02:00
argoyle b4d5dbe9e3 feat: add dummy-implementation of management API 2022-04-26 16:54:03 +02:00
argoyle b476cf0e36 fix: use correct return-variable 2022-04-26 15:37:19 +02:00
argoyle 37ac46759d fix: make sure thumbPrint is a string 2022-04-26 15:22:53 +02:00
argoyle 424e500d6b chore: format code 2022-04-26 15:22:39 +02:00
argoyle 9539d9b38d Merge branch 'dependabot-npm_and_yarn-express-4.18.0' into 'main'
Chore(deps): bump express from 4.17.3 to 4.18.0

See merge request unboundsoftware/auth0mock!35
2022-04-26 11:01:52 +00:00
argoyle a9ea2dace4 fix: add custom claims to both id and access token 2022-04-26 11:49:19 +02:00
argoyle aad18ad000 feat: add email custom claim 2022-04-26 11:08:19 +02:00
argoyle b009965908 feat: add env-property for default issuer 2022-04-26 09:55:56 +02:00
argoyle 68d3f0df82 Chore(deps): bump express from 4.17.3 to 4.18.0
Bumps [express](https://github.com/expressjs/express) from 4.17.3 to 4.18.0.
- [Release notes](https://github.com/expressjs/express/releases)
- [Changelog](https://github.com/expressjs/express/blob/master/History.md)
- [Commits](https://github.com/expressjs/express/compare/4.17.3...4.18.0)
2022-04-26 06:52:17 +00:00
4 changed files with 307 additions and 939 deletions
+84 -22
View File
@@ -11,10 +11,11 @@ const bodyParser = require('body-parser')
const favicon = require('serve-favicon') const favicon = require('serve-favicon')
const cert = require('./cert') const cert = require('./cert')
let issuer = 'localhost:3333' let issuer = process.env.ISSUER || 'localhost:3333'
let jwksOrigin = `https://${issuer}/` let jwksOrigin = `https://${issuer}/`
const audience = process.env.AUDIENCE || 'https://generic-audience' const audience = process.env.AUDIENCE || 'https://generic-audience'
const adminCustomClaim = process.env.ADMIN_CUSTOM_CLAIM || 'https://unbound.se/admin' const adminCustomClaim = process.env.ADMIN_CUSTOM_CLAIM || 'https://unbound.se/admin'
const emailCustomClaim = process.env.EMAIL_CUSTOM_CLAIM || 'https://unbound.se/email'
const debug = Debug('app') const debug = Debug('app')
@@ -27,10 +28,29 @@ const corsOpts = (req, cb) => {
cb(null, { origin: req.headers.origin }) cb(null, { origin: req.headers.origin })
} }
const addCustomClaims = (email, customClaims, token) => {
const emailClaim = {}
emailClaim[emailCustomClaim] = email
return [...customClaims, emailClaim].reduce((acc, claim) => {
return {
...acc,
...claim
}
}, token)
}
const signToken = (token) => {
return jwt.sign(Buffer.from(JSON.stringify(token)), privateKey, {
algorithm: 'RS256',
keyid: thumbprint
})
}
// Configure our small auth0-mock-server // Configure our small auth0-mock-server
app.options('*', cors(corsOpts)) app.options('*', cors(corsOpts))
.use(cors()) .use(cors())
.use(bodyParser.json()) .use(bodyParser.json({ strict: false }))
.use(bodyParser.urlencoded({ extended: true })) .use(bodyParser.urlencoded({ extended: true }))
.use(cookieParser()) .use(cookieParser())
.use(express.static(`${__dirname}/public`)) .use(express.static(`${__dirname}/public`))
@@ -38,28 +58,49 @@ app.options('*', cors(corsOpts))
// This route can be used to generate a valid jwt-token. // This route can be used to generate a valid jwt-token.
app.post('/oauth/token', (req, res) => { app.post('/oauth/token', (req, res) => {
let date = Math.floor(Date.now() / 1000)
if (req.body.grant_type === 'client_credentials' && req.body.client_id) {
let accessToken = signToken({
iss: jwksOrigin,
aud: [audience],
sub: 'auth0|management',
iat: date,
exp: date + 7200,
azp: req.body.client_id
})
let idToken = signToken({
iss: jwksOrigin,
aud: req.body.client_id,
sub: 'auth0|management',
iat: date,
exp: date + 7200,
azp: req.body.client_id,
name: 'Management API'
})
debug('Signed token for management API')
res.json({
access_token: accessToken,
id_token: idToken,
scope: 'openid%20profile%20email',
expires_in: 7200,
token_type: 'Bearer'
})
} else if (req.body.code) {
const code = req.body.code const code = req.body.code
const session = sessions[code] const session = sessions[code]
let accessToken = signToken(addCustomClaims(session.email, session.customClaims, {
let date = Math.floor(Date.now() / 1000)
let accessToken = jwt.sign(Buffer.from(JSON.stringify({
iss: jwksOrigin, iss: jwksOrigin,
aud: [audience], aud: [audience],
sub: 'auth0|' + session.email, sub: 'auth0|' + session.email,
iat: date, iat: date,
exp: date + 7200, exp: date + 7200,
azp: session.clientId azp: session.clientId
})), privateKey, { }))
algorithm: 'RS256',
keyid: thumbprint
})
const token = session.customClaims.reduce((acc, claim) => { let idToken = signToken(addCustomClaims(session.email, session.customClaims, {
return {
...acc,
...claim
}
}, {
iss: jwksOrigin, iss: jwksOrigin,
aud: session.clientId, aud: session.clientId,
nonce: session.nonce, nonce: session.nonce,
@@ -69,14 +110,9 @@ app.post('/oauth/token', (req, res) => {
azp: session.clientId, azp: session.clientId,
name: 'Example Person', name: 'Example Person',
picture: 'https://cdn.playbuzz.com/cdn/5458360f-32ea-460e-a707-1a2d26760558/70bda687-cb84-4756-8a44-8cf735ed87b3.jpg' picture: 'https://cdn.playbuzz.com/cdn/5458360f-32ea-460e-a707-1a2d26760558/70bda687-cb84-4756-8a44-8cf735ed87b3.jpg'
}) }))
let idToken = jwt.sign(Buffer.from(JSON.stringify(token)), privateKey, {
algorithm: 'RS256',
keyid: thumbprint
})
debug('Signed token for ' + session.email) debug('Signed token for ' + session.email)
// res.json({ token });
res.json({ res.json({
access_token: accessToken, access_token: accessToken,
@@ -85,6 +121,10 @@ app.post('/oauth/token', (req, res) => {
expires_in: 7200, expires_in: 7200,
token_type: 'Bearer' token_type: 'Bearer'
}) })
} else {
res.status(401)
res.send('Missing client_id or client_secret')
}
}) })
// This route can be used to generate a valid jwt-token. // This route can be used to generate a valid jwt-token.
@@ -257,7 +297,7 @@ app.post('/issuer', (req, res) => {
} }
issuer = req.body.issuer issuer = req.body.issuer
jwksOrigin = `https://${issuer}/` jwksOrigin = `https://${issuer}/`
const { privateKey: key, certDer: der, thumbPrint: thumb, exponent: exp, modulus: mod } = cert(jwksOrigin) const { privateKey: key, certDer: der, thumbprint: thumb, exponent: exp, modulus: mod } = cert(jwksOrigin)
privateKey = key privateKey = key
certDer = der certDer = der
thumbprint = thumb thumbprint = thumb
@@ -267,6 +307,28 @@ app.post('/issuer', (req, res) => {
res.send('ok') res.send('ok')
}) })
app.get('/api/v2/users-by-email', (req, res) => {
res.json([])
})
app.post('/api/v2/users', (req, res) => {
const email = req.body.email
res.json({
user_id: `auth0|${email}`
})
})
app.post('/api/v2/tickets/password-change', (req, res) => {
res.json({
ticket: `https://some-url`
})
})
app.use(function(req, res, next) {
console.log('404', req.path)
res.status(404).send('error: 404 Not Found ' + req.path)
})
app.listen(3333, () => { app.listen(3333, () => {
debug('Auth0-Mock-Server listening on port 3333!') debug('Auth0-Mock-Server listening on port 3333!')
}) })
+52 -52
View File
@@ -1,7 +1,7 @@
const base64url = require('base64-url'); const base64url = require('base64-url')
const createHash = require('crypto').createHash; const createHash = require('crypto').createHash
const forge = require('node-forge'); const forge = require('node-forge')
const NodeRSA = require('node-rsa'); const NodeRSA = require('node-rsa')
const PRIVATE_KEY_PEM = const PRIVATE_KEY_PEM =
'-----BEGIN RSA PRIVATE KEY-----\n' + '-----BEGIN RSA PRIVATE KEY-----\n' +
@@ -30,7 +30,7 @@ const PRIVATE_KEY_PEM =
'JEgWBQKBgQDKD+2Yh1/rUzu15lbPH0JSpozUinuFjePieR/4n+5CtEUxWJ2f0WeK\n' + 'JEgWBQKBgQDKD+2Yh1/rUzu15lbPH0JSpozUinuFjePieR/4n+5CtEUxWJ2f0WeK\n' +
's4XWWf2qgUccjpiGju2UR840mgWROoZ8BfSTd5tg1F7bo0HMgu2hu0RIRpZcRhsA\n' + 's4XWWf2qgUccjpiGju2UR840mgWROoZ8BfSTd5tg1F7bo0HMgu2hu0RIRpZcRhsA\n' +
'Cd0GrJvf1t0QIdDCXAy+RpgU1SLSq4Q6Lomc0WA5C5nBw9RKEUOV9A==\n' + 'Cd0GrJvf1t0QIdDCXAy+RpgU1SLSq4Q6Lomc0WA5C5nBw9RKEUOV9A==\n' +
'-----END RSA PRIVATE KEY-----\n'; '-----END RSA PRIVATE KEY-----\n'
const PUBLIC_KEY_PEM = const PUBLIC_KEY_PEM =
'-----BEGIN PUBLIC KEY-----\n' + '-----BEGIN PUBLIC KEY-----\n' +
@@ -41,92 +41,92 @@ const PUBLIC_KEY_PEM =
'qXHP6AwKZXpT6jCzjzq9uyHxVcudqw6j0kQw48/A5A6AN5fIVy1cKnd0sKdqRX1N\n' + 'qXHP6AwKZXpT6jCzjzq9uyHxVcudqw6j0kQw48/A5A6AN5fIVy1cKnd0sKdqRX1N\n' +
'UqVoiOrO4jaDB1IdLD+YmRE/JjOHsWIMElYCPxKqnsNo6VCslGX/ziinArHhqRBr\n' + 'UqVoiOrO4jaDB1IdLD+YmRE/JjOHsWIMElYCPxKqnsNo6VCslGX/ziinArHhqRBr\n' +
'HwIDAQAB\n' + 'HwIDAQAB\n' +
'-----END PUBLIC KEY-----\n'; '-----END PUBLIC KEY-----\n'
const createCertificate = ({ const createCertificate = ({
publicKey, publicKey,
privateKey, privateKey,
jwksOrigin, jwksOrigin
}) => { }) => {
const cert = forge.pki.createCertificate(); const cert = forge.pki.createCertificate()
cert.publicKey = publicKey; cert.publicKey = publicKey
cert.serialNumber = '123'; cert.serialNumber = '123'
const attrs = [ const attrs = [
{ {
name: 'commonName', name: 'commonName',
value: `${jwksOrigin}`, value: `${jwksOrigin}`
}, }
]; ]
cert.validity.notBefore = new Date(); cert.validity.notBefore = new Date()
cert.validity.notAfter = new Date(); cert.validity.notAfter = new Date()
cert.validity.notAfter.setFullYear(cert.validity.notBefore.getFullYear() + 1); cert.validity.notAfter.setFullYear(cert.validity.notBefore.getFullYear() + 1)
cert.setSubject(attrs); cert.setSubject(attrs)
cert.setIssuer(attrs); cert.setIssuer(attrs)
cert.sign(privateKey); cert.sign(privateKey)
return forge.pki.certificateToPem(cert) return forge.pki.certificateToPem(cert)
}; }
const getCertThumbprint = (certificate) => { const getCertThumbprint = (certificate) => {
const shasum = createHash('sha1'); const shasum = createHash('sha1')
const der = Buffer.from(certificate).toString('binary'); const der = Buffer.from(certificate).toString('binary')
shasum.update(der); shasum.update(der)
return shasum.digest('base64') return shasum.digest('base64')
}; }
const createKeyPair = () => { const createKeyPair = () => {
const privateKey = forge.pki.privateKeyFromPem(PRIVATE_KEY_PEM); const privateKey = forge.pki.privateKeyFromPem(PRIVATE_KEY_PEM)
const publicKey = forge.pki.publicKeyFromPem(PUBLIC_KEY_PEM); const publicKey = forge.pki.publicKeyFromPem(PUBLIC_KEY_PEM)
return { return {
privateKey, privateKey,
publicKey, publicKey
} }
}; }
const bnToB64 = (bn) => { const bnToB64 = (bn) => {
let hex = BigInt(bn).toString(16); let hex = BigInt(bn).toString(16)
if (hex.length % 2) { if (hex.length % 2) {
hex = '0' + hex; hex = '0' + hex
} }
const bin = []; const bin = []
let i = 0; let i = 0
let d; let d
let b; let b
while (i < hex.length) { while (i < hex.length) {
d = parseInt(hex.slice(i, i + 2), 16); d = parseInt(hex.slice(i, i + 2), 16)
b = String.fromCharCode(d); b = String.fromCharCode(d)
bin.push(b); bin.push(b)
i += 2; i += 2
} }
return Buffer.from(bin.join(''), 'binary').toString('base64'); return Buffer.from(bin.join(''), 'binary').toString('base64')
}; }
const setup = (jwksOrigin) => { const setup = (jwksOrigin) => {
const {privateKey, publicKey} = createKeyPair(); const { privateKey, publicKey } = createKeyPair()
const certPem = createCertificate({ const certPem = createCertificate({
jwksOrigin, jwksOrigin,
privateKey, privateKey,
publicKey, publicKey
}); })
const certDer = forge.util.encode64( const certDer = forge.util.encode64(
forge.asn1 forge.asn1
.toDer(forge.pki.certificateToAsn1(forge.pki.certificateFromPem(certPem))) .toDer(forge.pki.certificateToAsn1(forge.pki.certificateFromPem(certPem)))
.getBytes() .getBytes()
); )
const thumbprint = base64url.encode(getCertThumbprint(certDer)); const thumbprint = base64url.encode(getCertThumbprint(certDer))
const helperKey = new NodeRSA(); const helperKey = new NodeRSA()
helperKey.importKey(forge.pki.privateKeyToPem(privateKey)); helperKey.importKey(forge.pki.privateKeyToPem(privateKey))
const {n: modulus, e: exponent} = helperKey.exportKey('components'); const { n: modulus, e: exponent } = helperKey.exportKey('components')
return { return {
privateKey: forge.pki.privateKeyToPem(privateKey), privateKey: forge.pki.privateKeyToPem(privateKey),
certDer: certDer, certDer,
thumbPrint: thumbprint, thumbprint: thumbprint.toString(),
exponent: bnToB64(exponent), exponent: bnToB64(exponent),
modulus: modulus.toString('base64') modulus: modulus.toString('base64')
} }
}; }
module.exports = setup; module.exports = setup
+4 -4
View File
@@ -12,17 +12,17 @@
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"base64-url": "^2.3.3", "base64-url": "^2.3.3",
"body-parser": "^1.20.0", "body-parser": "^1.20.1",
"buffer": "^6.0.3", "buffer": "^6.0.3",
"cookie-parser": "^1.4.6", "cookie-parser": "^1.4.6",
"cors": "^2.8.3", "cors": "^2.8.3",
"debug": "^4.3.4", "debug": "^4.3.4",
"express": "^4.17.3", "express": "^4.18.2",
"https-localhost": "^4.7.1", "https-localhost": "^4.7.1",
"jsonwebtoken": "^8.5.1", "jsonwebtoken": "^9.0.0",
"node-forge": "^1.3.1", "node-forge": "^1.3.1",
"node-rsa": "^1.1.1", "node-rsa": "^1.1.1",
"nodemon": "^2.0.15", "nodemon": "^2.0.20",
"serve-favicon": "^2.4.2" "serve-favicon": "^2.4.2"
} }
} }
+83 -777
View File
File diff suppressed because it is too large Load Diff