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
This commit is contained in:
Aiden Foxx
2022-11-01 21:44:17 +01:00
committed by GitHub
parent 2c0ad892b6
commit 05c045e9ff
2 changed files with 23 additions and 14 deletions

View File

@@ -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<string, any>): Promise<string> {
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,

View File

@@ -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<string, any>): Promise<string> {
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,