This repository has been archived by the owner on May 10, 2019. It is now read-only.
/
verifier
executable file
·137 lines (117 loc) · 4.43 KB
/
verifier
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
#!/usr/bin/env node
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
const
util = require("util"),
path = require('path'),
url = require('url'),
fs = require('fs'),
express = require('express'),
computecluster = require('compute-cluster'),
metrics = require('../lib/metrics'),
heartbeat = require('../lib/heartbeat'),
logger = require('../lib/logging').logger,
config = require('../lib/configuration'),
shutdown = require('../lib/shutdown'),
statsd = require('../lib/statsd');
logger.info("verifier server starting up");
var app = express.createServer();
// setup health check / heartbeat (before logging)
heartbeat.setup(app);
// request to logger, dev formatted which omits personal data in the requests
app.use(express.logger({
format: config.get('express_log_format'),
stream: {
write: function(x) {
logger.info(typeof x === 'string' ? x.trim() : x);
}
}
}));
// limit all content bodies to 10kb, at which point we'll forcefully
// close down the connection.
app.use(express.limit("10kb"));
var statsd_config = config.get('statsd');
if (statsd_config && statsd_config.enabled) {
logger_statsd = require("connect-logger-statsd");
app.use(logger_statsd({
host: statsd_config.hostname || "localhost",
port: statsd_config.port || 8125,
prefix: statsd_config.prefix || "browserid.verifier."
}));
}
app.use(express.bodyParser());
try {
// explicitly relay VAR_PATH to children
process.env['VAR_PATH'] = config.get('var_path');
// allocate a compute cluster
var cc = new computecluster({
module: path.join(__dirname, "..", "lib", "verifier", "verifier-compute.js"),
max_processes: config.get('max_compute_processes')
}).on('error', function(e) {
logger.error("error detected in verification computation process! fatal: " + e.toString());
setTimeout(function() { process.exit(1); }, 0);
}).on('info', function(msg) {
logger.info("(compute cluster): " + msg);
}).on('debug', function(msg) {
logger.debug("(compute cluster): " + msg);
});
} catch(e) {
process.stderr.write("can't allocate compute cluster: " + e + "\n");
process.exit(1);
}
app.post('/verify', function(req, resp, next) {
req.body = req.body || {}
var assertion = (req.query && req.query.assertion) ? req.query.assertion : req. body.assertion;
var audience = (req.query && req.query.audience) ? req.query.audience : req.body.audience;
if (!(assertion && audience)) {
// why couldn't we extract these guys? Is it because the request parameters weren't encoded as we expect? GH-643
const want_ct = [ 'application/x-www-form-urlencoded', 'application/json' ];
try {
var ct = req.headers['content-type'];
if (ct.indexOf(';') != -1) ct = ct.substr(0, ct.indexOf(';'));
if (want_ct.indexOf(ct) == -1) throw "wrong content type";
} catch (e) {
return resp.json({ status: "failure", reason: "Content-Type expected to be one of: " + want_ct.join(", ") }, 415);
}
return resp.json({ status: "failure", reason: "need assertion and audience"}, 400);
}
var startTime = new Date();
cc.enqueue({
assertion: assertion,
audience: audience
}, function (err, r) {
var reqTime = new Date - startTime;
statsd.timing('assertion_verification_time', reqTime);
// consider "application" errors to be the same as harder errors
if (!err && r && r.error) err = r.error;
else if (!r || !r.success) err = "no response returned from child process";
if (err) {
resp.json({"status":"failure", reason: err}); //Could be 500 or 200 OK if invalid cert
metrics.report('verify', {
result: 'failure',
rp: audience
});
} else {
resp.json({
status : "okay",
email : r.success.email,
audience : audience, // NOTE: we return the audience formatted as the RP provided it, not normalized in any way.
expires : new Date(r.success.expires).valueOf(),
issuer: r.success.issuer
});
metrics.report('verify', {
result: 'success',
rp: r.success.audience
});
}
});
});
// shutdown nicely on signals
shutdown.handleTerminationSignals(app, function() {
cc.exit();
});
var bindTo = config.get('bind_to');
app.listen(bindTo.port, bindTo.host, function(conn) {
logger.info("running on http://" + app.address().address + ":" + app.address().port);
});