This repository has been archived by the owner on May 10, 2019. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 264
/
verifier
executable file
·157 lines (135 loc) · 4.89 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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
#!/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/. */
require('../lib/baseExceptions').addExceptionHandler();
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) {
var 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);
}
function doVerification(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' ];
var reason;
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) {
reason = "Content-Type expected to be one of: " + want_ct.join(", ");
metrics.report('verify', {
result: 'failure',
reason: reason,
rp: audience
});
return resp.json({ status: "failure", reason: reason}, 415);
}
reason = "need assertion and audience";
metrics.report('verify', {
result: 'failure',
reason: reason,
rp: audience
});
return resp.json({ status: "failure", reason: reason}, 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) {
statsd.increment("assertion_failure");
resp.json({"status":"failure", reason: err}); //Could be 500 or 200 OK if invalid cert
metrics.report('verify', {
result: 'failure',
reason: err,
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
});
}
});
}
app.post('/verify', doVerification);
app.post('/', doVerification);
// 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);
});