Added a CSRF bypass to enable OAuth

issue https://github.com/TryGhost/Team/issues/614
This commit is contained in:
Thibaut Patel 2021-05-14 17:38:28 +02:00
parent 6a08297c3a
commit 6bfefa02ac
3 changed files with 85 additions and 4 deletions

View File

@ -119,7 +119,10 @@ module.exports = function createSessionService({getSession, findUserById, getOri
}
const session = await getSession(req, res);
cookieCsrfProtection(req, session);
// Enable CSRF bypass (useful for OAuth for example)
if (!res || !res.locals || !res.locals.bypassCsrfProtection) {
cookieCsrfProtection(req, session);
}
if (!session || !session.user_id) {
return null;

View File

@ -52,5 +52,83 @@ describe('SessionService', function () {
await sessionService.destroyCurrentSession(req, res);
should.ok(req.session.destroy.calledOnce);
});
});
it('Throws an error when the csrf verification fails', async function () {
const getSession = async (req) => {
if (req.session) {
return req.session;
}
req.session = {
origin: 'origin'
};
return req.session;
};
const findUserById = sinon.spy(async ({id}) => ({id}));
const getOriginOfRequest = sinon.stub().returns('other-origin');
const sessionService = SessionService({
getSession,
findUserById,
getOriginOfRequest
});
const req = Object.create(express.request, {
ip: {
value: '0.0.0.0'
},
headers: {
value: {
cookie: 'thing'
}
},
get: {
value: () => 'Fake'
}
});
const res = Object.create(express.response);
const error = `Request made from incorrect origin. Expected 'origin' received 'other-origin'.`;
await sessionService.getUserForSession(req, res).should.be.rejectedWith(error);
});
it('Doesn\'t throw an error when the csrf verification fails when bypassed', async function () {
const getSession = async (req) => {
if (req.session) {
return req.session;
}
req.session = {
origin: 'origin'
};
return req.session;
};
const findUserById = sinon.spy(async ({id}) => ({id}));
const getOriginOfRequest = sinon.stub().returns('other-origin');
const sessionService = SessionService({
getSession,
findUserById,
getOriginOfRequest
});
const req = Object.create(express.request, {
ip: {
value: '0.0.0.0'
},
headers: {
value: {
cookie: 'thing'
}
},
get: {
value: () => 'Fake'
}
});
const res = Object.create(express.response);
res.locals = {
bypassCsrfProtection: true
};
await sessionService.getUserForSession(req, res).should.be.fulfilled();
});
});

View File

@ -1,8 +1,8 @@
declare function _exports({ getSession, findUserById, getOriginOfRequest }: {
getSession: (req: import("express").Request<import("express-serve-static-core").ParamsDictionary>, res: import("express").Response<any>) => Promise<import("./lib/SessionService").Session>;
getSession: (req: import("express").Request<import("express-serve-static-core").ParamsDictionary, any, any, qs.ParsedQs, Record<string, any>>, res: import("express").Response<any, Record<string, any>>) => Promise<import("./lib/SessionService").Session>;
findUserById: (data: {
id: string;
}) => Promise<import("./lib/SessionService").User>;
getOriginOfRequest: (req: import("express").Request<import("express-serve-static-core").ParamsDictionary>) => string;
getOriginOfRequest: (req: import("express").Request<import("express-serve-static-core").ParamsDictionary, any, any, qs.ParsedQs, Record<string, any>>) => string;
}): import("./lib/SessionService").SessionService;
export = _exports;