le-acme-core.js/lib/register-new-account.js

138 lines
3.9 KiB
JavaScript
Raw Normal View History

2015-12-15 14:33:53 +00:00
/*!
* letiny
* Copyright(c) 2015 Anatol Sommer <anatol@anatol.at>
* Some code used from https://github.com/letsencrypt/boulder/tree/master/test/js
* MPL 2.0
*/
'use strict';
2015-12-15 22:35:42 +00:00
module.exports.create = function (deps) {
var NOOP=function () {}, log=NOOP;
var acmeRequest = deps.acmeRequest;
2016-08-01 09:53:50 +00:00
var RSA = deps.RSA;
2015-12-15 22:35:42 +00:00
var Acme = deps.Acme;
2015-12-15 14:33:53 +00:00
2015-12-15 22:35:42 +00:00
function registerNewAccount(options, cb) {
2015-12-15 14:33:53 +00:00
2015-12-15 22:35:42 +00:00
function register() {
2015-12-16 03:23:34 +00:00
state.acme.post(options.newRegUrl, {
2015-12-15 22:35:42 +00:00
resource:'new-reg',
contact:['mailto:'+options.email]
}, getTerms);
2015-12-15 14:33:53 +00:00
}
2015-12-15 22:35:42 +00:00
function getTerms(err, res) {
var links;
2015-12-15 14:33:53 +00:00
if (err) {
return handleErr(err, 'Registration request failed: ' + err.toString());
}
if (Math.floor(res.statusCode/100)!==2) {
2015-12-15 22:35:42 +00:00
return handleErr(err, 'Registration request failed: ' + res.body.toString('utf8'));
}
2015-12-15 14:33:53 +00:00
2015-12-15 22:35:42 +00:00
links=Acme.parseLink(res.headers.link);
if (!links || !('next' in links)) {
return handleErr(err, 'Server didn\'t provide information to proceed (1)');
}
2015-12-15 14:33:53 +00:00
2015-12-15 22:35:42 +00:00
state.registrationUrl=res.headers.location;
// TODO should we pass this along?
//state.newAuthorizationUrl=links.next;
state.termsRequired=('terms-of-service' in links);
if (state.termsRequired) {
2015-12-15 15:09:14 +00:00
state.termsUrl=links['terms-of-service'];
2015-12-15 22:35:42 +00:00
options.agreeToTerms(state.termsUrl, function (err, agree) {
if (err) {
return handleErr(err);
}
if (!agree) {
return handleErr(new Error("You must agree to the terms of use at '" + state.termsUrl + "'"));
}
state.agreeTerms = agree;
state.termsUrl=links['terms-of-service'];
log(state.termsUrl);
acmeRequest.create().get(state.termsUrl, getAgreement);
2015-12-15 22:35:42 +00:00
});
} else {
2015-12-16 03:23:34 +00:00
cb(null, null);
2015-12-15 22:35:42 +00:00
}
2015-12-15 14:33:53 +00:00
}
2015-12-15 22:35:42 +00:00
function getAgreement(err/*, res, body*/) {
if (err) {
return handleErr(err, 'Couldn\'t get agreement');
}
log('The CA requires your agreement to terms:\n'+state.termsUrl);
sendAgreement();
2015-12-15 14:33:53 +00:00
}
2015-12-15 22:35:42 +00:00
function sendAgreement() {
if (state.termsRequired && !state.agreeTerms) {
return handleErr(null, 'The CA requires your agreement to terms: '+state.termsUrl);
}
2015-12-15 14:33:53 +00:00
2015-12-15 22:35:42 +00:00
log('Posting agreement to: '+state.registrationUrl);
2015-12-15 14:33:53 +00:00
2015-12-15 22:35:42 +00:00
state.acme.post(state.registrationUrl, {
resource:'reg',
agreement:state.termsUrl
}, function(err, res, body) {
2015-12-16 03:23:34 +00:00
var data;
2015-12-15 22:35:42 +00:00
if (err || Math.floor(res.statusCode/100)!==2) {
return handleErr(err, 'Couldn\'t POST agreement back to server', body);
2015-12-16 03:23:34 +00:00
}
if ('string' === typeof body || '{' === body[0] || '{' === String.fromCharCode(body[0])) {
2015-12-16 03:23:34 +00:00
try {
data = JSON.parse(body.toString('utf8'));
2015-12-16 03:23:34 +00:00
} catch(e) {
cb(e);
return;
2015-12-16 03:23:34 +00:00
}
2015-12-15 22:35:42 +00:00
}
2015-12-16 03:23:34 +00:00
cb(null, data);
2015-12-15 22:35:42 +00:00
});
}
2015-12-15 14:33:53 +00:00
2015-12-15 22:35:42 +00:00
function handleErr(err, text, info) {
log(text, err, info);
cb(err || new Error(text));
}
2016-08-01 09:53:50 +00:00
var state = {};
if (!options.accountKeypair) {
2016-08-02 00:07:54 +00:00
if (!options.accountPrivateKeyPem) {
return handleErr(new Error("options.accountKeypair must be an object with `privateKeyPem` and/or `privateKeyJwk`"));
}
console.warn("'accountPrivateKeyPem' is deprecated. Use options.accountKeypair.privateKeyPem instead.");
options.accountKeypair = RSA.import({ privateKeyPem: options.accountPrivateKeyPem });
2016-08-01 09:53:50 +00:00
}
if (!options.agreeToTerms) {
cb(new Error("options.agreeToTerms must be function (tosUrl, fn => (err, true))"));
return;
}
if (!options.newRegUrl) {
cb(new Error("options.newRegUrl must be the a new registration url"));
return;
}
if (!options.email) {
cb(new Error("options.email must be an email"));
return;
}
state.accountKeypair = options.accountKeypair;
state.acme=new Acme(state.accountKeypair);
2016-08-01 09:53:50 +00:00
register();
2015-12-15 14:33:53 +00:00
}
2015-12-15 22:35:42 +00:00
return registerNewAccount;
};