mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-02-03 23:00:14 -05:00
Implemented MVP
This commit is contained in:
parent
47f46d5b9b
commit
2e40e253d6
1 changed files with 106 additions and 0 deletions
|
@ -0,0 +1,106 @@
|
||||||
|
const concat = require('concat-stream');
|
||||||
|
const Cookies = require('cookies');
|
||||||
|
const jwt = require('jsonwebtoken');
|
||||||
|
const ignition = require('ghost-ignition');
|
||||||
|
|
||||||
|
const {
|
||||||
|
UnauthorizedError,
|
||||||
|
BadRequestError
|
||||||
|
} = ignition.errors;
|
||||||
|
|
||||||
|
const EMPTY = {};
|
||||||
|
const SIX_MONTHS_MS = 1000 * 60 * 60 * 24 * 184;
|
||||||
|
|
||||||
|
const wrapFn = (fn, cookieConfig) => (req, res) => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const cookies = new Cookies(req, res, cookieConfig);
|
||||||
|
req.on('error', reject);
|
||||||
|
req.pipe(concat(function (buff) {
|
||||||
|
const body = buff.toString();
|
||||||
|
resolve(fn(req, res, {body, cookies}));
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = function create(options = EMPTY) {
|
||||||
|
if (options === EMPTY) {
|
||||||
|
throw new Error('Must pass options');
|
||||||
|
}
|
||||||
|
|
||||||
|
const {
|
||||||
|
cookieMaxAge = SIX_MONTHS_MS,
|
||||||
|
cookieSecure = true,
|
||||||
|
cookieName = 'members-ssr',
|
||||||
|
cookiePath = '/',
|
||||||
|
cookieKeys,
|
||||||
|
membersApi
|
||||||
|
} = options;
|
||||||
|
|
||||||
|
if (!membersApi) {
|
||||||
|
throw new Error('Missing option membersApi');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!cookieKeys) {
|
||||||
|
throw new Error('Missing option cookieKeys');
|
||||||
|
}
|
||||||
|
|
||||||
|
const audience = ['members-ssr'];
|
||||||
|
|
||||||
|
const cookieConfig = {
|
||||||
|
keys: [].concat(cookieKeys),
|
||||||
|
secure: cookieSecure
|
||||||
|
};
|
||||||
|
|
||||||
|
const verifyJwt = token => membersApi.getPublicConfig().then(({publicKey, issuer}) => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
jwt.verify(token, publicKey, {
|
||||||
|
algorithms: ['RS512'],
|
||||||
|
issuer,
|
||||||
|
audience
|
||||||
|
}, (err, claims) => {
|
||||||
|
if (err) {
|
||||||
|
reject(new UnauthorizedError({err}));
|
||||||
|
}
|
||||||
|
resolve(claims);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
const exchangeTokenForSession = wrapFn((req, res, {body, cookies}) => {
|
||||||
|
const token = body;
|
||||||
|
if (!body || typeof body !== 'string') {
|
||||||
|
throw new BadRequestError({
|
||||||
|
message: 'Expected body containing JWT'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return verifyJwt(token).then(() => {
|
||||||
|
cookies.set(cookieName, token, {
|
||||||
|
signed: true,
|
||||||
|
httpOnly: true,
|
||||||
|
sameSite: 'lax',
|
||||||
|
maxAge: cookieMaxAge,
|
||||||
|
path: cookiePath
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}, cookieConfig);
|
||||||
|
|
||||||
|
const getMemberDataFromSession = wrapFn((req, res, {cookies}) => {
|
||||||
|
const token = cookies.get(cookieName, {
|
||||||
|
signed: true
|
||||||
|
});
|
||||||
|
if (!token) {
|
||||||
|
throw new BadRequestError({
|
||||||
|
message: `Cookie ${cookieName} not found`
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return verifyJwt(token).then((claims) => {
|
||||||
|
return membersApi.getMember(claims.sub, token);
|
||||||
|
});
|
||||||
|
}, cookieConfig);
|
||||||
|
|
||||||
|
return {
|
||||||
|
exchangeTokenForSession,
|
||||||
|
getMemberDataFromSession
|
||||||
|
};
|
||||||
|
};
|
Loading…
Add table
Reference in a new issue