This repository has been archived by the owner on Aug 16, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
validate.js
64 lines (53 loc) · 1.79 KB
/
validate.js
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
const got = require('got');
const jwt = require('jsonwebtoken');
// The authorization part
let certs;
let aud;
async function certificates() {
if (!certs) {
let response = await got('https://www.gstatic.com/iap/verify/public_key');
certs = JSON.parse(response.body);
}
return certs;
}
async function getMetadata(itemName) {
const endpoint = 'http://metadata.google.internal';
const path = '/computeMetadata/v1/project/';
const url = endpoint + path + itemName;
let response = await got(url, {
headers: {'Metadata-Flavor': 'Google'},
});
return response.body;
}
async function audience() {
if (!aud) {
let project_number = await getMetadata('numeric-project-id');
let project_id = await getMetadata('project-id');
aud = '/projects/' + project_number + '/apps/' + project_id;
}
return aud;
}
async function validateAssertion(assertion) {
if (!assertion) {
return {};
}
// Decode the header to determine which certificate signed the assertion
const encodedHeader = assertion.split('.')[0];
const decodedHeader = Buffer.from(encodedHeader, 'base64').toString('utf8');
const header = JSON.parse(decodedHeader);
const keyId = header.kid;
// Fetch the current certificates and verify the signature on the assertion
const certs = await certificates();
const payload = jwt.verify(assertion, certs[keyId]);
// Check that the assertion's audience matches ours
const aud = await audience();
if (payload.aud !== aud) {
throw new Error('Audience mismatch. {$payload.aud} should be {$aud}.');
}
// Return the two relevant pieces of information
return {
email: payload.email,
sub: payload.sub,
};
}
exports.validateAssertion = validateAssertion;