Skip to content

Instantly share code, notes, and snippets.

@flotwig
Last active June 18, 2019 18:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save flotwig/12b2f070fd627f48fa7681802e6c36de to your computer and use it in GitHub Desktop.
Save flotwig/12b2f070fd627f48fa7681802e6c36de to your computer and use it in GitHub Desktop.
node.js client certificate experiments
const assert = require('assert')
const Bluebird = require('bluebird')
const certyCb = require('certy')
const https = require('https')
const rp = require('request-promise')
const certy = Bluebird.promisifyAll(certyCb)
certy.createAsync()
.then((certs) => {
const { serverKey, serverCert, clientCert, clientKey, ca } = certs
const server = https.createServer({
key: serverKey,
cert: serverCert,
ca,
requestCert: true,
rejectUnauthorized: true,
}, (req, res) => {
res.writeHead(200)
res.end('hello world\n')
})
server.listen()
const { port } = server.address()
const baseOptions = {
cert: clientCert,
key: clientKey,
ca,
rejectUnauthorized: false,
resolveWithFullResponse: true,
}
// try normal pki
return rp.get(Object.assign({
url: `https://localhost:${port}/`,
}, baseOptions))
.then((res) => {
assert(res.statusCode === 200)
// try sending pki to a server that doesn't use it
return rp.get(Object.assign({
url: 'https://google.com/',
}, baseOptions))
})
.then((res) => {
assert(res.statusCode === 200)
// ditto
return rp.get(Object.assign({
url: 'https://example.com/',
}, baseOptions))
})
.then((res) => {
assert(res.statusCode === 200)
// try to send it to an http origin
return rp.get(Object.assign({
url: 'http://example.com/',
}, baseOptions))
})
.then((res) => {
assert(res.statusCode === 200)
// don't send a cert and key but the server wants one, should err
return rp.get(Object.assign({}, baseOptions, {
url: `https://localhost:${port}/`,
cert: undefined,
key: undefined,
}))
.then(() => {
throw new Error('should not reach')
})
.catch((e) => {
assert(e.message.includes('handshake failure'))
})
})
.then(() => {
// sending an array of certs and keys, only one of which matches
// this FAILS - probably the biggest question to adding this in Cypress will be
// how to send the correct cert/key for each request
return Bluebird.join(
certy.createAsync(),
certy.createAsync(),
(certs2, certs3) => {
return rp.get(Object.assign({}, baseOptions, {
url: `https://localhost:${port}/`,
cert: [clientCert, certs3.clientCert, certs2.clientCert],
key: [clientKey, certs3.clientKey, certs2.clientKey],
}))
}
)
})
.then(() => {
server.close()
})
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment