-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
@uppy/companion: remove oauthOrigin
#5311
base: 4.x
Are you sure you want to change the base?
Conversation
Diff output filesdiff --git a/packages/@uppy/companion/lib/config/companion.js b/packages/@uppy/companion/lib/config/companion.js
index 5931656..1839910 100644
--- a/packages/@uppy/companion/lib/config/companion.js
+++ b/packages/@uppy/companion/lib/config/companion.js
@@ -107,8 +107,8 @@ const validateConfig = (companionOptions) => {
"startup.uploadUrls",
);
}
- if (!companionOptions.oauthOrigin) {
- throw new TypeError("Option oauthOrigin is required. To disable security, pass \"*\"");
+ if (companionOptions.corsOrigins == null) {
+ throw new TypeError("Option corsOrigins is required. To disable security, pass true");
}
if (
periodicPingUrls != null && (!Array.isArray(periodicPingUrls)
diff --git a/packages/@uppy/companion/lib/server/controllers/connect.d.ts b/packages/@uppy/companion/lib/server/controllers/connect.d.ts
index e2b73d9..668b7e4 100644
--- a/packages/@uppy/companion/lib/server/controllers/connect.d.ts
+++ b/packages/@uppy/companion/lib/server/controllers/connect.d.ts
@@ -1,2 +1,2 @@
-declare function _exports(req: object, res: object): void;
+declare function _exports(req: object, res: object, next: any): void;
export = _exports;
diff --git a/packages/@uppy/companion/lib/server/controllers/connect.js b/packages/@uppy/companion/lib/server/controllers/connect.js
index 374cd76..a0f3776 100644
--- a/packages/@uppy/companion/lib/server/controllers/connect.js
+++ b/packages/@uppy/companion/lib/server/controllers/connect.js
@@ -1,42 +1,21 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const oAuthState = require("../helpers/oauth-state");
+function isOriginAllowed(origin, allowedOrigins) {
+ if (Array.isArray(allowedOrigins)) {
+ return allowedOrigins.some(allowedOrigin => isOriginAllowed(origin, allowedOrigin));
+ }
+ if (typeof allowedOrigins === "string") {
+ return origin === allowedOrigins;
+ }
+ return allowedOrigins.test?.(origin) ?? !!allowedOrigins;
+}
const queryString = (params, prefix = "?") => {
const str = new URLSearchParams(params).toString();
return str ? `${prefix}${str}` : "";
};
-/**
- * initializes the oAuth flow for a provider.
- *
- * @param {object} req
- * @param {object} res
- */
-module.exports = function connect(req, res) {
- const { secret, oauthOrigin } = req.companion.options;
- const stateObj = oAuthState.generateState();
- // not sure if we need to store origin in the session state (e.g. we could've just gotten it directly inside send-token)
- // but we're afraid to change the logic there
- if (!Array.isArray(oauthOrigin)) {
- // If the server only allows a single origin, we ignore the client-supplied
- // origin from query because we don't need it.
- stateObj.origin = oauthOrigin;
- } else if (oauthOrigin.length < 2) {
- // eslint-disable-next-line prefer-destructuring
- stateObj.origin = oauthOrigin[0];
- } else {
- // If we have multiple allowed origins, we need to check the client-supplied origin from query.
- // If the client provides an untrusted origin,
- // we want to send `undefined`. `undefined` means `/`, which is the same origin when passed to `postMessage`.
- // https://html.spec.whatwg.org/multipage/web-messaging.html#dom-window-postmessage-options-dev
- const { origin } = JSON.parse(atob(req.query.state));
- stateObj.origin = oauthOrigin.find(o => o === origin);
- }
- if (req.companion.options.server.oauthDomain) {
- stateObj.companionInstance = req.companion.buildURL("", true);
- }
- if (req.query.uppyPreAuthToken) {
- stateObj.preAuthToken = req.query.uppyPreAuthToken;
- }
+function encodeStateAndRedirect(req, res, stateObj) {
+ const { secret } = req.companion.options;
const state = oAuthState.encodeState(stateObj, secret);
const { providerClass, providerGrantConfig } = req.companion;
// pass along grant's dynamic config (if specified for the provider in its grant config `dynamic` section)
@@ -62,4 +41,38 @@ module.exports = function connect(req, res) {
});
// Now we redirect to grant's /connect endpoint, see `app.use(Grant(grantConfig))`
res.redirect(req.companion.buildURL(`/connect/${oauthProvider}${qs}`, true));
+}
+/**
+ * initializes the oAuth flow for a provider.
+ *
+ * @param {object} req
+ * @param {object} res
+ */
+module.exports = function connect(req, res, next) {
+ const stateObj = oAuthState.generateState();
+ if (req.companion.options.server.oauthDomain) {
+ stateObj.companionInstance = req.companion.buildURL("", true);
+ }
+ if (req.query.uppyPreAuthToken) {
+ stateObj.preAuthToken = req.query.uppyPreAuthToken;
+ }
+ stateObj.origin = res.getHeader("Access-Control-Allow-Origin");
+ if (!stateObj.origin) {
+ const { corsOrigins } = req.companion.options;
+ const { origin } = JSON.parse(atob(req.query.state));
+ if (typeof corsOrigins === "function") {
+ corsOrigins(origin, (err, finalOrigin) => {
+ if (err) {
+ next(err);
+ }
+ stateObj.origin = finalOrigin;
+ encodeStateAndRedirect(req, res, stateObj);
+ });
+ return;
+ }
+ if (isOriginAllowed(origin, req.companion.options.corsOrigins)) {
+ stateObj.origin = origin;
+ }
+ }
+ encodeStateAndRedirect(req, res, stateObj);
};
diff --git a/packages/@uppy/companion/lib/server/controllers/index.d.ts b/packages/@uppy/companion/lib/server/controllers/index.d.ts
index a782333..044ac31 100644
--- a/packages/@uppy/companion/lib/server/controllers/index.d.ts
+++ b/packages/@uppy/companion/lib/server/controllers/index.d.ts
@@ -6,7 +6,7 @@ export let thumbnail: typeof import("./thumbnail");
export let list: typeof import("./list");
export let simpleAuth: typeof import("./simple-auth");
export let logout: typeof import("./logout");
-export let connect: (req: any, res: any) => void;
+export let connect: (req: any, res: any, next: any) => void;
export let preauth: typeof import("./preauth");
export let redirect: (req: any, res: any) => void;
export let refreshToken: typeof import("./refresh-token");
diff --git a/packages/@uppy/companion/lib/standalone/helper.js b/packages/@uppy/companion/lib/standalone/helper.js
index fa5d55f..5c3e44d 100644
--- a/packages/@uppy/companion/lib/standalone/helper.js
+++ b/packages/@uppy/companion/lib/standalone/helper.js
@@ -40,9 +40,18 @@ const hasProtocol = (url) => {
const companionProtocol = process.env.COMPANION_PROTOCOL || "http";
function getCorsOrigins() {
if (process.env.COMPANION_CLIENT_ORIGINS) {
- return process.env.COMPANION_CLIENT_ORIGINS
- .split(",")
- .map((url) => (hasProtocol(url) ? url : `${companionProtocol}://${url}`));
+ switch (process.env.COMPANION_CLIENT_ORIGINS) {
+ case "true":
+ return true;
+ case "false":
+ return false;
+ case "*":
+ return "*";
+ default:
+ return process.env.COMPANION_CLIENT_ORIGINS
+ .split(",")
+ .map((url) => (hasProtocol(url) ? url : `${companionProtocol}://${url}`));
+ }
}
if (process.env.COMPANION_CLIENT_ORIGINS_REGEX) {
return new RegExp(process.env.COMPANION_CLIENT_ORIGINS_REGEX);
@@ -179,9 +188,6 @@ const getConfigFromEnv = () => {
corsOrigins: getCorsOrigins(),
testDynamicOauthCredentials: process.env.COMPANION_TEST_DYNAMIC_OAUTH_CREDENTIALS === "true",
testDynamicOauthCredentialsSecret: process.env.COMPANION_TEST_DYNAMIC_OAUTH_CREDENTIALS_SECRET,
- oauthOrigin: process.env.COMPANION_OAUTH_ORIGIN?.includes(",")
- ? process.env.COMPANION_OAUTH_ORIGIN.split(",")
- : process.env.COMPANION_OAUTH_ORIGIN,
};
};
/** |
|
||
Allowed CORS Origins (default `true`). Passed as the `origin` option in | ||
[cors](https://github.com/expressjs/cors#configuration-options)) | ||
Allowed CORS Origins. Passed as the `origin` option in |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we explain what should be passed? Entire URI as string? Compatible with everything cors
supports?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's a link to the docs (also it's a bit unrelated to this PR)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's what makes it confusing, I read that link I and I pass a regex. Then it crashes because postMessage
does not support a regex. So it is related to this PR to clarify what is now support and remove that link
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No no, a regex would work just fine
@@ -6,8 +6,10 @@ These cover all the major Uppy versions and how to migrate to them. | |||
|
|||
- End-of-Life versions of Node.js are no longer supported (use latest 18.x LTS, | |||
20.x LTS, or 22.x current). | |||
- Setting the `oauthOrigin` option is now required. To get back to the unsafe | |||
behavior of the previous version, set it to `'*'`. | |||
- Setting the `corsOrigin` option is now required. You should define the list of |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's link to this option in the docs
No description provided.