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

chore: oidc new auth test #138

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all 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
60 changes: 44 additions & 16 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
},
"dependencies": {
"@deriv-com/analytics": "^1.5.3",
"@deriv-com/auth-client": "^1.2.8",
"@deriv-com/quill-ui": "1.18.1",
"@deriv-com/translations": "^1.3.9",
"@deriv-com/ui": "^1.36.4",
Expand Down
2 changes: 2 additions & 0 deletions src/app/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Fragment, lazy, Suspense, useEffect } from 'react';
import React from 'react';
import { createBrowserRouter, createRoutesFromElements, Route, RouterProvider } from 'react-router-dom';
import RoutePromptDialog from '@/components/route-prompt-dialog';
import CallbackPage from '@/pages/callback';
import Endpoint from '@/pages/endpoint';
import { initializeI18n, localize, TranslationProvider } from '@deriv-com/translations';
import { Loader } from '@deriv-com/ui';
Expand Down Expand Up @@ -47,6 +48,7 @@ const router = createBrowserRouter(
{/* All child routes will be passed as children to Layout */}
<Route index element={<AppRoot />} />
<Route path='endpoint' element={<Endpoint />} />
<Route path='callback' element={<CallbackPage />} />
</Route>
)
);
Expand Down
8 changes: 6 additions & 2 deletions src/components/layout/header/header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import useActiveAccount from '@/hooks/api/account/useActiveAccount';
import { useApiBase } from '@/hooks/useApiBase';
import { useStore } from '@/hooks/useStore';
import { StandaloneCircleUserRegularIcon } from '@deriv/quill-icons/Standalone';
import { requestOidcAuthentication } from '@deriv-com/auth-client';
import { Localize, useTranslations } from '@deriv-com/translations';
import { Header, useDevice, Wrapper } from '@deriv-com/ui';
import { Tooltip } from '@deriv-com/ui';
Expand Down Expand Up @@ -67,8 +68,11 @@ const AppHeader = observer(() => {
<div className='auth-actions'>
<Button
tertiary
onClick={() => {
window.location.assign(getOauthURL());
onClick={async () => {
// window.location.assign(getOauthURL());
await requestOidcAuthentication({
redirectCallbackUri: `${window.location.origin}/callback`,
});
}}
>
<Localize i18n_default_text='Log in' />
Expand Down
3 changes: 2 additions & 1 deletion src/components/layout/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@ import './layout.scss';

const Layout = () => {
const { isDesktop } = useDevice();
const isCallbackPage = window.location.pathname === '/callback';

return (
<div className={clsx('layout', { responsive: isDesktop })}>
<AppHeader />
{!isCallbackPage && <AppHeader />}
<Body>
<Outlet />
</Body>
Expand Down
46 changes: 46 additions & 0 deletions src/hooks/useGrowthbookGetFeatureValue.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { useEffect, useState } from 'react';

declare global {
interface Window {
Analytics: typeof Analytics;
}
}
import { useIsMounted } from 'usehooks-ts';
import { Analytics } from '@deriv-com/analytics';
import getFeatureFlag from '../utils/getFeatureFlag';

interface UseGrowthbookGetFeatureValueArgs<T> {
featureFlag: string;
defaultValue?: T;
}

const useGrowthbookGetFeatureValue = <T extends string | boolean>({
featureFlag,
defaultValue,
}: UseGrowthbookGetFeatureValueArgs<T>) => {
const resolvedDefaultValue: T = defaultValue !== undefined ? defaultValue : (false as T);
const [featureFlagValue, setFeatureFlagValue] = useState<boolean>(false);
const [isGBLoaded, setIsGBLoaded] = useState(false);
const isMounted = useIsMounted();

// Required for debugging Growthbook, this will be removed after this is added in the Analytics directly.
if (typeof window !== 'undefined') {
window.Analytics = Analytics;
}

useEffect(() => {
const fetchFeatureFlag = async () => {
const is_enabled = await getFeatureFlag(featureFlag, resolvedDefaultValue);
if (isMounted()) {
setFeatureFlagValue(is_enabled);
setIsGBLoaded(true);
}
};

fetchFeatureFlag();
}, [featureFlag, resolvedDefaultValue, isMounted]);

return [featureFlagValue, isGBLoaded];
};

export default useGrowthbookGetFeatureValue;
31 changes: 31 additions & 0 deletions src/hooks/useOauth2.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { TOAuth2EnabledAppList, useIsOAuth2Enabled, useOAuth2 } from '@deriv-com/auth-client';
import useGrowthbookGetFeatureValue from './useGrowthbookGetFeatureValue';

/**
* Provides an object with two properties: `isOAuth2Enabled` and `oAuthLogout`.
*
* `isOAuth2Enabled` is a boolean that indicates whether OAuth2 is enabled.
*
* `oAuthLogout` is a function that logs out the user of the OAuth2-enabled app.
*
* The `handleLogout` argument is an optional function that will be called after logging out the user.
* If `handleLogout` is not provided, the function will resolve immediately.
*
* @param {{ handleLogout?: () => Promise<void> }} [options] - An object with an optional `handleLogout` property.
* @returns {{ isOAuth2Enabled: boolean; oAuthLogout: () => Promise<void> }}
*/
export const useOauth2 = ({ handleLogout }: { handleLogout?: () => Promise<void> } = {}) => {
const [oAuth2EnabledApps, OAuth2EnabledAppsInitialised] = useGrowthbookGetFeatureValue<string>({
featureFlag: 'hydra_be',
}) as unknown as [TOAuth2EnabledAppList, boolean];

const isOAuth2Enabled = useIsOAuth2Enabled(oAuth2EnabledApps, OAuth2EnabledAppsInitialised);

const oAuthGrowthbookConfig = {
OAuth2EnabledApps: oAuth2EnabledApps,
OAuth2EnabledAppsInitialised,
};

const { OAuth2Logout: oAuthLogout } = useOAuth2(oAuthGrowthbookConfig, handleLogout ?? (() => Promise.resolve()));
return { isOAuth2Enabled, oAuthLogout };
};
43 changes: 43 additions & 0 deletions src/pages/callback/callbackpage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { Callback } from '@deriv-com/auth-client';
import { Button } from '@deriv-com/ui';

const CallbackPage = () => {
return (
<Callback
onSignInSuccess={tokens => {
console.log(tokens);
const accountsList: Record<string, string> = {};

for (const [key, value] of Object.entries(tokens)) {
if (key.startsWith('acct')) {
const tokenKey = key.replace('acct', 'token');
if (tokens[tokenKey]) {
accountsList[value] = tokens[tokenKey];
}
}
}

localStorage.setItem('accountsList', JSON.stringify(accountsList));

localStorage.setItem('authToken', tokens.token1);
localStorage.setItem('active_loginid', tokens.acct1);

window.location.href = '/';
}}
renderReturnButton={() => {
return (
<Button
className='callback-return-button'
onClick={() => {
window.location.href = '/';
}}
>
{'Return to Bot'}
</Button>
);
}}
/>
);
};

export default CallbackPage;
3 changes: 3 additions & 0 deletions src/pages/callback/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import CallbackPage from './callbackpage';

export default CallbackPage;
Loading
Loading