Created
April 3, 2021 17:24
-
-
Save Falci/8e12be1b9538c4521a3d312a02e4682d to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const fs = require('fs'); | |
const crypto = require('crypto'); | |
const decB64 = b64 => Buffer.from(b64, 'base64').toString('ascii'); | |
const encB64 = ascii => Buffer.from(ascii).toString('base64'); | |
const saveKeyToFile = (filename, key) => | |
fs.writeFileSync(filename, key.export({ type: 'pkcs8', format: 'pem' })); | |
const loadKeyFromFile = filename => loadRawKey(fs.readFileSync(filename)); | |
const loadRawKey = raw => crypto.createPrivateKey(raw); | |
const keyToPublicKey = key => crypto.createPublicKey(key).export({ type: 'spki', format: 'pem' }); | |
const fingerprint = key => crypto.createHash('sha256').update(keyToPublicKey(key)).digest('hex'); | |
const generateKey = () => | |
crypto.generateKeyPair('rsa', { | |
modulusLength: 4046, | |
privateKeyEncoding: { type: 'pkcs8', format: 'der' }, | |
}).privateKey; | |
const generateUrl = ({ id, state, callbackUrl }, key, deviceId) => { | |
const url = new URL(decB64(callbackUrl)); // b64 => str => url | |
const challenge = Buffer.from(state, 'base64'); // b64 => Buffer | |
const signed = crypto.sign('sha512', challenge, { | |
key, | |
padding: crypto.constants.RSA_PKCS1_PSS_PADDING, | |
saltLength: 64, | |
}); | |
const publicKey = keyToPublicKey(key); | |
const data = { | |
signed: encB64(signed.toString('base64')), // Buffer => b64 => b64 (https://github.com/namebasehq/handshake-id-manager/issues/6) | |
domain: id, // b64 | |
deviceId: encB64(deviceId), // str => b64 | |
publicKey: encB64(publicKey), // str => b64 | |
}; | |
url.hash = encB64(JSON.stringify(data)); // JSON => str => b64 | |
return url; | |
}; | |
module.exports = { | |
decB64, | |
encB64, | |
generateKey, | |
generateUrl, | |
keyToPublicKey, | |
loadKeyFromFile, | |
loadRawKey, | |
fingerprint, | |
saveKeyToFile, | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// The following is the code used to process the login request: | |
const { loadKeyFromFile, generateUrl } = require('./login-with-hns'); | |
// 1. Load the private key: | |
const key = loadKeyFromFile('my-private.key'); | |
// 2. Use the same deviceId: | |
const deviceId = 'my-device'; | |
// 3. Generate the url: | |
// id, state and callbackUrl should be in the same format as received in the URL hash: | |
const url = generateUrl({ id, state, callbackUrl }, key, deviceId); | |
// 4. Redirect | |
res.redirect(url.toString()); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// This is code to setup your name to use "Login with Handshake" | |
const { generateKey, saveKeyToFile, fingerprint } = require('./login-with-hns'); | |
// 0. For this example, we will login with the TLD: "example" | |
const name = 'example'; | |
// 1. The private key | |
const key = generateKey(); | |
// 2. Make a backup of your private key: | |
saveKeyToFile('my-private.key', key); | |
// 3. Create a custom deviceId: | |
const deviceId = 'my-device'; | |
// 4. Generate the Fingerprint | |
const fp = fingerprint(key); | |
// 5. Create a TXT record to store the fingerprint: | |
// my-device._auth.example. IN TXT "v=0;fingerprint=1790b098060455d8e2f110a8847a063221e3ef5060f0e103be1c42788d80983f" | |
console.log(`${deviceId}._auth.${name}. IN TXT "v=0;fingerprint=${fp}"`); | |
// 6. Create a TXT record to tell the OIDC where to login | |
// _idmanager.example. IN TXT v=0;url=https://example/ | |
console.log(`_idmanager.${name}. IN TXT v=0;url=https://${name}/`); | |
// 6.1. The OIDC will make a call to you like: | |
// https://example/#/login?state=YXBGdjdQcUpUdmQ3NU00YlVOaVVUWnpjcEstNWduMlNQMU9VSWR1eDg3UQ==&id=ZXhhbXBsZQ==&callbackUrl=aHR0cHM6Ly9vaWRjLm5hbWViYXNlLmlvL2xvZ2luL3VoeUd5LVh3Wk1KUlQxVS1jdGtNRS9jaGFsbGVuZ2U= | |
// Note this URL uses hash (#) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment