Skip to content

Commit

Permalink
Merge pull request #886 from adrienne-deriv/oidc-flow-release
Browse files Browse the repository at this point in the history
Added OIDC flow for SmartTrader (re-release)
  • Loading branch information
ahmadtaimoor-deriv authored Dec 16, 2024
2 parents 63ca053 + 5e0b784 commit c77e66f
Show file tree
Hide file tree
Showing 16 changed files with 346 additions and 129 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.3",
"@deriv-com/quill-ui": "^1.16.2",
"@deriv-com/utils": "^0.0.38",
"@deriv/deriv-api": "^1.0.15",
Expand Down
1 change: 1 addition & 0 deletions scripts/config/pages.js

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

119 changes: 81 additions & 38 deletions src/javascript/_common/auth.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,15 @@ const {
URLConstants,
WebSocketUtils,
} = require('@deriv-com/utils');
const Cookies = require('js-cookie');
const requestOidcAuthentication = require('@deriv-com/auth-client').requestOidcAuthentication;
const OAuth2Logout = require('@deriv-com/auth-client').OAuth2Logout;
const Analytics = require('./analytics');

export const DEFAULT_OAUTH_LOGOUT_URL = 'https://oauth.deriv.com/oauth2/sessions/logout';

export const DEFAULT_OAUTH_ORIGIN_URL = 'https://oauth.deriv.com';

const LOGOUT_HANDLER_TIMEOUT = 10000;

const SocketURL = {
[URLConstants.derivP2pProduction]: 'blue.derivws.com',
[URLConstants.derivP2pStaging] : 'red.derivws.com',
Expand Down Expand Up @@ -78,48 +79,90 @@ export const isOAuth2Enabled = () => {
};

export const getLogoutHandler = onWSLogoutAndRedirect => {
const isAuthEnabled = isOAuth2Enabled();

if (!isAuthEnabled) {
return onWSLogoutAndRedirect;
}
const oAuth2Logout = OAuth2Logout(onWSLogoutAndRedirect);
return oAuth2Logout;
};

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}`);
}
}
export const requestSingleLogout = async (onWSLogoutAndRedirect) => {
const _requestSingleLogout = async () => {

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

View workflow job for this annotation

GitHub Actions / Build and Test

Unexpected dangling '_' in '_requestSingleLogout'

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

View workflow job for this annotation

GitHub Actions / Build and Test

Unexpected dangling '_' in '_requestSingleLogout'

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

View workflow job for this annotation

GitHub Actions / Build and Test

Unexpected dangling '_' in '_requestSingleLogout'

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

View workflow job for this annotation

GitHub Actions / Build and Test

Unexpected dangling '_' in '_requestSingleLogout'

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

View workflow job for this annotation

GitHub Actions / Build and Test

Unexpected dangling '_' in '_requestSingleLogout'
const isLoggedOutCookie = Cookies.get('logged_state') === 'false';
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');

if (isLoggedOutCookie && isClientAccountsPopulated && isAuthEnabled && !isCallbackPage && !isEndpointPage) {
const logoutHandler = getLogoutHandler(onWSLogoutAndRedirect);
await logoutHandler(onWSLogoutAndRedirect);
}
};

window.addEventListener('message', onMessage);

const oAuth2Logout = () => {
if (!isAuthEnabled) {
onWSLogoutAndRedirect();
return;
}

let iframe = document.getElementById('logout-iframe');
if (!iframe) {
iframe = document.createElement('iframe');
iframe.id = 'logout-iframe';
iframe.style.display = 'none';
document.body.appendChild(iframe);
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) {
_requestSingleLogout();
clearInterval(interval);
} else {
retryInterval += 1;
}
}
}, 500);
} else {
_requestSingleLogout();
}
};

setTimeout(() => {
onWSLogoutAndRedirect();
}, LOGOUT_HANDLER_TIMEOUT);
export const requestSingleSignOn = async () => {
const _requestSingleSignOn = async () => {

Check warning on line 125 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 125 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 125 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 125 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 125 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`,
});
}

iframe.src = getOAuthLogoutUrl();
};

return oAuth2Logout;
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 c77e66f

Please sign in to comment.