diff --git a/src/backend/src/routers/auth/revoke-session.js b/src/backend/src/routers/auth/revoke-session.js index c5195c72..ff23d143 100644 --- a/src/backend/src/routers/auth/revoke-session.js +++ b/src/backend/src/routers/auth/revoke-session.js @@ -36,6 +36,11 @@ module.exports = eggspress('/auth/revoke-session', { throw APIError.create('forbidden'); } + const svc_antiCSRF = req.services.get('anti-csrf'); + if ( ! svc_antiCSRF.consume_token(actor.type.user.uuid, req.body.anti_csrf) ) { + return res.status(400).json({ message: 'incorrect anti-CSRF token' }); + } + // Ensure valid UUID if ( ! req.body.uuid || typeof req.body.uuid !== 'string' ) { throw APIError.create('field_invalid', null, { diff --git a/src/gui/src/UI/UIWindowManageSessions.js b/src/gui/src/UI/UIWindowManageSessions.js index 9515c2ae..48819c55 100644 --- a/src/gui/src/UI/UIWindowManageSessions.js +++ b/src/gui/src/UI/UIWindowManageSessions.js @@ -105,6 +105,9 @@ const UIWindowManageSessions = async function UIWindowManageSessions (options) { if ( alert_resp !== 'yes' ) { return; } + + + const anti_csrf = await services.get('anti-csrf').token(); const resp = await fetch(`${window.api_origin}/auth/revoke-session`, { method: 'POST', @@ -114,6 +117,7 @@ const UIWindowManageSessions = async function UIWindowManageSessions (options) { }, body: JSON.stringify({ uuid: session.uuid, + anti_csrf, }), }); if ( resp.ok ) { diff --git a/src/gui/src/initgui.js b/src/gui/src/initgui.js index cd7bf0b3..efdadc45 100644 --- a/src/gui/src/initgui.js +++ b/src/gui/src/initgui.js @@ -45,6 +45,7 @@ import UIComponentWindow from './UI/UIComponentWindow.js'; import update_mouse_position from './helpers/update_mouse_position.js'; import { LaunchOnInitService } from './services/LaunchOnInitService.js'; import item_icon from './helpers/item_icon.js'; +import { AntiCSRFService } from './services/AntiCSRFService.js'; const launch_services = async function (options) { // === Services Data Structures === @@ -79,6 +80,7 @@ const launch_services = async function (options) { register('process', new ProcessService()); register('locale', new LocaleService()); register('settings', new SettingsService()); + register('anti-csrf', new AntiCSRFService()); register('__launch-on-init', new LaunchOnInitService()); // === Service-Script Services === diff --git a/src/gui/src/services/AntiCSRFService.js b/src/gui/src/services/AntiCSRFService.js new file mode 100644 index 00000000..d5e65a2a --- /dev/null +++ b/src/gui/src/services/AntiCSRFService.js @@ -0,0 +1,23 @@ +import { Service } from "../definitions.js"; + +export class AntiCSRFService extends Service { + /** + * Request an anti-csrf token from the server + * @return anti_csrf: string + */ + async token () { + const anti_csrf = await (async () => { + const resp = await fetch( + `${window.gui_origin}/get-anticsrf-token`,{ + headers: { + 'Content-Type': 'application/json', + 'Authorization': 'Bearer ' + window.auth_token, + } + },) + const { token } = await resp.json(); + return token; + })(); + + return anti_csrf; + } +}