From f8e4fe54ba8141804c8422589190aa78592a5831 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaros=C5=82aw=20Sadzi=C5=84ski?= Date: Fri, 23 Jul 2021 00:21:09 +0200 Subject: [PATCH] (core) Fixing origin check during Google Authentication Summary: Fixing two bugs - Google Auth Endpoint wasn't resolving protocol in a correct way - Google Auth Popup was navigationg to endpoint url based on home url, which was diffent from current page origin Test Plan: n/a Reviewers: paulfitz Reviewed By: paulfitz Subscribers: paulfitz Differential Revision: https://phab.getgrist.com/D2937 --- app/client/ui/sendToDrive.ts | 3 +-- app/server/lib/GoogleAuth.ts | 13 +++++++------ app/server/lib/requestUtils.ts | 13 +++++++++++++ 3 files changed, 21 insertions(+), 8 deletions(-) diff --git a/app/client/ui/sendToDrive.ts b/app/client/ui/sendToDrive.ts index df982fdd..79a9c35d 100644 --- a/app/client/ui/sendToDrive.ts +++ b/app/client/ui/sendToDrive.ts @@ -1,5 +1,4 @@ import {get as getBrowserGlobals} from 'app/client/lib/browserGlobals'; -import {getHomeUrl} from 'app/client/models/AppModel'; import {reportError} from 'app/client/models/errors'; import {spinnerModal} from 'app/client/ui2018/modals'; import type { DocPageModel } from 'app/client/models/DocPageModel'; @@ -15,7 +14,7 @@ const G = getBrowserGlobals('window'); * https://developers.google.com/identity/protocols/oauth2/scopes */ function getGoogleAuthEndpoint(scope?: string) { - return new URL(`auth/google?scope=${scope || ''}`, getHomeUrl()).href; + return new URL(`auth/google?scope=${scope || ''}`, window.location.origin).href; } /** diff --git a/app/server/lib/GoogleAuth.ts b/app/server/lib/GoogleAuth.ts index 65142d03..31610837 100644 --- a/app/server/lib/GoogleAuth.ts +++ b/app/server/lib/GoogleAuth.ts @@ -1,10 +1,11 @@ -import { auth } from '@googleapis/oauth2'; -import { ApiError } from 'app/common/ApiError'; -import { parseSubdomain } from 'app/common/gristUrls'; -import { expressWrap } from 'app/server/lib/expressWrap'; +import {auth} from '@googleapis/oauth2'; +import {ApiError} from 'app/common/ApiError'; +import {parseSubdomain} from 'app/common/gristUrls'; +import {expressWrap} from 'app/server/lib/expressWrap'; import * as log from 'app/server/lib/log'; +import {getOriginUrl} from 'app/server/lib/requestUtils'; import * as express from 'express'; -import { URL } from 'url'; +import {URL} from 'url'; /** * Google Auth Endpoint for performing server side authentication. More information can be found @@ -150,7 +151,7 @@ export function addGoogleAuthEndpoint( const oAuth2Client = _googleAuthClient(); const scope = req.query.scope || DRIVE_SCOPE; // Create url for origin parameter for a popup window. - const origin = `${req.protocol}://${req.headers.host}`; + const origin = getOriginUrl(req); const authUrl = oAuth2Client.generateAuthUrl({ scope, prompt: 'select_account', diff --git a/app/server/lib/requestUtils.ts b/app/server/lib/requestUtils.ts index 41482abc..303a78c0 100644 --- a/app/server/lib/requestUtils.ts +++ b/app/server/lib/requestUtils.ts @@ -237,3 +237,16 @@ export function optIntegerParam(p: any): number|undefined { export interface RequestWithGristInfo extends Request { gristInfo?: string; } + +/** + * Returns original request origin. In case, when a client was connected to proxy + * or load balancer, it reads protocol from forwarded headers. + * More can be read on: + * https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-Proto + * https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/x-forwarded-headers.html + */ +export function getOriginUrl(req: Request) { + const host = req.headers.host!; + const protocol = req.get("X-Forwarded-Proto") || req.protocol; + return `${protocol}://${host}`; +}