mirror of
https://github.com/Spengreb/sync.git
synced 2026-06-10 15:22:04 +00:00
Protect /api/v1 mutations with CSRF for cookie auth while exempting cbt_ bearer bot tokens and wiring UI X-CSRF-Token headers
This commit is contained in:
parent
12696452aa
commit
6eeee342d7
4 changed files with 49 additions and 1 deletions
|
|
@ -37,7 +37,9 @@ exports.init = function csrfInit (domain) {
|
|||
|
||||
exports.verify = function csrfVerify(req) {
|
||||
var secret = req.signedCookies._csrf;
|
||||
var token = req.body._csrf || req.query._csrf;
|
||||
var token = (req.body && req.body._csrf) ||
|
||||
(req.query && req.query._csrf) ||
|
||||
req.header('x-csrf-token');
|
||||
|
||||
if (!tokens.verify(secret, token)) {
|
||||
throw new CSRFError('Invalid CSRF token');
|
||||
|
|
|
|||
|
|
@ -1,7 +1,30 @@
|
|||
const express = require('express');
|
||||
const csrf = require('../../csrf');
|
||||
|
||||
const router = express.Router();
|
||||
|
||||
function isMutatingMethod(method) {
|
||||
return method === 'POST' || method === 'PUT' || method === 'PATCH' || method === 'DELETE';
|
||||
}
|
||||
|
||||
function hasBotBearerToken(req) {
|
||||
const authHeader = req.headers && req.headers.authorization;
|
||||
return typeof authHeader === 'string' && /^Bearer\s+cbt_/.test(authHeader);
|
||||
}
|
||||
|
||||
router.use((req, res, next) => {
|
||||
if (!isMutatingMethod(req.method) || hasBotBearerToken(req)) {
|
||||
return next();
|
||||
}
|
||||
|
||||
try {
|
||||
csrf.verify(req);
|
||||
next();
|
||||
} catch (_err) {
|
||||
return res.status(403).json({ error: 'Invalid CSRF token' });
|
||||
}
|
||||
});
|
||||
|
||||
router.use('/channels/:channel/bots', require('./bots'));
|
||||
router.use('/channels/:channel/emotes', require('./emotes'));
|
||||
router.use('/channels/:channel/playlist', require('./playlist'));
|
||||
|
|
|
|||
|
|
@ -15,10 +15,12 @@ mixin head()
|
|||
var DEFAULT_THEME = '#{DEFAULT_THEME}';
|
||||
var CHANNELPATH = '#{channelPath}';
|
||||
var CHANNELNAME = '#{channelName}';
|
||||
var CSRF_TOKEN = '#{csrfToken}';
|
||||
else
|
||||
script(type="text/javascript").
|
||||
var DEFAULT_THEME = '#{DEFAULT_THEME}';
|
||||
var CHANNELPATH = '#{channelPath}';
|
||||
var CSRF_TOKEN = '#{csrfToken}';
|
||||
|
||||
script(src="/js/theme.js")
|
||||
//[if lt IE 9]
|
||||
|
|
|
|||
21
www/js/ui.js
21
www/js/ui.js
|
|
@ -1257,6 +1257,27 @@ $("#resize-video-smaller").on('click', function () {
|
|||
}
|
||||
});
|
||||
|
||||
$.ajaxPrefilter(function (options, _originalOptions, _jqXHR) {
|
||||
var url = String(options.url || '');
|
||||
if (!/\/api\/v1\//.test(url)) {
|
||||
return;
|
||||
}
|
||||
|
||||
var method = String(options.type || options.method || 'GET').toUpperCase();
|
||||
if (method === 'GET' || method === 'HEAD' || method === 'OPTIONS') {
|
||||
return;
|
||||
}
|
||||
|
||||
options.headers = options.headers || {};
|
||||
if (options.headers.Authorization || options.headers.authorization) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (typeof CSRF_TOKEN === 'string' && CSRF_TOKEN.length > 0) {
|
||||
options.headers['X-CSRF-Token'] = CSRF_TOKEN;
|
||||
}
|
||||
});
|
||||
|
||||
var CSTBots = (function () {
|
||||
function apiBase() {
|
||||
return '/api/v1/channels/' + CHANNEL.name;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue