From d3caa0d1474c3089f71af40facee7eb2c2f30957 Mon Sep 17 00:00:00 2001 From: Cellebyte Date: Sun, 2 Jun 2024 00:41:01 +0200 Subject: [PATCH 1/2] Added changes from @nicolashenry out of \#9248 --- dev-helpers/oauth2-redirect.html | 53 +++++++------------------------- src/core/oauth2-authorize.js | 48 +++++++++++++++++++++++++++-- src/core/plugins/auth/actions.js | 17 ++++++++++ 3 files changed, 73 insertions(+), 45 deletions(-) diff --git a/dev-helpers/oauth2-redirect.html b/dev-helpers/oauth2-redirect.html index 87a2eed8f5e..6bd294091d3 100644 --- a/dev-helpers/oauth2-redirect.html +++ b/dev-helpers/oauth2-redirect.html @@ -1,15 +1,13 @@ - - + + \ No newline at end of file diff --git a/src/core/oauth2-authorize.js b/src/core/oauth2-authorize.js index 6ec41c244d5..96e212b66a2 100644 --- a/src/core/oauth2-authorize.js +++ b/src/core/oauth2-authorize.js @@ -122,11 +122,53 @@ export default function authorize ( { auth, authActions, errActions, configs, au callback = authActions.authorizeAccessCodeWithFormParams } - authActions.authPopup(url, { + const oauth2 = { auth: auth, state: state, redirectUrl: redirectUrl, callback: callback, - errCb: errActions.newAuthErr - }) + errCb: errActions.newAuthErr, + handleAuth: (qp) => { + const isValid = qp.state === oauth2.state + + if (( + oauth2.auth.schema.get("flow") === "accessCode" || + oauth2.auth.schema.get("flow") === "authorizationCode" || + oauth2.auth.schema.get("flow") === "authorization_code" + ) && !oauth2.auth.code) { + if (!isValid) { + oauth2.errCb({ + authId: oauth2.auth.name, + source: "auth", + level: "warning", + message: "Authorization may be unsafe, passed state was changed in server Passed state wasn't returned from auth server" + }) + } + + if (qp.code) { + delete oauth2.state + oauth2.auth.code = qp.code + oauth2.callback({auth: oauth2.auth, redirectUrl: redirectUrl}) + } else { + let oauthErrorMsg + if (qp.error) { + oauthErrorMsg = "["+qp.error+"]: " + + (qp.error_description ? qp.error_description+ ". " : "no accessCode received from the server. ") + + (qp.error_uri ? "More info: "+qp.error_uri : "") + } + + oauth2.errCb({ + authId: oauth2.auth.name, + source: "auth", + level: "error", + message: oauthErrorMsg || "[Authorization failed]: no accessCode received from the server" + }) + } + } else { + oauth2.callback({auth: oauth2.auth, token: qp, isValid: isValid, redirectUrl: redirectUrl}) + } + } + } + + authActions.authPopup(url, oauth2) } diff --git a/src/core/plugins/auth/actions.js b/src/core/plugins/auth/actions.js index 799e9fc0638..cffcce9f3a3 100644 --- a/src/core/plugins/auth/actions.js +++ b/src/core/plugins/auth/actions.js @@ -51,6 +51,10 @@ export const preAuthorizeImplicit = (payload) => ( { authActions, errActions } ) // remove oauth2 property from window after redirect from authentication delete win.swaggerUIRedirectOauth2 + if (win.oauth2Channel) { + win.oauth2Channel.close() + delete win.oauth2Channel + } if ( flow !== "accessCode" && !isValid ) { errActions.newAuthErr( { @@ -284,5 +288,18 @@ export const persistAuthorizationIfNeeded = () => ( { authSelectors, getConfigs export const authPopup = (url, swaggerUIRedirectOauth2) => ( ) => { win.swaggerUIRedirectOauth2 = swaggerUIRedirectOauth2 + if (win.oauth2Channel) { + win.oauth2Channel.close() + } + const oauth2Channel = new BroadcastChannel("oauth2_channel") + oauth2Channel.addEventListener("message", event => { + const data = event.data + const state = data ? data.state : undefined + if (state === swaggerUIRedirectOauth2.state) { + swaggerUIRedirectOauth2.handleAuth(data) + } + }) + win.oauth2Channel = oauth2Channel + win.open(url) } From 3442d4311669556dee1e42df9a15e552b937ec5b Mon Sep 17 00:00:00 2001 From: Cellebyte Date: Wed, 7 May 2025 22:22:51 +0200 Subject: [PATCH 2/2] Added suggested fix for npm run test from @ppena-LiveData --- package-lock.json | 8 ++++++++ package.json | 3 ++- test/unit/core/plugins/auth/actions.js | 5 +++++ 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/package-lock.json b/package-lock.json index 8a00add79c2..1c1aab01159 100644 --- a/package-lock.json +++ b/package-lock.json @@ -66,6 +66,7 @@ "babel-plugin-module-resolver": "=5.0.2", "babel-plugin-transform-react-remove-prop-types": "=0.4.24", "body-parser": "^1.19.0", + "broadcastchannel-polyfill": "=1.0.1", "buffer": "^6.0.3", "cheerio": "=1.0.0", "cors": "^2.8.5", @@ -8027,6 +8028,13 @@ "node": ">=8" } }, + "node_modules/broadcastchannel-polyfill": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/broadcastchannel-polyfill/-/broadcastchannel-polyfill-1.0.1.tgz", + "integrity": "sha512-iooPAN913j4xfrIu5o+mDaks9UUDOBfgjn8SsuzysfXr/X+f8m9y5t8c5rAbW6P0LdUXBJx33zwN4Cs6b9BGRw==", + "dev": true, + "license": "Unlicense" + }, "node_modules/browserslist": { "version": "4.24.4", "dev": true, diff --git a/package.json b/package.json index c2601a26662..4deaaaedb7f 100644 --- a/package.json +++ b/package.json @@ -130,6 +130,7 @@ "babel-plugin-module-resolver": "=5.0.2", "babel-plugin-transform-react-remove-prop-types": "=0.4.24", "body-parser": "^1.19.0", + "broadcastchannel-polyfill": "=1.0.1", "buffer": "^6.0.3", "cheerio": "=1.0.0", "cors": "^2.8.5", @@ -171,9 +172,9 @@ "oauth2-server": "^2.4.1", "open": "^10.1.0", "postcss": "^8.5.3", - "postcss-scss": "^4.0.9", "postcss-loader": "^8.1.1", "postcss-preset-env": "^10.1.6", + "postcss-scss": "^4.0.9", "prettier": "^3.5.3", "process": "^0.11.10", "react-refresh": "^0.17.0", diff --git a/test/unit/core/plugins/auth/actions.js b/test/unit/core/plugins/auth/actions.js index d9c751be6d5..6260405671c 100644 --- a/test/unit/core/plugins/auth/actions.js +++ b/test/unit/core/plugins/auth/actions.js @@ -1,3 +1,5 @@ +import { BroadcastChannel } from "broadcastchannel-polyfill" +import { MessageChannel } from "node:worker_threads" import { Map } from "immutable" import win from "core/window" import { @@ -10,6 +12,9 @@ import { } from "core/plugins/auth/actions" import {authorizeAccessCodeWithBasicAuthentication, authPopup} from "../../../../../src/core/plugins/auth/actions" +// broadcastchannel-polyfill expects MessageChannel to exist +global.MessageChannel = MessageChannel + describe("auth plugin - actions", () => { describe("authorizeRequest", () => {