Skip to content
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions ui/src/main/js/Index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import rootReducer from 'store/reducers';
import { ThemeProvider } from 'react-jss';
import theme from '_theme';
import { dom } from '@fortawesome/fontawesome-svg-core';
import HttpInterceptor from 'common/util/HttpInterceptor';

const initialState = {};
// Setup history
Expand All @@ -18,6 +19,9 @@ const history = createHistory();
// Configure store with redux, thunk and history
const store = createStore(rootReducer(history), initialState, applyMiddleware(thunk, routerMiddleware(history)));

// Set up HTTP interceptor for 401 handling
HttpInterceptor.setupGlobalInterceptor(store);

dom.watch({
autoReplaceSvgRoot: document
});
Expand Down
46 changes: 46 additions & 0 deletions ui/src/main/js/common/util/HttpInterceptor.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
class HttpInterceptor {
static AUTH_ENDPOINTS = [
'/alert/api/login',
'/alert/api/verify',
'/alert/api/csrf',
'/alert/api/verify/saml',
'/alert/api/logout'
];

static isAuthEndpoint(url) {
return this.AUTH_ENDPOINTS.some(endpoint => url.includes(endpoint));
}

static isAlertApiCall(url) {
return url && url.includes('/alert/api/');
}

static shouldHandleUnauthorized(response, url) {
return response.status === 401 &&
this.isAlertApiCall(url) &&
!this.isAuthEndpoint(url);
}

static setupGlobalInterceptor(store) {
const { unauthorized } = require('../../store/actions/session');
const originalFetch = window.fetch;

window.fetch = async (...args) => {
try {
const response = await originalFetch(...args);
if (this.shouldHandleUnauthorized(response, args[0])) {
// if (this.shouldHandleUnauthorized({status: 401, ...response}, args[0])) {
Copy link

Copilot AI Sep 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove this commented-out debugging code before merging to production.

Suggested change
// if (this.shouldHandleUnauthorized({status: 401, ...response}, args[0])) {

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Keeping this in for testing purposes

Comment on lines +47 to +48
Copy link

Copilot AI Sep 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The URL parameter (args[0]) may not always be a string. When using fetch with a Request object, args[0] would be a Request instance, not a URL string. Consider extracting the URL properly: const url = typeof args[0] === 'string' ? args[0] : args[0].url;

Suggested change
if (this.shouldHandleUnauthorized(response, args[0])) {
// if (this.shouldHandleUnauthorized({status: 401, ...response}, args[0])) {
const url = typeof args[0] === 'string' ? args[0] : args[0].url;
if (this.shouldHandleUnauthorized(response, url)) {

Copilot uses AI. Check for mistakes.
console.log('Unauthorized access detected, logging out user');
store.dispatch(unauthorized());
}

return response;
} catch (error) {
// Don't interfere with network errors
throw error;
}
};
}
}

export default HttpInterceptor;