diff --git a/package-lock.json b/package-lock.json
index 1df6d60b..d5dc8bc8 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -27,12 +27,14 @@
"@react-spring/web": "^9.7.3",
"@textea/json-viewer": "^3.4.1",
"@use-gesture/react": "^10.3.0",
+ "axios": "^1.7.7",
"babel-plugin-jsx-remove-data-test-id": "^3.0.0",
"clsx": "^1.2.1",
"docusaurus-plugin-sass": "^0.2.2",
"identity-obj-proxy": "^3.0.0",
"install": "^0.13.0",
"moment": "^2.29.4",
+ "oidc-client-ts": "^3.1.0",
"prism-react-renderer": "^2.3.1",
"react": "^18.2.0",
"react-dom": "^18.2.0",
@@ -9429,8 +9431,7 @@
"node_modules/asynckit": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
- "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
- "dev": true
+ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
},
"node_modules/at-least-node": {
"version": "1.0.0",
@@ -9491,6 +9492,16 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/axios": {
+ "version": "1.7.7",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz",
+ "integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==",
+ "dependencies": {
+ "follow-redirects": "^1.15.6",
+ "form-data": "^4.0.0",
+ "proxy-from-env": "^1.1.0"
+ }
+ },
"node_modules/babel-jest": {
"version": "29.7.0",
"resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz",
@@ -10804,7 +10815,6 @@
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
- "dev": true,
"dependencies": {
"delayed-stream": "~1.0.0"
},
@@ -12051,7 +12061,6 @@
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
- "dev": true,
"engines": {
"node": ">=0.4.0"
}
@@ -14314,7 +14323,6 @@
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
"integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
- "dev": true,
"dependencies": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.8",
@@ -15357,6 +15365,7 @@
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz",
"integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==",
+ "dev": true,
"dependencies": {
"lru-cache": "^6.0.0"
},
@@ -15368,6 +15377,7 @@
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+ "dev": true,
"dependencies": {
"yallist": "^4.0.0"
},
@@ -15378,7 +15388,8 @@
"node_modules/hosted-git-info/node_modules/yallist": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
- "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+ "dev": true
},
"node_modules/hpack.js": {
"version": "2.1.6",
@@ -22894,6 +22905,7 @@
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz",
"integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==",
+ "dev": true,
"dependencies": {
"hosted-git-info": "^4.0.1",
"is-core-module": "^2.5.0",
@@ -22908,6 +22920,7 @@
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+ "dev": true,
"dependencies": {
"yallist": "^4.0.0"
},
@@ -22919,6 +22932,7 @@
"version": "7.6.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz",
"integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==",
+ "dev": true,
"dependencies": {
"lru-cache": "^6.0.0"
},
@@ -22932,7 +22946,8 @@
"node_modules/normalize-package-data/node_modules/yallist": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
- "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+ "dev": true
},
"node_modules/normalize-path": {
"version": "3.0.0",
@@ -27584,6 +27599,11 @@
"node": ">= 0.10"
}
},
+ "node_modules/proxy-from-env": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
+ "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
+ },
"node_modules/psl": {
"version": "1.9.0",
"resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz",
diff --git a/package.json b/package.json
index 0bb7d5a6..15b81666 100644
--- a/package.json
+++ b/package.json
@@ -46,6 +46,7 @@
"@textea/json-viewer": "^3.4.1",
"@use-gesture/react": "^10.3.0",
"babel-plugin-jsx-remove-data-test-id": "^3.0.0",
+ "axios": "^1.7.7",
"clsx": "^1.2.1",
"docusaurus-plugin-sass": "^0.2.2",
"identity-obj-proxy": "^3.0.0",
@@ -56,6 +57,7 @@
"react-dom": "^18.2.0",
"react-hook-form": "^7.41.5",
"react-table": "^7.8.0",
+ "oidc-client-ts": "^3.1.0",
"sass": "^1.57.1",
"sass-loader": "^13.2.0",
"swiper": "^8.3.2",
diff --git a/src/components/UserNavbarItem/item.desktop.tsx b/src/components/UserNavbarItem/item.desktop.tsx
index 7bbd9594..24d97c2a 100644
--- a/src/components/UserNavbarItem/item.desktop.tsx
+++ b/src/components/UserNavbarItem/item.desktop.tsx
@@ -3,6 +3,7 @@ import clsx from 'clsx';
import Translate from '@docusaurus/Translate';
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
import { Button } from '@deriv-com/quill-ui';
+import { requestOidcAuthentication } from '@deriv-com/auth-client';
import {
LabelPairedGridLgRegularIcon,
StandaloneRightFromBracketBoldIcon,
@@ -92,8 +93,13 @@ const UserNavbarDesktopItem = ({ authUrl, is_logged_in }: IUserNavbarItemProps)
const { deviceType } = useDeviceType();
const isDesktop = deviceType === 'desktop';
- const handleClick = () => {
- location.assign(authUrl);
+ const handleClick = async () => {
+ // location.assign(authUrl);
+ const app_id = localStorage.getItem('config.app_id');
+ const redirect_uri = `${window.location.origin}/dashboard`;
+ const post_logout_redirect_uri = `${window.location.origin}/`;
+
+ await requestOidcAuthentication(app_id, redirect_uri, post_logout_redirect_uri);
};
return is_logged_in ? (
diff --git a/src/features/dashboard/dashboard.tsx b/src/features/dashboard/dashboard.tsx
index 438f44da..3d5de147 100644
--- a/src/features/dashboard/dashboard.tsx
+++ b/src/features/dashboard/dashboard.tsx
@@ -3,17 +3,88 @@ import useAuthContext from '@site/src/hooks/useAuthContext';
import useAppManager from '@site/src/hooks/useAppManager';
import ManageDashboard from './manage-dashboard';
import { Login } from '../Login/Login';
+import axios from 'axios';
+import { getAccountsFromSearchParams } from '@site/src/utils';
const Dashboard = () => {
- const { is_logged_in } = useAuthContext();
+ const { is_logged_in, updateLoginAccounts } = useAuthContext();
const { setIsDashboard } = useAppManager();
useEffect(() => {
setIsDashboard(true);
+ const exchangeToken = async () => {
+ try {
+ const urlParams = new URLSearchParams(window?.location?.search);
+ const oidc_endpoints = localStorage.getItem('config.oidc_endpoints') || '{}';
+
+ const token_endpoint = JSON.parse(oidc_endpoints).token_endpoint || '';
+
+ const code = urlParams.get('code');
+ const state = urlParams.get('state');
+ const oidc_key = `oidc.${state}`;
+
+ const oidc_data = localStorage.getItem(oidc_key);
+ const code_verifier = oidc_data ? JSON.parse(oidc_data).code_verifier : null;
+ const appId = localStorage.getItem('config.app_id');
+
+ if (!code_verifier) return;
+
+ const response = await fetch(token_endpoint, {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/x-www-form-urlencoded',
+ Accept: 'application/json',
+ },
+ body: new URLSearchParams({
+ grant_type: 'authorization_code',
+ redirect_uri: `${window.location.origin}/dashboard`,
+ code: code,
+ code_verifier: code_verifier,
+ client_id: appId,
+ }).toString(),
+ });
+
+ const data = await response.json();
+ if (response.ok) {
+ localStorage.setItem('id_token', data.id_token);
+
+ try {
+ const response = await axios.post(
+ 'https://qa101.deriv.dev/oauth2/legacy/tokens',
+ {},
+ {
+ headers: {
+ Authorization: `Bearer ${data.access_token}`,
+ 'Content-Type': 'application/json',
+ },
+ },
+ );
+
+ const legacyData = response.data;
+ const accounts = getAccountsFromSearchParams(legacyData);
+ updateLoginAccounts(accounts);
+ window.history.replaceState({}, document.title, '/dashboard');
+ } catch (error) {
+ if (error.response) {
+ const legacyData = error.response.data;
+ console.error('Error fetching legacy tokens:', legacyData);
+ } else {
+ console.error('Failed to fetch legacy tokens:', error);
+ }
+ }
+ } else {
+ console.error('Error exchanging token:', data);
+ }
+ } catch (error) {
+ console.error('Token exchange failed:', error);
+ }
+ };
+
+ exchangeToken();
return () => {
setIsDashboard(false);
};
- }, [setIsDashboard]);
+ }, [setIsDashboard, updateLoginAccounts]);
if (is_logged_in) return ;
return ;