Skip to content

Instantly share code, notes, and snippets.

@robbywashere-zz
Created July 4, 2018 10:27
Show Gist options
  • Save robbywashere-zz/6cf9d72d3301deb686f7813e2be4efe0 to your computer and use it in GitHub Desktop.
Save robbywashere-zz/6cf9d72d3301deb686f7813e2be4efe0 to your computer and use it in GitHub Desktop.
get google api auth tokens with client_id and client_secret
const CLIENT_ID = <CLIENT_ID>;
const CLIENT_SECRET = <CLIENT_SECRET>;
// Hardcoded dummy redirect URI for non-web apps.
const REDIRECT_URI = 'urn:ietf:wg:oauth:2.0:oob';
// The URL root for accessing Google Accounts.
const GOOGLE_ACCOUNTS_BASE_URL = 'https://accounts.google.com';
const path = require('path');
const { URL, parse: parseURL } = require('url');
const https = require('https');
const readline = require('readline');
const querystring = require('querystring');
const OAUTH51SAFE = '~-._';
const specialEncoder = (safe) => (str) => str.split('').map(chr=>((!(safe.indexOf(chr)<0) || !/[^a-zA-Z0-9]/.test(chr)) ? chr : '%'+chr.charCodeAt(0).toString(16))).join('');
const encodeSpecialFormObj = (obj)=>querystring.stringify(obj, null, null,{ encodeURIComponent: specialEncoder(OAUTH51SAFE) });
function postFormGetJson(formUrl, data) {
const url = parseURL(formUrl.toString());
const encodedData = encodeSpecialFormObj(data);
const options = {
hostname: url.host,
port: 443,
path: url.path,
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': encodedData.length
}
};
return new Promise( (resolve,reject) => {
let data = '';
const request = https.request(options, resp => {
if (resp.statusCode >= 400) {
let err = new Error(`http error ${resp.statusCode}`);
err.statusCode = resp.statusCode;
reject(err);
}
resp.on('data', (chunk) => {
data += chunk;
});
resp.on('end', ()=>{
try {
resolve(JSON.parse(data.toString()));
} catch (e) {
let err = new Error(`Unable to parse JSON from ${url}`);
err.statusCode = resp.statusCode;
reject(err);
};
});
})
.on('error', (e) => reject(e))
request.write(encodedData);
})
}
function paramifyURL({ url, params }) {
const nurl = new URL(url.toString()); //clone url, because not mutate functions es bueno
Object.entries(params).forEach(([key, value]) => nurl.searchParams.append(key, value));
return nurl;
}
function authTokens(clientId, clientSecret, authCode) {
const url = new URL('o/oauth2/token', GOOGLE_ACCOUNTS_BASE_URL);
const params = {
client_id: clientId,
client_secret: clientSecret,
redirect_uri: REDIRECT_URI,
code: authCode,
grant_type: 'authorization_code',
};
return postFormGetJson(url, params);
}
function genPermitUrl(clientId, scope = 'https://mail.google.com/') {
const url = new URL('o/oauth2/auth', GOOGLE_ACCOUNTS_BASE_URL);
const params = {
client_id: clientId,
redirect_uri: REDIRECT_URI,
scope,
response_type: 'code',
}
return paramifyURL({ url, params }).href
}
function prompt(msg){
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
return new Promise( resolve => {
rl.question(`${msg}:`, answer => {
rl.close();
resolve(answer.replace(/\n$/, ''));
});
})
}
if (require.main === module) {
(async function main(){
const permitUrl = genPermitUrl(CLIENT_ID);
process.stdout.write(`* To authorize token, visit this url and follow the directions:\n\n-- ${permitUrl}\n\n`);
const authCode = await prompt('Enter verification code');
try {
let codez = await authTokens(CLIENT_ID,CLIENT_SECRET, authCode);
process.stdout.write(JSON.stringify(codez,null,4));
} catch(e) {
console.error('Could not retrieve tokens!',e);
}
})()
}
module.exports = { GeneratePermitUrl: genPermitUrl, FetchAuthTokens: authTokens }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment