mirror of
https://github.com/gristlabs/grist-core.git
synced 2024-10-27 20:44:07 +00:00
(core) Google auth endpoint has not responded with auth code
Summary: Google Auth popup wasn't able to resolve origin from gristConfig. Moving this reponsability to server side, where it gets calculated from initial request. Test Plan: n/a Reviewers: dsagal, paulfitz Reviewed By: paulfitz Differential Revision: https://phab.getgrist.com/D2935
This commit is contained in:
parent
08295a696b
commit
291bcd17ff
@ -11,7 +11,7 @@ export async function makeXLSX(
|
|||||||
activeDoc: ActiveDoc,
|
activeDoc: ActiveDoc,
|
||||||
req: express.Request): Promise<ArrayBuffer> {
|
req: express.Request): Promise<ArrayBuffer> {
|
||||||
const content = await exportDoc(activeDoc, req);
|
const content = await exportDoc(activeDoc, req);
|
||||||
const data = await convertToExcel(content, req.host === 'localhost');
|
const data = await convertToExcel(content, req.hostname === 'localhost');
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1232,7 +1232,7 @@ export class FlexServer implements GristServer {
|
|||||||
|
|
||||||
public addGoogleAuthEndpoint() {
|
public addGoogleAuthEndpoint() {
|
||||||
if (this._check('google-auth')) { return; }
|
if (this._check('google-auth')) { return; }
|
||||||
const messagePage = makeMessagePage(this, getAppPathTo(this.appRoot, 'static'));
|
const messagePage = makeMessagePage(getAppPathTo(this.appRoot, 'static'));
|
||||||
addGoogleAuthEndpoint(this.app, messagePage);
|
addGoogleAuthEndpoint(this.app, messagePage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
import {auth} from '@googleapis/oauth2';
|
import { auth } from '@googleapis/oauth2';
|
||||||
import {ApiError} from 'app/common/ApiError';
|
import { ApiError } from 'app/common/ApiError';
|
||||||
import {parseSubdomain} from 'app/common/gristUrls';
|
import { parseSubdomain } from 'app/common/gristUrls';
|
||||||
import {expressWrap} from 'app/server/lib/expressWrap';
|
import { expressWrap } from 'app/server/lib/expressWrap';
|
||||||
import * as log from 'app/server/lib/log';
|
import * as log from 'app/server/lib/log';
|
||||||
import * as express from 'express';
|
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
|
* Google Auth Endpoint for performing server side authentication. More information can be found
|
||||||
@ -130,15 +130,18 @@ export function addGoogleAuthEndpoint(
|
|||||||
log.info(`GoogleAuth - auth handler at ${getFullAuthEndpointUrl()}`);
|
log.info(`GoogleAuth - auth handler at ${getFullAuthEndpointUrl()}`);
|
||||||
|
|
||||||
expressApp.get(authHandlerPath, expressWrap(async (req: express.Request, res: express.Response) => {
|
expressApp.get(authHandlerPath, expressWrap(async (req: express.Request, res: express.Response) => {
|
||||||
|
|
||||||
// Test if the code is in a query string. Google sends it back after user has given a concent for
|
// Test if the code is in a query string. Google sends it back after user has given a concent for
|
||||||
// our request. It is encrypted (with CLIENT_SECRET) and signed with redirect url.
|
// our request. It is encrypted (with CLIENT_SECRET) and signed with redirect url.
|
||||||
|
// In state query parameter we will receive an url that was send as part of the request to Google.
|
||||||
|
|
||||||
if (req.query.code) {
|
if (req.query.code) {
|
||||||
log.debug("GoogleAuth - response from Google with valid code");
|
log.debug("GoogleAuth - response from Google with valid code");
|
||||||
messagePage(req, res, { code: req.query.code });
|
messagePage(req, res, { code: req.query.code, origin: req.query.state });
|
||||||
} else if (req.query.error) {
|
} else if (req.query.error) {
|
||||||
log.debug("GoogleAuth - response from Google with error code", req.query.error);
|
log.debug("GoogleAuth - response from Google with error code", req.query.error);
|
||||||
if (req.query.error === "access_denied") {
|
if (req.query.error === "access_denied") {
|
||||||
messagePage(req, res, { error: req.query.error });
|
messagePage(req, res, { error: req.query.error, origin: req.query.state });
|
||||||
} else {
|
} else {
|
||||||
// This should not happen, either code or error is a mandatory query parameter.
|
// This should not happen, either code or error is a mandatory query parameter.
|
||||||
throw new ApiError("Error authenticating with Google", 500);
|
throw new ApiError("Error authenticating with Google", 500);
|
||||||
@ -146,13 +149,17 @@ export function addGoogleAuthEndpoint(
|
|||||||
} else {
|
} else {
|
||||||
const oAuth2Client = _googleAuthClient();
|
const oAuth2Client = _googleAuthClient();
|
||||||
const scope = req.query.scope || DRIVE_SCOPE;
|
const scope = req.query.scope || DRIVE_SCOPE;
|
||||||
|
// Create url for origin parameter for a popup window.
|
||||||
|
const origin = `${req.protocol}://${req.headers.host}`;
|
||||||
const authUrl = oAuth2Client.generateAuthUrl({
|
const authUrl = oAuth2Client.generateAuthUrl({
|
||||||
scope,
|
scope,
|
||||||
prompt: 'select_account'
|
prompt: 'select_account',
|
||||||
|
state: origin
|
||||||
});
|
});
|
||||||
log.debug(`GoogleAuth - redirecting to Google consent screen`, {
|
log.debug(`GoogleAuth - redirecting to Google consent screen`, {
|
||||||
authUrl,
|
authUrl,
|
||||||
scope
|
scope,
|
||||||
|
state: origin
|
||||||
});
|
});
|
||||||
res.redirect(authUrl);
|
res.redirect(authUrl);
|
||||||
}
|
}
|
||||||
|
@ -51,12 +51,10 @@ export function makeGristConfig(homeUrl: string|null, extra: Partial<GristLoadCo
|
|||||||
* Primary used for Google Auth Grist's endpoint, but can be used in future in any other server side
|
* Primary used for Google Auth Grist's endpoint, but can be used in future in any other server side
|
||||||
* authentication flow.
|
* authentication flow.
|
||||||
*/
|
*/
|
||||||
export function makeMessagePage(server: GristServer, staticDir: string) {
|
export function makeMessagePage(staticDir: string) {
|
||||||
return async (req: express.Request, resp: express.Response, message: any) => {
|
return async (req: express.Request, resp: express.Response, message: any) => {
|
||||||
const config = server.getGristConfig();
|
|
||||||
const fileContent = await fse.readFile(path.join(staticDir, "message.html"), 'utf8');
|
const fileContent = await fse.readFile(path.join(staticDir, "message.html"), 'utf8');
|
||||||
const content = fileContent
|
const content = fileContent
|
||||||
.replace("<!-- INSERT CONFIG -->", `<script>window.gristConfig = ${JSON.stringify(config)};</script>`)
|
|
||||||
.replace("<!-- INSERT MESSAGE -->", `<script>window.message = ${JSON.stringify(message)};</script>`);
|
.replace("<!-- INSERT MESSAGE -->", `<script>window.message = ${JSON.stringify(message)};</script>`);
|
||||||
resp.status(200).type('html').send(content);
|
resp.status(200).type('html').send(content);
|
||||||
};
|
};
|
||||||
|
@ -4,12 +4,9 @@
|
|||||||
<meta charset="utf8">
|
<meta charset="utf8">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<!-- INSERT CONFIG -->
|
|
||||||
<!-- INSERT MESSAGE -->
|
<!-- INSERT MESSAGE -->
|
||||||
<script>
|
<script>
|
||||||
// Determine proper home url for origin parameter
|
window.opener.postMessage(message, message.origin);
|
||||||
const origin = gristConfig.pathOnly ? gristConfig.homeUrl : `https://${gristConfig.org}${gristConfig.baseDomain}`;
|
|
||||||
window.opener.postMessage(message, origin);
|
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
Loading…
Reference in New Issue
Block a user