aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSam Wilkins <samwilkins333@gmail.com>2019-10-27 18:46:57 -0400
committerSam Wilkins <samwilkins333@gmail.com>2019-10-27 18:46:57 -0400
commitfeec691275ec83e4ddd8fd8ea803f004a371cf11 (patch)
tree80ab25479622a244fc058174c961917d94c9823b /src
parente6bd33867cc7f7185575666255369f55cacb9856 (diff)
refactoring oauth2 client use in google api serverside
Diffstat (limited to 'src')
-rw-r--r--src/server/apis/google/GoogleApiServerUtils.ts87
-rw-r--r--src/server/index.ts10
2 files changed, 40 insertions, 57 deletions
diff --git a/src/server/apis/google/GoogleApiServerUtils.ts b/src/server/apis/google/GoogleApiServerUtils.ts
index 6093197f1..c0824cfb7 100644
--- a/src/server/apis/google/GoogleApiServerUtils.ts
+++ b/src/server/apis/google/GoogleApiServerUtils.ts
@@ -1,7 +1,6 @@
import { google } from "googleapis";
-import { createInterface } from "readline";
-import { readFile, writeFile } from "fs";
-import { OAuth2Client, Credentials } from "google-auth-library";
+import { readFile } from "fs";
+import { OAuth2Client, Credentials, OAuth2ClientOptions } from "google-auth-library";
import { Opt } from "../../../new_fields/Doc";
import { GlobalOptions } from "googleapis-common";
import { GaxiosResponse } from "gaxios";
@@ -31,6 +30,8 @@ export namespace GoogleApiServerUtils {
'userinfo.profile'
];
+ const ClientMapping = new Map<String, OAuth2Client>();
+
export const parseBuffer = (data: Buffer) => JSON.parse(data.toString());
export enum Service {
@@ -51,11 +52,11 @@ export namespace GoogleApiServerUtils {
export type Endpoint = { get: ApiHandler, create: ApiHandler, batchUpdate: ApiHandler };
export type EndpointParameters = GlobalOptions & { version: "v1" };
- export const GetEndpoint = (sector: string, paths: CredentialInformation) => {
+ export const GetEndpoint = (sector: string, userId: string) => {
return new Promise<Opt<Endpoint>>(resolve => {
- RetrieveCredentials(paths).then(authentication => {
+ authorize(userId).then(({ client: auth }) => {
let routed: Opt<Endpoint>;
- let parameters: EndpointParameters = { auth: authentication.client, version: "v1" };
+ let parameters: EndpointParameters = { auth, version: "v1" };
switch (sector) {
case Service.Documents:
routed = google.docs(parameters).documents;
@@ -69,16 +70,17 @@ export namespace GoogleApiServerUtils {
});
};
- export const RetrieveAccessToken = (information: CredentialInformation) => {
+ export const RetrieveAccessToken = (userId: string): Promise<string> => {
return new Promise<string>((resolve, reject) => {
- RetrieveCredentials(information).then(
- credentials => resolve(credentials.token.access_token!),
+ authorize(userId).then(
+ ({ token: { access_token } }) => resolve(access_token!),
error => reject(`Error: unable to authenticate Google Photos API request.\n${error}`)
);
});
};
- let AuthorizationManager: OAuth2Client;
+ let installed: OAuth2ClientOptions;
+ let worker: OAuth2Client;
export const LoadOAuthClient = async () => {
return new Promise<void>((resolve, reject) => {
@@ -87,15 +89,17 @@ export namespace GoogleApiServerUtils {
reject(err);
return console.log('Error loading client secret file:', err);
}
- const { client_secret, client_id, redirect_uris } = parseBuffer(credentials).installed;
- AuthorizationManager = new google.auth.OAuth2(client_id, client_secret, redirect_uris[0]);
+ installed = parseBuffer(credentials).installed;
+ worker = new google.auth.OAuth2(installed);
resolve();
});
});
};
+ const generateClient = () => new google.auth.OAuth2(installed);
+
export const GenerateAuthenticationUrl = async (information: CredentialInformation) => {
- return AuthorizationManager.generateAuthUrl({
+ return worker.generateAuthUrl({
access_type: 'offline',
scope: SCOPES.map(relative => prefix + relative),
});
@@ -106,16 +110,15 @@ export namespace GoogleApiServerUtils {
avatar: string;
name: string;
}
- export const ProcessClientSideCode = async (information: CredentialInformation, authenticationCode: string): Promise<GoogleAuthenticationResult> => {
+ export const ProcessClientSideCode = async (userId: string, authenticationCode: string): Promise<GoogleAuthenticationResult> => {
return new Promise<GoogleAuthenticationResult>((resolve, reject) => {
- AuthorizationManager.getToken(authenticationCode, async (err, token) => {
+ worker.getToken(authenticationCode, async (err, token) => {
if (err || !token) {
reject(err);
return console.error('Error retrieving access token', err);
}
- AuthorizationManager.setCredentials(token);
const enriched = injectUserInfo(token);
- await Database.Auxiliary.GoogleAuthenticationToken.Write(information.userId, enriched);
+ await Database.Auxiliary.GoogleAuthenticationToken.Write(userId, enriched);
const { given_name, picture } = enriched.userInfo;
resolve({
access_token: enriched.access_token!,
@@ -155,57 +158,39 @@ export namespace GoogleApiServerUtils {
sub: string;
}
- export const RetrieveCredentials = (information: CredentialInformation) => {
- return new Promise<TokenResult>((resolve, reject) => {
- readFile(information.credentialsPath, async (err, credentials) => {
- if (err) {
- reject(err);
- return console.log('Error loading client secret file:', err);
+ export const authorize = async (userId: string): Promise<AuthenticationResult> => {
+ return Database.Auxiliary.GoogleAuthenticationToken.Fetch(userId).then(token => {
+ return new Promise<AuthenticationResult>((resolve, reject) => {
+ const client = generateClient();
+ if (token!.expiry_date! < new Date().getTime()) {
+ // Token has expired, so submitting a request for a refreshed access token
+ return refreshToken(token!, client, userId).then(resolve, reject);
}
- authorize(parseBuffer(credentials), information.userId).then(resolve, reject);
+ // Authentication successful!
+ client.setCredentials(token!);
+ resolve({ token: token!, client });
});
});
};
- export const RetrievePhotosEndpoint = (paths: CredentialInformation) => {
+ export const RetrievePhotosEndpoint = (userId: string) => {
return new Promise<any>((resolve, reject) => {
- RetrieveAccessToken(paths).then(
+ RetrieveAccessToken(userId).then(
token => resolve(new Photos(token)),
reject
);
});
};
- type TokenResult = { token: Credentials, client: OAuth2Client };
- /**
- * Create an OAuth2 client with the given credentials, and returns the promise resolving to the authenticated client
- * @param {Object} credentials The authorization client credentials.
- */
- export function authorize(credentials: any, userId: string): Promise<TokenResult> {
- const { client_secret, client_id, redirect_uris } = credentials.installed;
- const oAuth2Client = new google.auth.OAuth2(client_id, client_secret, redirect_uris[0]);
- return new Promise<TokenResult>((resolve, reject) => {
- // Attempting to authorize user (${userId})
- Database.Auxiliary.GoogleAuthenticationToken.Fetch(userId).then(token => {
- if (token!.expiry_date! < new Date().getTime()) {
- // Token has expired, so submitting a request for a refreshed access token
- return refreshToken(token!, client_id, client_secret, oAuth2Client, userId).then(resolve, reject);
- }
- // Authentication successful!
- oAuth2Client.setCredentials(token!);
- resolve({ token: token!, client: oAuth2Client });
- });
- });
- }
+ type AuthenticationResult = { token: Credentials, client: OAuth2Client };
const refreshEndpoint = "https://oauth2.googleapis.com/token";
- const refreshToken = (credentials: Credentials, client_id: string, client_secret: string, oAuth2Client: OAuth2Client, userId: string) => {
- return new Promise<TokenResult>(resolve => {
+ const refreshToken = (credentials: Credentials, oAuth2Client: OAuth2Client, userId: string) => {
+ return new Promise<AuthenticationResult>(resolve => {
let headerParameters = { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } };
let queryParameters = {
refreshToken: credentials.refresh_token,
- client_id,
- client_secret,
+ ...installed,
grant_type: "refresh_token"
};
let url = `${refreshEndpoint}?${qs.stringify(queryParameters)}`;
diff --git a/src/server/index.ts b/src/server/index.ts
index 384800f23..3220a9533 100644
--- a/src/server/index.ts
+++ b/src/server/index.ts
@@ -564,10 +564,10 @@ function routeSetter(router: RouteManager) {
router.addSupervisedRoute({
method: Method.POST,
subscription: new RouteSubscriber(RouteStore.googleDocs).add("sector", "action"),
- onValidation: ({ req, res }) => {
+ onValidation: ({ req, res, user }) => {
let sector: GoogleApiServerUtils.Service = req.params.sector as GoogleApiServerUtils.Service;
let action: GoogleApiServerUtils.Action = req.params.action as GoogleApiServerUtils.Action;
- GoogleApiServerUtils.GetEndpoint(GoogleApiServerUtils.Service[sector], { credentialsPath, userId: req.headers.userId as string }).then(endpoint => {
+ GoogleApiServerUtils.GetEndpoint(GoogleApiServerUtils.Service[sector], user.id).then(endpoint => {
let handler = EndpointHandlerMap.get(action);
if (endpoint && handler) {
let execute = handler(endpoint, req.body).then(
@@ -592,7 +592,7 @@ function routeSetter(router: RouteManager) {
if (!token) {
return res.send(await GoogleApiServerUtils.GenerateAuthenticationUrl(information));
}
- GoogleApiServerUtils.RetrieveAccessToken(information).then(token => res.send(token));
+ GoogleApiServerUtils.RetrieveAccessToken(userId).then(token => res.send(token));
}
});
@@ -600,9 +600,7 @@ function routeSetter(router: RouteManager) {
method: Method.POST,
subscription: RouteStore.writeGoogleAccessToken,
onValidation: async ({ user, req, res }) => {
- const userId = user.id;
- const information = { credentialsPath, userId };
- res.send(await GoogleApiServerUtils.ProcessClientSideCode(information, req.body.authenticationCode));
+ res.send(await GoogleApiServerUtils.ProcessClientSideCode(user.id, req.body.authenticationCode));
}
});