Skip to content

Instantly share code, notes, and snippets.

@seanmonstar
Last active December 22, 2015 20:58
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save seanmonstar/6529756 to your computer and use it in GitHub Desktop.
Save seanmonstar/6529756 to your computer and use it in GitHub Desktop.
const jwcrypto = require('jwcrypto');
require('jwcrypto/lib/algs/ds');
require('jwcrypto/lib/algs/rs');
exports.sign = function sign(options, callback) {
var pubKey = jwcrypto.loadPublicKey(options.pubkey);
var privKey = jwcrypto.loadSecretKey(options.privkey);
var expiration = new Date();
var iat = new Date();
expiration.setTime(new Date().valueOf() + (options.duration * 1000));
// Set issuedAt to 10 seconds ago. Pads for verifier clock skew
iat.setTime(iat.valueOf() - (10 * 1000));
jwcrypto.cert.sign(
{ publicKey: pubKey, principal: { email: options.email } },
{ issuer: options.hostname, issuedAt: iat, expiresAt: expiration },
null,
privKey,
callback);
};
{
"name": "yourApp",
"version": "1.0",
"private": true,
"dependencies": {
"client-sessions": "0.3.x",
"express": "3.x",
"jwcrypto": "0.4.x"
}
}
const fs = require('fs');
const express = require('express');
const jwcrypto = require('jwcrypto');
const cert = require('./cert');
const clientSessions = require('client-sessions');
require('jwcrypto/lib/algs/rs');
require('jwcrypto/lib/algs/ds');
const PRIV_KEY = fs.readFileSync('/path/to/private/key').toString();
const app = express();
app.use(function(req, res, next) {
req.connection.proxySecure = true;
res.setHeader('Strict-Transport-Security',
'max-age=10886400; includeSubdomains');
next();
});
app.use(clientSessions({
cookieName: 'session',
secret: 'your secret here',
duration: 1000 * 60 * 60, // 1hour? longer?
cookie: {
secure: true
}
}));
app.use(express.csrf()); // you'll need some way to tell your html pages about this csrf token to POST back
const EMAIL = "some@example.com";
const PASSWORD = "password";
app.post('/persona/auth', function(req, res) {
if (req.body.email === EMAIL && req.body.password === PASSWORD) {
req.session.email = EMAIL;
res.send(200);
} else {
res.send(401);
}
});
app.post('/persona/certify', function(req, res) {
// you need to validate req.body parameters here
// 0. that the request is coming from someone who has authority to make it
// - you'd likely need to store a session from the /auth route, and check it here
if (req.session.email !== EMAIL) {
return res.send(401);
}
// 1. that `pubkey` is a public key
// 2. that `email` is correct
cert.sign({
privkey: PRIV_KEY,
hostname: 'your.host.name',
duration: Math.min(req.body.duration, 1000 * 60 * 60 * 24), // max of a day
pubkey: req.body.pubkey,
email: EMAIL
}, function onCert(err, cert) {
if (err) {
return res.send(500, err);
}
res.json({
cert: cert
});
});
});
});
app.listen(1337, '127.0.0.1'); // use whichever you need
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment