From dde892052a609e928966bb0e35363b084d704c86 Mon Sep 17 00:00:00 2001 From: Adrienne Rio Date: Tue, 10 Dec 2024 19:50:23 +0800 Subject: [PATCH 1/5] feat: added oidc flow for smarttrader --- package-lock.json | 85 +++++------ package.json | 2 +- scripts/config/pages.js | 1 + src/javascript/_common/auth.js | 83 +++++++++-- src/javascript/_common/utility.js | 2 +- src/javascript/app/base/binary_pages.js | 2 + src/javascript/app/base/callback.js | 16 ++ src/javascript/app/base/header.js | 56 ++++--- src/javascript/app/base/logged_in.js | 2 - src/javascript/app/base/page.js | 2 + .../app/pages/callback/callback.jsx | 138 ++++++++++++++++++ src/javascript/app/pages/deriv_iframe.jsx | 19 --- src/templates/_common/_layout/layout.jsx | 1 - .../_common/includes/deriv-iframe.jsx | 5 - src/templates/app/callback.jsx | 30 ++++ src/templates/app/logged_in.jsx | 1 - 16 files changed, 343 insertions(+), 102 deletions(-) create mode 100644 src/javascript/app/base/callback.js create mode 100644 src/javascript/app/pages/callback/callback.jsx delete mode 100644 src/javascript/app/pages/deriv_iframe.jsx delete mode 100644 src/templates/_common/includes/deriv-iframe.jsx create mode 100644 src/templates/app/callback.jsx diff --git a/package-lock.json b/package-lock.json index df1df4fd578..b09b76abafd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,7 +14,7 @@ "@binary-com/binary-style": "^0.2.26", "@binary-com/webtrader-charts": "^0.6.2", "@deriv-com/analytics": "^1.26.1", - "@deriv-com/auth-client": "^1.0.15", + "@deriv-com/auth-client": "1.3.3", "@deriv-com/quill-ui": "^1.16.2", "@deriv-com/utils": "^0.0.38", "@deriv/deriv-api": "^1.0.15", @@ -2527,49 +2527,30 @@ } }, "node_modules/@deriv-com/auth-client": { - "version": "1.0.15", - "resolved": "https://registry.npmjs.org/@deriv-com/auth-client/-/auth-client-1.0.15.tgz", - "integrity": "sha512-2G6IUtPIX2TmlpW2khDUeltqfsxJtxZgiFdoHidW19rjZYDaj4aHDEh/RXArbiUUKF0i0FGgupzAuW4Id/o7SA==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@deriv-com/auth-client/-/auth-client-1.3.3.tgz", + "integrity": "sha512-LXp890lIZjZjSIs1OzHZCET/qQp9ACdLnbKOMXFAvqleNlUFZstlIhZIDYHTMorU3pclh3oG/wErZwRLNTMxkw==", "dependencies": { - "@deriv-com/utils": "^0.0.33", - "react": "^18.3.1", - "react-dom": "^18.3.1" + "@deriv-com/utils": "^0.0.42", + "js-cookie": "3.0.5", + "oidc-client-ts": "^3.1.0" + }, + "optionalDependencies": { + "@rollup/rollup-linux-x64-gnu": "^4.27.3" } }, "node_modules/@deriv-com/auth-client/node_modules/@deriv-com/utils": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/@deriv-com/utils/-/utils-0.0.33.tgz", - "integrity": "sha512-LzIpzMvfWhK9y06Qpe/HOB4pFCizk2wAyhv9I0s48Romq+d5MM1mmsuh5CvS4SnzzdLyuBy4rgXrOO3394HB7w==" + "version": "0.0.42", + "resolved": "https://registry.npmjs.org/@deriv-com/utils/-/utils-0.0.42.tgz", + "integrity": "sha512-4JhTpg0sQWCq94RSMGpuT/09bYSV8yO3WdunM2R84qxWNitRH/i4k/xfdleRVzX+xLSmMmJWlkbD6NAlP8U5eg==" }, - "node_modules/@deriv-com/auth-client/node_modules/react": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", - "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", - "dependencies": { - "loose-envify": "^1.1.0" - }, + "node_modules/@deriv-com/auth-client/node_modules/js-cookie": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.5.tgz", + "integrity": "sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==", + "license": "MIT", "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@deriv-com/auth-client/node_modules/react-dom": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", - "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", - "dependencies": { - "loose-envify": "^1.1.0", - "scheduler": "^0.23.2" - }, - "peerDependencies": { - "react": "^18.3.1" - } - }, - "node_modules/@deriv-com/auth-client/node_modules/scheduler": { - "version": "0.23.2", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", - "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", - "dependencies": { - "loose-envify": "^1.1.0" + "node": ">=14" } }, "node_modules/@deriv-com/quill-tokens": { @@ -3244,12 +3225,13 @@ "integrity": "sha512-yNN7S2HHh2is9WrLlfEnPdX5rO9Nlv3wmBXSWXXQTt9mAC5PU/NFQRfGGI/fBNRSQA4PGqgz5LYHwTcHhEwXeQ==" }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.20.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.20.0.tgz", - "integrity": "sha512-y+eoL2I3iphUg9tN9GB6ku1FA8kOfmF4oUEWhztDJ4KXJy1agk/9+pejOuZkNFhRwHAOxMsBPLbXPd6mJiCwew==", + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.28.1.tgz", + "integrity": "sha512-fzgeABz7rrAlKYB0y2kSEiURrI0691CSL0+KXwKwhxvj92VULEDQLpBYLHpF49MSiPG4sq5CK3qHMnb9tlCjBw==", "cpu": [ "x64" ], + "license": "MIT", "optional": true, "os": [ "linux" @@ -12173,6 +12155,15 @@ "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.2.1.tgz", "integrity": "sha512-g3UB796vUFIY90VIv/WX3L2c8CS2MdWUww3CNrYmqza1Fg0DURc2K/O4YrnklBdQarSJ/y8JnJYDGc+1iumQjg==" }, + "node_modules/jwt-decode": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-4.0.0.tgz", + "integrity": "sha512-+KJGIyHgkGuIq3IEBNftfhW/LfWhXUIY6OmyVWjliu5KH1y0fw7VQ8YndE2O4qZdMSd9SqbnC8GOcZEy0Om7sA==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", @@ -16386,6 +16377,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/oidc-client-ts": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/oidc-client-ts/-/oidc-client-ts-3.1.0.tgz", + "integrity": "sha512-IDopEXjiwjkmJLYZo6BTlvwOtnlSniWZkKZoXforC/oLZHC9wkIxd25Kwtmo5yKFMMVcsp3JY6bhcNJqdYk8+g==", + "license": "Apache-2.0", + "dependencies": { + "jwt-decode": "^4.0.0" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/on-finished": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", diff --git a/package.json b/package.json index ce0800ea613..027bdf7e43a 100644 --- a/package.json +++ b/package.json @@ -107,7 +107,7 @@ "@binary-com/binary-style": "^0.2.26", "@binary-com/webtrader-charts": "^0.6.2", "@deriv-com/analytics": "^1.26.1", - "@deriv-com/auth-client": "^1.0.15", + "@deriv-com/auth-client": "1.3.3", "@deriv-com/quill-ui": "^1.16.2", "@deriv-com/utils": "^0.0.38", "@deriv/deriv-api": "^1.0.15", diff --git a/scripts/config/pages.js b/scripts/config/pages.js index 370d3179c2b..4215d9e360d 100644 --- a/scripts/config/pages.js +++ b/scripts/config/pages.js @@ -64,6 +64,7 @@ module.exports = [ // ['dialog', 'app/dialog', null], ['explanation', 'app/trade/explanation', null], ['logged_inws', 'app/logged_in', null], + ['callback', 'app/callback', null], // ['redirect', 'app/logged_in', null, 'Redirecting...'], // ==================== Section: "static" ==================== diff --git a/src/javascript/_common/auth.js b/src/javascript/_common/auth.js index 6a54713b52c..73bdbad0d12 100644 --- a/src/javascript/_common/auth.js +++ b/src/javascript/_common/auth.js @@ -5,6 +5,8 @@ const { URLConstants, WebSocketUtils, } = require('@deriv-com/utils'); +const Cookies = require('js-cookie'); +const requestOidcAuthentication = require('@deriv-com/auth-client').requestOidcAuthentication; const Analytics = require('./analytics'); export const DEFAULT_OAUTH_LOGOUT_URL = 'https://oauth.deriv.com/oauth2/sessions/logout'; @@ -79,22 +81,33 @@ export const isOAuth2Enabled = () => { export const getLogoutHandler = onWSLogoutAndRedirect => { const isAuthEnabled = isOAuth2Enabled(); + let timeout; if (!isAuthEnabled) { return onWSLogoutAndRedirect; } - const onMessage = async event => { - const allowedOrigin = getOAuthOrigin(); - if (allowedOrigin === event.origin) { - if (event.data === 'logout_complete') { - try { - await onWSLogoutAndRedirect(); - } catch (err) { - // eslint-disable-next-line no-console - console.error(`logout was completed successfully on oauth hydra server, but logout handler returned error: ${err}`); - } + const cleanup = () => { + clearTimeout(timeout); + + const iframe = document.getElementById('logout-iframe'); + if (iframe) iframe.remove(); + }; + + const onMessage = event => { + if (event.data === 'logout_complete') { + const domains = ['deriv.com', 'binary.sx', 'pages.dev', 'localhost']; + const currentDomain = window.location.hostname.split('.').slice(-2).join('.'); + if (domains.includes(currentDomain)) { + Cookies.set('logged_state', 'false', { + expires: 30, + path : '/', + secure : true, + }); } + onWSLogoutAndRedirect(); + window.removeEventListener('message', onMessage); + cleanup(); } }; @@ -113,8 +126,10 @@ export const getLogoutHandler = onWSLogoutAndRedirect => { iframe.style.display = 'none'; document.body.appendChild(iframe); - setTimeout(() => { + timeout = setTimeout(() => { onWSLogoutAndRedirect(); + window.removeEventListener('message', onMessage); + cleanup(); }, LOGOUT_HANDLER_TIMEOUT); } @@ -123,3 +138,49 @@ export const getLogoutHandler = onWSLogoutAndRedirect => { return oAuth2Logout; }; + +export const requestSingleSignOn = async () => { + const _requestSingleSignOn = async () => { + // if we have previously logged in, + // this cookie will be set by the Callback page (which is exported from @deriv-com/auth-client library) to true when we have successfully logged in from other apps + const isLoggedInCookie = Cookies.get('logged_state') === 'true'; + const clientAccounts = JSON.parse(localStorage.getItem('client.accounts') || '{}'); + const isClientAccountsPopulated = Object.keys(clientAccounts).length > 0; + const isAuthEnabled = isOAuth2Enabled(); + const isCallbackPage = window.location.pathname.includes('callback'); + const isEndpointPage = window.location.pathname.includes('endpoint'); + + // we only do SSO if: + // we have previously logged-in before from SmartTrader or any other apps (Deriv.app, etc) - isLoggedInCookie + // if we are not in the callback route to prevent re-calling this function - !isCallbackPage + // if client.accounts in localStorage is empty - !isClientAccountsPopulated + // and if feature flag for OIDC Phase 2 is enabled - isAuthEnabled + if (isLoggedInCookie && !isCallbackPage && !isEndpointPage && !isClientAccountsPopulated && isAuthEnabled) { + await requestOidcAuthentication({ + redirectCallbackUri: `${window.location.origin}/en/callback`, + }); + } + }; + + const isGrowthbookLoaded = Analytics.isGrowthbookLoaded(); + if (!isGrowthbookLoaded) { + let retryInterval = 0; + // this interval is to check if Growthbook is already initialised. + // If not, keep checking it (max 10 times) and SSO if conditions are met + const interval = setInterval(() => { + if (retryInterval > 10) { + clearInterval(interval); + } else { + const isLoaded = Analytics.isGrowthbookLoaded(); + if (isLoaded) { + _requestSingleSignOn(); + clearInterval(interval); + } else { + retryInterval += 1; + } + } + }, 500); + } else { + _requestSingleSignOn(); + } +}; diff --git a/src/javascript/_common/utility.js b/src/javascript/_common/utility.js index c572a061536..357aa94de85 100644 --- a/src/javascript/_common/utility.js +++ b/src/javascript/_common/utility.js @@ -109,7 +109,7 @@ const isEmptyObject = (obj) => { return is_empty; }; -const isLoginPages = () => /logged_inws|redirect/i.test(window.location.pathname); +const isLoginPages = () => /logged_inws|redirect|callback/i.test(window.location.pathname); const cloneObject = obj => (!isEmptyObject(obj) ? extend(true, Array.isArray(obj) ? [] : {}, obj) : obj); diff --git a/src/javascript/app/base/binary_pages.js b/src/javascript/app/base/binary_pages.js index b35779f60d7..4ec8f9d00c0 100644 --- a/src/javascript/app/base/binary_pages.js +++ b/src/javascript/app/base/binary_pages.js @@ -3,6 +3,7 @@ // ==================== app ==================== const LoggedInHandler = require('./logged_in'); +const CallbackHandler = require('./callback'); // const Redirect = require('./redirect'); // const AccountTransfer = require('../pages/cashier/account_transfer'); // const Cashier = require('../pages/cashier/cashier'); @@ -98,6 +99,7 @@ const pages_config = { // landing_page : { module: StaticPages.LandingPage, is_authenticated: true, only_virtual: true }, // limitsws : { module: Limits, is_authenticated: true, no_mf: true, only_real: true, needs_currency: true }, logged_inws: { module: LoggedInHandler }, + callback : { module: CallbackHandler }, // lost_passwordws : { module: LostPassword, not_authenticated: true }, // malta : { module: StaticPages.Locations }, // maltainvestws : { module: FinancialAccOpening, is_authenticated: true }, diff --git a/src/javascript/app/base/callback.js b/src/javascript/app/base/callback.js new file mode 100644 index 00000000000..632f27afdc1 --- /dev/null +++ b/src/javascript/app/base/callback.js @@ -0,0 +1,16 @@ +const SocketCache = require('../../_common/base/socket_cache'); +const CallbackElement = require('../pages/callback/callback.jsx'); + +const CallbackHandler = (() => { + const onLoad = () => { + SocketCache.clear(); + CallbackElement.init(); + parent.window.is_logging_in = 1; // this flag is used in base.js to prevent auto-reloading this pag + }; + + return { + onLoad, + }; +})(); + +module.exports = CallbackHandler; diff --git a/src/javascript/app/base/header.js b/src/javascript/app/base/header.js index b75ed21d959..a3245f62308 100644 --- a/src/javascript/app/base/header.js +++ b/src/javascript/app/base/header.js @@ -1,13 +1,14 @@ // const BinaryPjax = require('./binary_pjax'); -const Client = require('./client'); -const BinarySocket = require('./socket'); -const AuthClient = require('../../_common/auth'); -const showHidePulser = require('../common/account_opening').showHidePulser; -const updateTotal = require('../pages/user/update_total'); -const isAuthenticationAllowed = require('../../_common/base/client_base').isAuthenticationAllowed; -const GTM = require('../../_common/base/gtm'); -const Login = require('../../_common/base/login'); -const SocketCache = require('../../_common/base/socket_cache'); +const requestOidcAuthentication = require('@deriv-com/auth-client').requestOidcAuthentication; +const Client = require('./client'); +const BinarySocket = require('./socket'); +const AuthClient = require('../../_common/auth'); +const showHidePulser = require('../common/account_opening').showHidePulser; +const updateTotal = require('../pages/user/update_total'); +const isAuthenticationAllowed = require('../../_common/base/client_base').isAuthenticationAllowed; +const GTM = require('../../_common/base/gtm'); +const Login = require('../../_common/base/login'); +const SocketCache = require('../../_common/base/socket_cache'); // const elementInnerHtml = require('../../_common/common_functions').elementInnerHtml; const getElementById = require('../../_common/common_functions').getElementById; const localize = require('../../_common/localize').localize; @@ -24,7 +25,6 @@ const template = require('../../_common/utility').template; const Language = require('../../_common/language'); const mapCurrencyName = require('../../_common/base/currency_base').mapCurrencyName; const isEuCountry = require('../common/country_base').isEuCountry; -const DerivIFrame = require('../pages/deriv_iframe.jsx'); const DerivLiveChat = require('../pages/livechat.jsx'); const Chat = require('../../_common/chat.js').default; const getRemoteConfig = require('../hooks/useRemoteConfig').getRemoteConfig; @@ -45,7 +45,6 @@ const Header = (() => { }; const onLoad = () => { - DerivIFrame.init(); populateAccountsList(); populateWalletAccounts(); bindSvg(); @@ -652,19 +651,35 @@ const Header = (() => { // } // }; - const loginOnClick = (e) => { + const loginOnClick = async (e) => { e.preventDefault(); - Login.redirectToLogin(); + const isOAuth2Enabled = AuthClient.isOAuth2Enabled(); + + if (isOAuth2Enabled) { + const redirectCallbackUri = `${window.location.origin}/en/callback`; + const postLoginRedirectUri = window.location.origin; + const postLogoutRedirectUri = `${window.location.origin}/en/trading`; + // Test commit + await requestOidcAuthentication({ + redirectCallbackUri, + postLoginRedirectUri, + postLogoutRedirectUri, + }); + } else { + Login.redirectToLogin(); + } }; - + const logoutOnClick = async () => { await Chat.clear(); // This will wrap the logout call Client.sendLogoutRequest with our own logout iframe, which is to inform Hydra that the user is logging out // and the session should be cleared on Hydra's side. Once this is done, it will call the passed-in logout handler Client.sendLogoutRequest. // If Hydra authentication is not enabled, the logout handler Client.sendLogoutRequest will just be called instead. - const onLogoutWithOauth = await AuthClient.getLogoutHandler(Client.sendLogoutRequest); - + const onLogoutWithOauth = await AuthClient.getLogoutHandler( + Client.sendLogoutRequest + ); + onLogoutWithOauth(); }; @@ -891,13 +906,14 @@ const Header = (() => { const account_switcher_seperator = document.getElementById('cfd-link-seperator'); const multiplier_text = localize('Multipliers'); const account_header = document.querySelectorAll('.header__accounts-multiple'); + const is_callback_page = window.location.pathname.includes('callback'); let is_virtual; if (current_active_login) { is_virtual = current_active_login.startsWith('VRTC'); } const showTradersHubLink = (show) => { - traders_hub_link.style.display = show ? 'flex' : 'none'; - account_switcher_seperator.style.display = show ? 'block' : 'none'; + if (traders_hub_link.style) traders_hub_link.style.display = show ? 'flex' : 'none'; + if (account_switcher_seperator.style) account_switcher_seperator.style.display = show ? 'block' : 'none'; }; account_header.forEach(header => { @@ -908,8 +924,8 @@ const Header = (() => { $(`${multiplier_text}`).insertAfter('#header__acc-balance'); } - if (has_real_account) showTradersHubLink(true); - if (is_virtual) showTradersHubLink(true); + if (has_real_account && !is_callback_page) showTradersHubLink(true); + if (is_virtual && !is_callback_page) showTradersHubLink(true); if (is_virtual || !has_real_account) { manage_acc_btn.style.visibility = 'hidden'; } diff --git a/src/javascript/app/base/logged_in.js b/src/javascript/app/base/logged_in.js index 2a250d20dcd..0c081b0e3b2 100644 --- a/src/javascript/app/base/logged_in.js +++ b/src/javascript/app/base/logged_in.js @@ -12,7 +12,6 @@ const removeCookies = require('../../_common/storage').removeCookies; const paramsHash = require('../../_common/url').paramsHash; const urlFor = require('../../_common/url').urlFor; const getPropertyValue = require('../../_common/utility').getPropertyValue; -const DerivIFrame = require('../pages/deriv_iframe.jsx'); const LoggedInHandler = (() => { const onLoad = () => { @@ -20,7 +19,6 @@ const LoggedInHandler = (() => { parent.window.is_logging_in = 1; // this flag is used in base.js to prevent auto-reloading this page let redirect_url; const params = paramsHash(window.location.href); - DerivIFrame.init(); BinarySocket.send({ authorize: params.token1 }).then((response) => { const account_list = getPropertyValue(response, ['authorize', 'account_list']); if (isStorageSupported(localStorage) && isStorageSupported(sessionStorage) && account_list) { diff --git a/src/javascript/app/base/page.js b/src/javascript/app/base/page.js index 72818dc8f86..89136eab72a 100644 --- a/src/javascript/app/base/page.js +++ b/src/javascript/app/base/page.js @@ -22,6 +22,7 @@ const scrollToTop = require('../../_common/scroll').scrollToTop; const toISOFormat = require('../../_common/string_util').toISOFormat; const Url = require('../../_common/url'); const Analytics = require('../../_common/analytics'); +const { requestSingleSignOn } = require('../../_common/auth'); const Chat = require('../../_common/chat.js').default; const createElement = require('../../_common/utility').createElement; const isLoginPages = require('../../_common/utility').isLoginPages; @@ -100,6 +101,7 @@ const Page = (() => { updateLinksURL('#content'); } else { init(); + requestSingleSignOn(); if (!isLoginPages()) { Language.setCookie(Language.urlLang()); const url_query_strings = Url.paramsHash(); diff --git a/src/javascript/app/pages/callback/callback.jsx b/src/javascript/app/pages/callback/callback.jsx new file mode 100644 index 00000000000..bdd7ed1559f --- /dev/null +++ b/src/javascript/app/pages/callback/callback.jsx @@ -0,0 +1,138 @@ +import React from 'react'; +import ReactDOM from 'react-dom'; + +import { Callback } from '@deriv-com/auth-client'; + +import Cookies from 'js-cookie'; +import moment from 'moment'; +import Client from '../../base/client'; +import BinarySocket from '../../base/socket'; +import GTM from '../../../_common/base/gtm'; +import { get as getLanguage, urlLang } from '../../../_common/language'; +import { isStorageSupported, removeCookies } from '../../../_common/storage'; +import { urlFor } from '../../../_common/url'; +import { getPropertyValue } from '../../../_common/utility'; +import { getElementById } from '../../../_common/common_functions'; + +const map_names = { + country : 'residence', + landing_company_name: 'landing_company_shortcode', +}; + +const storeClientAccounts = (tokens, account_list) => { + // Parse url for loginids, tokens, and currencies returned by OAuth + + // Clear all accounts before entering the loop + Client.clearAllAccounts(); + + account_list.forEach(account => { + Object.keys(account).forEach(param => { + if (param === 'loginid') { + if (!Client.get('loginid') && !account.is_disabled && !account.is_virtual) { + Client.set(param, account[param]); + } + } else { + const param_to_set = map_names[param] || param; + const value_to_set = typeof account[param] === 'undefined' ? '' : account[param]; + Client.set(param_to_set, value_to_set, account.loginid); + } + }); + }); + + let i = 1; + while (tokens[`acct${i}`]) { + const loginid = tokens[`acct${i}`]; + const token = tokens[`token${i}`]; + if (loginid && token) { + Client.set('token', token, loginid); + } + i++; + } + + // if didn't find any login ID that matched the above condition + // or the selected one doesn't have a token, set the first one + if (!Client.get('loginid') || !Client.get('token')) { + Client.set('loginid', tokens.acct1 || account_list[0].loginid); + } + + if (Client.isLoggedIn()) { + GTM.setLoginFlag('log_in'); + Client.set('session_start', parseInt(moment().valueOf() / 1000)); + // Remove cookies that were set by the old code + removeCookies('email', 'login', 'loginid', 'loginid_list', 'residence'); + } +}; + +const CallbackContainer = () => { + const onLoginSuccess = async tokens => { + let redirect_url; + BinarySocket.send({ authorize: tokens.token1 }).then(response => { + const account_list = getPropertyValue(response, ['authorize', 'account_list']); + if ( + isStorageSupported(localStorage) && + isStorageSupported(sessionStorage) && + account_list + ) { + // redirect url + redirect_url = sessionStorage.getItem('redirect_url'); + sessionStorage.removeItem('redirect_url'); + + storeClientAccounts(tokens, account_list); + } else { + Client.doLogout({ logout: 1 }); + } + + // redirect back + let set_default = true; + if (redirect_url) { + const do_not_redirect = [ + 'reset_passwordws', + 'lost_passwordws', + 'change_passwordws', + 'home', + '404', + ]; + const reg = new RegExp(do_not_redirect.join('|'), 'i'); + if (!reg.test(redirect_url) && urlFor('') !== redirect_url) { + set_default = false; + } + } + if (set_default) { + const lang_cookie = urlLang(redirect_url) || Cookies.get('language'); + const language = getLanguage(); + redirect_url = + Client.isAccountOfType('financial') || Client.isOptionsBlocked() + ? urlFor('user/metatrader') + : Client.defaultRedirectUrl(); + if (lang_cookie && lang_cookie !== language) { + redirect_url = redirect_url.replace( + new RegExp(`/${language}/`, 'i'), + `/${lang_cookie.toLowerCase()}/` + ); + } + } + getElementById('loading_link').setAttribute('href', redirect_url); + + const domains = ['deriv.com', 'binary.sx', 'pages.dev', 'localhost']; + const currentDomain = window.location.hostname.split('.').slice(-2).join('.'); + if (domains.includes(currentDomain)) { + Cookies.set('logged_state', 'true', { + expires: 30, + path : '/', + secure : true, + }); + } + + window.location.href = redirect_url; // need to redirect not using pjax + }); + }; + + // eslint-disable-next-line no-console + return ; +}; + +export const init = () => { + ReactDOM.render(, document.getElementById('callback_container')); +}; + +export default init; diff --git a/src/javascript/app/pages/deriv_iframe.jsx b/src/javascript/app/pages/deriv_iframe.jsx deleted file mode 100644 index 82781c14f79..00000000000 --- a/src/javascript/app/pages/deriv_iframe.jsx +++ /dev/null @@ -1,19 +0,0 @@ -import React from 'react'; -import ReactDOM from 'react-dom'; -import { isOAuth2Enabled } from '../../_common/auth'; - -const DerivIFrame = () => ( -