From 05c045e9ffb2c8cdc2bfaa98c83c33c596bbe934 Mon Sep 17 00:00:00 2001 From: Aiden Foxx Date: Tue, 1 Nov 2022 21:44:17 +0100 Subject: [PATCH] Handle "form_post" OAuth and OpenID responses (#16231) * Allow both POST and GET responses in OAuth flow * Be more explicit about which method we fetch OAuth data from * Removed unnecessary error handling in OAuth router * Fixed method check in OAuth router * Simplified method check * Added POST support to OpenID flow * Prefer redirect on OpenID POST to retain LAX cookie policy * Prefer redirect on OAuth2 POST to retain LAX cookie policy * Update api/src/auth/drivers/oauth2.ts * Update api/src/auth/drivers/openid.ts --- api/src/auth/drivers/oauth2.ts | 18 +++++++++++------- api/src/auth/drivers/openid.ts | 19 ++++++++++++------- 2 files changed, 23 insertions(+), 14 deletions(-) diff --git a/api/src/auth/drivers/oauth2.ts b/api/src/auth/drivers/oauth2.ts index d6a384932b..4100157bc9 100644 --- a/api/src/auth/drivers/oauth2.ts +++ b/api/src/auth/drivers/oauth2.ts @@ -1,6 +1,7 @@ import { BaseException } from '@directus/shared/exceptions'; import { parseJSON } from '@directus/shared/utils'; import { Router } from 'express'; +import bodyParser from 'body-parser'; import flatten from 'flat'; import jwt from 'jsonwebtoken'; import ms from 'ms'; @@ -103,8 +104,8 @@ export class OAuth2AuthDriver extends LocalAuthDriver { } async getUserID(payload: Record): Promise { - if (!payload.code || !payload.codeVerifier) { - logger.warn('[OAuth2] No code or codeVerifier in payload'); + if (!payload.code || !payload.codeVerifier || !payload.state) { + logger.warn('[OAuth2] No code, codeVerifier or state in payload'); throw new InvalidCredentialsException(); } @@ -254,6 +255,14 @@ export function createOAuth2AuthRouter(providerName: string): Router { respond ); + router.post( + '/callback', + bodyParser.urlencoded({ extended: false }), + (req, res) => { + res.redirect(303, `./callback?${new URLSearchParams(req.body)}`); + }, + respond + ); router.get( '/callback', asyncHandler(async (req, res, next) => { @@ -286,11 +295,6 @@ export function createOAuth2AuthRouter(providerName: string): Router { try { res.clearCookie(`oauth2.${providerName}`); - - if (!req.query.code || !req.query.state) { - logger.warn(`[OAuth2] Couldn't extract OAuth2 code or state from query: ${JSON.stringify(req.query)}`); - } - authResponse = await authenticationService.login(providerName, { code: req.query.code, codeVerifier: verifier, diff --git a/api/src/auth/drivers/openid.ts b/api/src/auth/drivers/openid.ts index 86dcb55687..d53678a2de 100644 --- a/api/src/auth/drivers/openid.ts +++ b/api/src/auth/drivers/openid.ts @@ -1,6 +1,7 @@ import { BaseException } from '@directus/shared/exceptions'; import { parseJSON } from '@directus/shared/utils'; import { Router } from 'express'; +import bodyParser from 'body-parser'; import flatten from 'flat'; import jwt from 'jsonwebtoken'; import ms from 'ms'; @@ -116,8 +117,8 @@ export class OpenIDAuthDriver extends LocalAuthDriver { } async getUserID(payload: Record): Promise { - if (!payload.code || !payload.codeVerifier) { - logger.warn('[OpenID] No code or codeVerifier in payload'); + if (!payload.code || !payload.codeVerifier || !payload.state) { + logger.warn('[OpenID] No code, codeVerifier or state in payload'); throw new InvalidCredentialsException(); } @@ -278,6 +279,15 @@ export function createOpenIDAuthRouter(providerName: string): Router { respond ); + router.post( + '/callback', + bodyParser.urlencoded({ extended: false }), + (req, res) => { + res.redirect(303, `./callback?${new URLSearchParams(req.body)}`); + }, + respond + ); + router.get( '/callback', asyncHandler(async (req, res, next) => { @@ -310,11 +320,6 @@ export function createOpenIDAuthRouter(providerName: string): Router { try { res.clearCookie(`openid.${providerName}`); - - if (!req.query.code || !req.query.state) { - logger.warn(`[OpenID] Couldn't extract OpenID code or state from query: ${JSON.stringify(req.query)}`); - } - authResponse = await authenticationService.login(providerName, { code: req.query.code, codeVerifier: verifier,