Skip to content

Commit

Permalink
Merge pull request #861 from adrienne-deriv/oidc-flow-latest
Browse files Browse the repository at this point in the history
Added OIDC flow to SmartTrader
  • Loading branch information
ahmadtaimoor-deriv authored Dec 9, 2024
2 parents 8817db8 + 599f47c commit d9496e1
Show file tree
Hide file tree
Showing 16 changed files with 344 additions and 103 deletions.
85 changes: 44 additions & 41 deletions package-lock.json

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

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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.1",
"@deriv-com/quill-ui": "^1.16.2",
"@deriv-com/utils": "^0.0.38",
"@deriv/deriv-api": "^1.0.15",
Expand Down
3 changes: 2 additions & 1 deletion scripts/config/pages.js

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

83 changes: 72 additions & 11 deletions src/javascript/_common/auth.js
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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();
}
};

Expand All @@ -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);
}

Expand All @@ -123,3 +138,49 @@ export const getLogoutHandler = onWSLogoutAndRedirect => {

return oAuth2Logout;
};

export const requestSingleSignOn = async () => {
const _requestSingleSignOn = async () => {

Check warning on line 143 in src/javascript/_common/auth.js

View workflow job for this annotation

GitHub Actions / Build and Test

Unexpected dangling '_' in '_requestSingleSignOn'

Check warning on line 143 in src/javascript/_common/auth.js

View workflow job for this annotation

GitHub Actions / Build and Test

Unexpected dangling '_' in '_requestSingleSignOn'

Check warning on line 143 in src/javascript/_common/auth.js

View workflow job for this annotation

GitHub Actions / Build and Test

Unexpected dangling '_' in '_requestSingleSignOn'
// 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();
}
};
2 changes: 1 addition & 1 deletion src/javascript/_common/utility.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
2 changes: 2 additions & 0 deletions src/javascript/app/base/binary_pages.js
Original file line number Diff line number Diff line change
Expand Up @@ -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');
Expand Down Expand Up @@ -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 },
Expand Down
16 changes: 16 additions & 0 deletions src/javascript/app/base/callback.js
Original file line number Diff line number Diff line change
@@ -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;
Loading

0 comments on commit d9496e1

Please sign in to comment.