Skip to content
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

fix: Check OAuth2 redirect URL for matching callback URL and authorization code in query parameters #2148

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
@@ -1,6 +1,10 @@
const { BrowserWindow } = require('electron');
const { preferencesUtil } = require('../../store/preferences');

const matchesCallbackUrl = (url, callbackUrl) => {
return url ? url.href.startsWith(callbackUrl.href) : false;
};

const authorizeUserInWindow = ({ authorizeUrl, callbackUrl, session }) => {
return new Promise(async (resolve, reject) => {
let finalUrl = null;
Expand Down Expand Up @@ -30,12 +34,12 @@ const authorizeUserInWindow = ({ authorizeUrl, callbackUrl, session }) => {
});

function onWindowRedirect(url) {
// check if the url contains an authorization code
if (new URL(url).searchParams.has('code')) {
finalUrl = url;
if (!url || !finalUrl.includes(callbackUrl)) {
reject(new Error('Invalid Callback Url'));
// check if the redirect is to the callback URL and if it contains an authorization code
if (matchesCallbackUrl(new URL(url), new URL(callbackUrl))) {
if (!new URL(url).searchParams.has('code')) {
reject(new Error('Invalid Callback URL: Does not contain an authorization code'));
}
finalUrl = url;
window.close();
}
if (url.match(/(error=).*/) || url.match(/(error_description=).*/) || url.match(/(error_uri=).*/)) {
Expand Down Expand Up @@ -93,4 +97,4 @@ const authorizeUserInWindow = ({ authorizeUrl, callbackUrl, session }) => {
});
};

module.exports = { authorizeUserInWindow };
module.exports = { authorizeUserInWindow, matchesCallbackUrl };
19 changes: 19 additions & 0 deletions packages/bruno-electron/tests/network/authorize-user.spec.js
@@ -0,0 +1,19 @@
const { matchesCallbackUrl } = require('../../src/ipc/network/authorize-user-in-window');

describe('matchesCallbackUrl', () => {
const testCases = [
{ url: 'https://random-url/endpoint', expected: false },
{ url: 'https://random-url/endpoint?code=abcd', expected: false },
{ url: 'https://callback.url/endpoint?code=abcd', expected: true },
{ url: 'https://callback.url/endpoint/?code=abcd', expected: true },
{ url: 'https://callback.url/random-endpoint/?code=abcd', expected: false }
];

it.each(testCases)('$url - should be $expected', ({ url, expected }) => {
let callBackUrl = 'https://callback.url/endpoint';

let actual = matchesCallbackUrl(new URL(url), new URL(callBackUrl));

expect(actual).toBe(expected);
});
});