This repository has been archived by the owner on Aug 12, 2018. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2
/
google-oauth-serviceaccount.js
117 lines (96 loc) · 3.4 KB
/
google-oauth-serviceaccount.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
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
process.env.TZ = 'UTC';
const request = require('request');
const crypto = require('crypto');
const config = require('nconf');
const fs = require('fs');
const logger = require('./lib/logger');
logger.debug(new Date().toString());
var auth = function(callback) {
config.argv().env().file({
file: 'oauth-config.json'
});
config.defaults({
keyFile: "key.pem",
expiresInMinutes: 60,
claim:{
"iss":"yourProjectID@developer.gserviceaccount.com"
,"scope":"https://www.googleapis.com/auth/calendar"
,"aud":"https://accounts.google.com/o/oauth2/token"
}
});
var keyFile = config.get('keyFile');
if(!fs.existsSync(keyFile)){
logger.error("keyFile not found:"+keyFile);
process.exit(1);
}
var jwtHeader = {
alg: "RS256",
typ: "JWT"
};
var jwtHeaderB64 = base64urlEncode(JSON.stringify(jwtHeader));
logger.debug("Header:" + jwtHeaderB64);
//decode
logger.debug(new Buffer(jwtHeaderB64, 'base64').toString('ascii'));
// https://developers.google.com/google-apps/calendar/v3/reference/calendars/get
var iat = Math.floor(new Date().getTime() / 1000);
var exp = iat + (config.get('expiresInMinutes') * 60);
var jwtClaim = config.get('claim');
jwtClaim.exp = exp;
jwtClaim.iat = iat;
logger.debug(JSON.stringify(jwtClaim));
var jwtClaimB64 = base64urlEncode(JSON.stringify(jwtClaim));
logger.debug("Claim:" + jwtClaimB64);
var signatureInput = jwtHeaderB64 + '.' + jwtClaimB64;
logger.debug("Signature Input:" + signatureInput);
var JWT = null;
var signature = sign(signatureInput, keyFile);
logger.debug("Signature:" + signature);
JWT = signatureInput + '.' + signature;
logger.debug("JWT:"+JWT);
request.post({
url: 'https://accounts.google.com/o/oauth2/token',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
form: {
grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer',
assertion: JWT
}
}, function(err, res, body) {
if (err){
callback(err, null);
}else{
if (res.statusCode == 200) {
logger.info("STATUS:200");
callback(err, JSON.parse(body).access_token);
}else{
logger.warning('STATUS: ' + res.statusCode);
logger.debug('HEADERS: ' + JSON.stringify(res.headers));
logger.error('Response:\n' + body);
callback(new Error("failed to retrieve an access token"), body);
}
}
});
}
function sign(inStr, keyPath) {
var key = fs.readFileSync(keyPath);
if(key.length==0)
logger.warning("most likely invalid key file: " + keyPath);
var sig = crypto.createSign('RSA-SHA256').update(inStr).sign(key, 'base64');
//verification
var verifier = crypto.createVerify("RSA-SHA256");
verifier.update(inStr);
if(verifier.verify(key, sig, 'base64')){
logger.debug("signature verified with:"+keyPath);
}else{
logger.error("signature NOT verified with:"+keyPath);
}
return base64urlEscape(sig);
}
function base64urlEncode(str) {
return base64urlEscape(new Buffer(str).toString('base64'));
}
function base64urlEscape(str) {
return str.replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '');
}
module.exports.auth = auth;