Skip to content

Commit

Permalink
STCOR-918: *BREAKING* remove token-based authentication code (#1592)
Browse files Browse the repository at this point in the history
https://folio-org.atlassian.net/browse/STCOR-918
https://folio-org.atlassian.net/browse/STCOR-922

Here we removed token-based authentication endpoints. Also, removed
`useSecureTokens` logic part.
  • Loading branch information
UladzislauKutarkin authored Feb 14, 2025
1 parent fa2ffcf commit f768417
Show file tree
Hide file tree
Showing 11 changed files with 59 additions and 92 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
* *BREAKING* Upgrade `@folio/stripes-*` dependencies.
* *BREAKING* Upgrade `react-intl` to `^v7`. Refs STCOR-945.
* Change Help icon aria label to just Help in MainNav component. Refs STCOR-931.
* *BREAKING* remove token-based authentication code. Refs STCOR-918.
* *BREAKING* replace useSecureTokens conditionalsRefs STCOR-922.

## [10.2.0](https://github.com/folio-org/stripes-core/tree/v10.2.0) (2024-10-11)
[Full Changelog](https://github.com/folio-org/stripes-core/compare/v10.1.1...v10.2.0)
Expand Down
2 changes: 1 addition & 1 deletion src/RootWithIntl.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ const RootWithIntl = ({ stripes, token = '', isAuthenticated = false, disableAut
{ (typeof connectedStripes.okapi !== 'object' || connectedStripes.discovery.isFinished) && (
<ModuleContainer id="content">
<OverlayContainer />
{connectedStripes.config.useSecureTokens && <SessionEventContainer history={history} queryClient={queryClient} />}
<SessionEventContainer history={history} queryClient={queryClient} />
<Switch>
<TitledRoute
name="home"
Expand Down
2 changes: 1 addition & 1 deletion src/components/Login/LoginCtrl.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ class LoginCtrl extends Component {
}

handleSubmit = (data) => {
return requestLogin(this.props.okapiUrl, this.context.store, this.tenant, data)
return requestLogin(this.props.okapiUrl, this.context.store, this.props.tenant, data)
.then(this.handleSuccessfulLogin)
.catch(e => {
console.error(e); // eslint-disable-line no-console
Expand Down
20 changes: 9 additions & 11 deletions src/components/Root/Root.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,18 +66,16 @@ class Root extends Component {
// enhanced security mode:
// * configure fetch and xhr interceptors to conduct RTR
// * see SessionEventContainer for RTR handling
if (this.props.config.useSecureTokens) {
const rtrConfig = configureRtr(this.props.config.rtr);
const rtrConfig = configureRtr(this.props.config.rtr);

this.ffetch = new FFetch({
logger: this.props.logger,
store,
rtrConfig,
okapi
});
this.ffetch.replaceFetch();
this.ffetch.replaceXMLHttpRequest();
}
this.ffetch = new FFetch({
logger: this.props.logger,
store,
rtrConfig,
okapi
});
this.ffetch.replaceFetch();
this.ffetch.replaceXMLHttpRequest();
}

componentDidMount() {
Expand Down
7 changes: 1 addition & 6 deletions src/components/SSOLanding/useSSOSession.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,9 @@ import { useLocation } from 'react-router-dom';
import { useCookies } from 'react-cookie';
import queryString from 'query-string';

import { config } from 'stripes-config';

import { defaultErrors } from '../../constants';
import { setAuthError } from '../../okapiActions';
import { requestUserWithPerms } from '../../loginServices';
import { parseJWT } from '../../helpers';

const getParams = (location) => {
const search = location.search;
Expand All @@ -24,9 +21,7 @@ const getToken = (cookies, params) => {
};

const getTenant = (params, token, store) => {
const tenant = config.useSecureTokens
? params?.tenantId
: parseJWT(token)?.tenant;
const tenant = params?.tenantId;

return tenant || store.getState()?.okapi?.tenant;
};
Expand Down
3 changes: 2 additions & 1 deletion src/components/SSOLanding/useSSOSession.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ describe('SSOLanding', () => {

it('should request user session when RTR is disabled and right tenant from ssoToken', () => {
const tokenTenant = 'tokenTenant';
const okapiTenant = 'okapiTenant';
const store = useStore();

useLocation.mockReturnValue({ search: `ssoToken=${ssoTokenValue}` });
Expand All @@ -97,7 +98,7 @@ describe('SSOLanding', () => {

renderHook(() => useSSOSession());

expect(requestUserWithPerms).toHaveBeenCalledWith(store.getState().okapi.url, store, tokenTenant, ssoTokenValue);
expect(requestUserWithPerms).toHaveBeenCalledWith(store.getState().okapi.url, store, okapiTenant, ssoTokenValue);
});

it('should request user session when RTR is enabled and right tenant from query params', () => {
Expand Down
84 changes: 41 additions & 43 deletions src/components/SessionEventContainer/SessionEventContainer.js
Original file line number Diff line number Diff line change
Expand Up @@ -188,62 +188,60 @@ const SessionEventContainer = ({ history }) => {
// i.e. same keys as channels, but the value is the identically named object
const channelListeners = { window, bc };

if (stripes.config.useSecureTokens) {
const { idleModalTTL, idleSessionTTL, activityEvents } = stripes.config.rtr;

// inactive timer: show the "keep working?" modal
const showModalIT = createInactivityTimer(ms(idleSessionTTL) - ms(idleModalTTL), () => {
stripes.logger.log('rtr', 'session idle; showing modal');
stripes.store.dispatch(toggleRtrModal(true));
setIsVisible(true);
});
showModalIT.signal();
const { idleModalTTL, idleSessionTTL, activityEvents } = stripes.config.rtr;

// inactive timer: logout
const logoutIT = createInactivityTimer(idleSessionTTL, () => {
stripes.logger.log('rtr', 'session idle; dispatching RTR_TIMEOUT_EVENT');
// set a localstorage key so other windows know it was a timeout
localStorage.setItem(RTR_TIMEOUT_EVENT, 'true');
// inactive timer: show the "keep working?" modal
const showModalIT = createInactivityTimer(ms(idleSessionTTL) - ms(idleModalTTL), () => {
stripes.logger.log('rtr', 'session idle; showing modal');
stripes.store.dispatch(toggleRtrModal(true));
setIsVisible(true);
});
showModalIT.signal();

// dispatch a timeout event for handling in this window
window.dispatchEvent(new Event(RTR_TIMEOUT_EVENT));
});
logoutIT.signal();
// inactive timer: logout
const logoutIT = createInactivityTimer(idleSessionTTL, () => {
stripes.logger.log('rtr', 'session idle; dispatching RTR_TIMEOUT_EVENT');
// set a localstorage key so other windows know it was a timeout
localStorage.setItem(RTR_TIMEOUT_EVENT, 'true');

timers.current = { showModalIT, logoutIT };
// dispatch a timeout event for handling in this window
window.dispatchEvent(new Event(RTR_TIMEOUT_EVENT));
});
logoutIT.signal();

// RTR error in this window: logout
channels.window[RTR_ERROR_EVENT] = (e) => thisWindowRtrError(e, stripes, history);
timers.current = { showModalIT, logoutIT };

// idle session timeout in this window: logout
channels.window[RTR_TIMEOUT_EVENT] = (e) => thisWindowRtrIstTimeout(e, stripes, history);
// RTR error in this window: logout
channels.window[RTR_ERROR_EVENT] = (e) => thisWindowRtrError(e, stripes, history);

// localstorage change in another window: logout?
channels.window.storage = (e) => otherWindowStorage(e, stripes, history);
// idle session timeout in this window: logout
channels.window[RTR_TIMEOUT_EVENT] = (e) => thisWindowRtrIstTimeout(e, stripes, history);

// activity in another window: send keep-alive to idle-timers.
channels.bc.message = (message) => otherWindowActivity(message, stripes, timers, setIsVisible);
// localstorage change in another window: logout?
channels.window.storage = (e) => otherWindowStorage(e, stripes, history);

// activity in this window: ping idle-timers and BroadcastChannel
activityEvents.forEach(eventName => {
channels.window[eventName] = (e) => thisWindowActivity(e, stripes, timers, bc);
});
// activity in another window: send keep-alive to idle-timers.
channels.bc.message = (message) => otherWindowActivity(message, stripes, timers, setIsVisible);

// activity in this window: ping idle-timers and BroadcastChannel
activityEvents.forEach(eventName => {
channels.window[eventName] = (e) => thisWindowActivity(e, stripes, timers, bc);
});

// fixed-length session: show session-is-ending warning
channels.window[RTR_FLS_WARNING_EVENT] = (e) => thisWindowRtrFlsWarning(e, stripes, setIsFlsVisible);
// fixed-length session: show session-is-ending warning
channels.window[RTR_FLS_WARNING_EVENT] = (e) => thisWindowRtrFlsWarning(e, stripes, setIsFlsVisible);

// fixed-length session: terminate session
channels.window[RTR_FLS_TIMEOUT_EVENT] = (e) => thisWindowRtrFlsTimeout(e, stripes, history);
// fixed-length session: terminate session
channels.window[RTR_FLS_TIMEOUT_EVENT] = (e) => thisWindowRtrFlsTimeout(e, stripes, history);


// add listeners
Object.entries(channels).forEach(([k, channel]) => {
Object.entries(channel).forEach(([e, h]) => {
stripes.logger.log('rtrv', `adding listener ${k}.${e}`);
channelListeners[k].addEventListener(e, h);
});
// add listeners
Object.entries(channels).forEach(([k, channel]) => {
Object.entries(channel).forEach(([e, h]) => {
stripes.logger.log('rtrv', `adding listener ${k}.${e}`);
channelListeners[k].addEventListener(e, h);
});
}
});

// cleanup: clear timers and event listeners
return () => {
Expand Down
10 changes: 0 additions & 10 deletions src/components/SessionEventContainer/SessionEventContainer.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,16 +43,6 @@ describe('SessionEventContainer', () => {
eventsPortalElement.id = eventsPortal;
document.body.appendChild(eventsPortalElement);
});
it('Renders nothing if useSecureTokens is false', async () => {
const insecureStripes = {
config: {
useSecureTokens: false,
},
};
render(<Harness stripes={insecureStripes}><SessionEventContainer /></Harness>);

expect(screen.queryByText('KeepWorkingModal')).toBe(null);
});

it('Shows a modal when idle timer expires', async () => {
render(<Harness stripes={stripes}><SessionEventContainer /></Harness>);
Expand Down
2 changes: 1 addition & 1 deletion src/loginServices.js
Original file line number Diff line number Diff line change
Expand Up @@ -878,7 +878,7 @@ export function checkOkapiSession(okapiUrl, store, tenant) {
* @returns {Promise}
*/
export function requestLogin(okapiUrl, store, tenant, data) {
const loginPath = config.useSecureTokens ? 'login-with-expiry' : 'login';
const loginPath = 'login-with-expiry';
return fetch(`${okapiUrl}/bl-users/${loginPath}?expandPermissions=true&fullPermissions=true`, {
body: JSON.stringify(data),
credentials: 'include',
Expand Down
2 changes: 1 addition & 1 deletion src/loginServices.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -754,7 +754,7 @@ describe('unauthorizedPath functions', () => {
);

expect(global.fetch).toHaveBeenCalledWith(
'http://okapi-url/bl-users/login?expandPermissions=true&fullPermissions=true',
'http://okapi-url/bl-users/login-with-expiry?expandPermissions=true&fullPermissions=true',
expect.objectContaining({
method: 'POST',
headers: expect.objectContaining({
Expand Down
17 changes: 0 additions & 17 deletions test/bigtest/network/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -86,23 +86,6 @@ export default function configure() {

this.post('/authn/logout', {}, 204);

this.post('/bl-users/login', () => {
return new Response(201, {}, {
user: {
id: 'test',
username: 'testuser',
personal: {
lastName: 'User',
firstName: 'Test',
email: '[email protected]',
}
},
permissions: {
permissions: []
}
});
});

this.post('/bl-users/login-with-expiry', () => {
return new Response(201, {}, {
user: {
Expand Down

0 comments on commit f768417

Please sign in to comment.