Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions apps/meteor/client/views/root/AppLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import { useMessageLinkClicks } from './hooks/useMessageLinkClicks';
import { useNativeEmoji } from './hooks/useNativeEmoji';
import { useNotificationPermission } from './hooks/useNotificationPermission';
import { useOAuthLogin } from './hooks/useOAuthLogin';
import { useOAuthPopupCommands } from './hooks/useOAuthPopupCommands';
import { useRedirectToSetupWizard } from './hooks/useRedirectToSetupWizard';
import { useSettingsOnLoadSiteUrl } from './hooks/useSettingsOnLoadSiteUrl';
import { useShareSessionWithOtherClients } from './hooks/useShareSessionWithOtherClients';
Expand Down Expand Up @@ -76,6 +77,7 @@ const AppLayout = () => {
useLoginViaQuery();
useLoginOtherClients();
useOAuthLogin();
useOAuthPopupCommands();
useShareSessionWithOtherClients();
useLoadMissedMessages();
useDesktopFavicon();
Expand Down
73 changes: 73 additions & 0 deletions apps/meteor/client/views/root/hooks/useOAuthPopupCommands.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import { escapeRegExp } from '@rocket.chat/string-helpers';
import { type LocationPathname, useLoginWithToken, useSetting } from '@rocket.chat/ui-contexts';
import { useEffect } from 'react';

import { ltrim, rtrim } from '../../../../lib/utils/stringUtils';
import { baseURI } from '../../../lib/baseURI';
import { getRootUrlPathPrefix } from '../../../lib/meteorRuntimeConfig';
import { router } from '../../../providers/RouterProvider';

export const useOAuthPopupCommands = () => {
Comment thread
yash-rajpal marked this conversation as resolved.
Resolved
const loginWithToken = useLoginWithToken();
const enableModernOAuthFlow = useSetting('Accounts_OAuth_Use_Modern_Flow', true);

useEffect(() => {
if (!enableModernOAuthFlow) {
return;
}

const commands = {
//Used for the 2FA challenge and for handing the session over to the desktop/mobile clients.
'redirect'(data: { path: string }) {
if (typeof data.path !== 'string' || data.path.trim().length === 0) {
return console.error('OAuth popup command [navigate]: `path` not defined');
}

const newUrl = new URL(`${rtrim(baseURI, '/')}/${ltrim(data.path, '/')}`);

const newParams = Object.fromEntries(newUrl.searchParams.entries());

const newPath = newUrl.pathname.replace(new RegExp(`^${escapeRegExp(getRootUrlPathPrefix())}`), '') as LocationPathname;

router.navigate({
pathname: newPath,
search: { ...router.getSearchParameters(), ...newParams },
});
},

'oauth-login-with-token'(data: { token: string }) {
if (typeof data.token !== 'string') {
return console.error('OAuth popup command [login]: `token` not defined');
}

void loginWithToken(data.token);
},
} as const;

const messageListener = (event: MessageEvent) => {
//The popup is same-origin, anything else is not ours to act on.
if (event.origin !== window.location.origin) {
return;
}

if (typeof event.data !== 'object' || event.data === null) {
return;
}

const { oauthPopupCommand } = event.data as { oauthPopupCommand?: unknown };

if (typeof oauthPopupCommand !== 'string' || !(oauthPopupCommand in commands)) {
Comment thread
cubic-dev-ai[bot] marked this conversation as resolved.
Resolved
return;
}

const command: (data: MessageEvent['data']) => void = commands[oauthPopupCommand as keyof typeof commands];
command(event.data);
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Resolved
};

window.addEventListener('message', messageListener);

return () => {
window.removeEventListener('message', messageListener);
};
}, [loginWithToken, enableModernOAuthFlow]);
};
6 changes: 3 additions & 3 deletions apps/meteor/server/lib/oauth/passportOAuthCallback.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ const handlePopupStyleOAuth = async (res: Response, oAuthUser: IUser, loginClien
if (secondFactorMethod) {
const challengeId = await secondFactorMethod.sendTwoFactorChallenge(oAuthUser);
sendPopupMessage(res, {
externalCommand: 'go',
oauthPopupCommand: 'redirect',
path: `/2fa/${secondFactorMethod.method}/${challengeId}${loginClient ? `?loginClient=${loginClient}` : ''}`,
});
return;
Expand All @@ -50,13 +50,13 @@ const handlePopupStyleOAuth = async (res: Response, oAuthUser: IUser, loginClien

if (loginClient) {
sendPopupMessage(res, {
externalCommand: 'go',
oauthPopupCommand: 'redirect',
path: `home?resumeToken=${token}&userId=${oAuthUser._id}&loginClient=${loginClient}`,
});
return;
}

sendPopupMessage(res, { externalCommand: 'login-with-token', token });
sendPopupMessage(res, { oauthPopupCommand: 'oauth-login-with-token', token });
};

export const passportOAuthCallback =
Expand Down
Loading