aboutsummaryrefslogtreecommitdiff
path: root/src/server
diff options
context:
space:
mode:
Diffstat (limited to 'src/server')
-rw-r--r--src/server/apis/google/GoogleApiServerUtils.ts51
-rw-r--r--src/server/database.ts5
-rw-r--r--src/server/index.ts3
3 files changed, 50 insertions, 9 deletions
diff --git a/src/server/apis/google/GoogleApiServerUtils.ts b/src/server/apis/google/GoogleApiServerUtils.ts
index 963c7736a..5714c9928 100644
--- a/src/server/apis/google/GoogleApiServerUtils.ts
+++ b/src/server/apis/google/GoogleApiServerUtils.ts
@@ -25,7 +25,8 @@ export namespace GoogleApiServerUtils {
'drive.file',
'photoslibrary',
'photoslibrary.appendonly',
- 'photoslibrary.sharing'
+ 'photoslibrary.sharing',
+ 'userinfo.profile'
];
export const parseBuffer = (data: Buffer) => JSON.parse(data.toString());
@@ -96,21 +97,61 @@ export namespace GoogleApiServerUtils {
});
};
- export const ProcessClientSideCode = async (information: CredentialInformation, authenticationCode: string): Promise<TokenResult> => {
+ export interface GoogleAuthenticationResult {
+ access_token: string;
+ avatar: string;
+ name: string;
+ }
+ export const ProcessClientSideCode = async (information: CredentialInformation, authenticationCode: string): Promise<GoogleAuthenticationResult> => {
const oAuth2Client = await RetrieveOAuthClient(information);
- return new Promise<TokenResult>((resolve, reject) => {
+ return new Promise<GoogleAuthenticationResult>((resolve, reject) => {
oAuth2Client.getToken(authenticationCode, async (err, token) => {
if (err || !token) {
reject(err);
return console.error('Error retrieving access token', err);
}
oAuth2Client.setCredentials(token);
- await Database.Auxiliary.GoogleAuthenticationToken.Write(information.userId, token);
- resolve({ token, client: oAuth2Client });
+ const enriched = injectUserInfo(token);
+ await Database.Auxiliary.GoogleAuthenticationToken.Write(information.userId, enriched);
+ const { given_name, picture } = enriched.userInfo;
+ resolve({
+ access_token: enriched.access_token!,
+ avatar: picture,
+ name: given_name
+ });
});
});
};
+ /**
+ * It's pretty cool: the credentials id_token is split into thirds by periods.
+ * The middle third contains a base64-encoded JSON string with all the
+ * user info contained in the interface below. So, we isolate that middle third,
+ * base64 decode with atob and parse the JSON.
+ * @param credentials the client credentials returned from OAuth after the user
+ * has executed the authentication routine
+ */
+ const injectUserInfo = (credentials: Credentials): EnrichedCredentials => {
+ const userInfo = JSON.parse(atob(credentials.id_token!.split(".")[1]));
+ return { ...credentials, userInfo };
+ };
+
+ export type EnrichedCredentials = Credentials & { userInfo: UserInfo };
+ export interface UserInfo {
+ at_hash: string;
+ aud: string;
+ azp: string;
+ exp: number;
+ family_name: string;
+ given_name: string;
+ iat: number;
+ iss: string;
+ locale: string;
+ name: string;
+ picture: string;
+ sub: string;
+ }
+
export const RetrieveCredentials = (information: CredentialInformation) => {
return new Promise<TokenResult>((resolve, reject) => {
readFile(information.credentialsPath, async (err, credentials) => {
diff --git a/src/server/database.ts b/src/server/database.ts
index 990441d5a..db86b472d 100644
--- a/src/server/database.ts
+++ b/src/server/database.ts
@@ -4,6 +4,7 @@ import { Opt } from '../new_fields/Doc';
import { Utils, emptyFunction } from '../Utils';
import { DashUploadUtils } from './DashUploadUtils';
import { Credentials } from 'google-auth-library';
+import { GoogleApiServerUtils } from './apis/google/GoogleApiServerUtils';
export namespace Database {
@@ -259,8 +260,8 @@ export namespace Database {
return SanitizedSingletonQuery<StoredCredentials>({ userId }, GoogleAuthentication, removeId);
};
- export const Write = async (userId: string, token: any) => {
- return Instance.insert({ userId, canAccess: [], ...token }, GoogleAuthentication);
+ export const Write = async (userId: string, enrichedCredentials: GoogleApiServerUtils.EnrichedCredentials) => {
+ return Instance.insert({ userId, canAccess: [], ...enrichedCredentials }, GoogleAuthentication);
};
export const Update = async (userId: string, access_token: string, expiry_date: number) => {
diff --git a/src/server/index.ts b/src/server/index.ts
index 86c226a21..010a851bc 100644
--- a/src/server/index.ts
+++ b/src/server/index.ts
@@ -958,8 +958,7 @@ app.get(RouteStore.readGoogleAccessToken, async (req, res) => {
app.post(RouteStore.writeGoogleAccessToken, async (req, res) => {
const userId = req.header("userId")!;
const information = { credentialsPath, userId };
- const { token } = await GoogleApiServerUtils.ProcessClientSideCode(information, req.body.authenticationCode);
- res.send(token.access_token);
+ res.send(await GoogleApiServerUtils.ProcessClientSideCode(information, req.body.authenticationCode));
});
const tokenError = "Unable to successfully upload bytes for all images!";