mirror of
https://github.com/apotdevin/thunderhub.git
synced 2025-02-24 06:47:41 +01:00
113 lines
3 KiB
TypeScript
113 lines
3 KiB
TypeScript
import getConfig from 'next/config';
|
|
import jwt from 'jsonwebtoken';
|
|
import { readCookie, refreshCookie } from 'server/helpers/fileHelpers';
|
|
import { ContextType } from 'server/types/apiTypes';
|
|
import { SSO_ACCOUNT, SERVER_ACCOUNT } from 'src/context/AccountContext';
|
|
import { logger } from 'server/helpers/logger';
|
|
import cookie from 'cookie';
|
|
import { requestLimiter } from 'server/helpers/rateLimiter';
|
|
import bcrypt from 'bcryptjs';
|
|
|
|
const { serverRuntimeConfig } = getConfig() || {};
|
|
const { cookiePath, nodeEnv } = serverRuntimeConfig || {};
|
|
|
|
export const authResolvers = {
|
|
Query: {
|
|
getAuthToken: async (_: undefined, params: any, context: ContextType) => {
|
|
const { ip, secret, sso, res } = context;
|
|
await requestLimiter(ip, 'getAuthToken');
|
|
|
|
if (!sso.host || !sso.macaroon) {
|
|
logger.warn('Host and macaroon are required for SSO');
|
|
return null;
|
|
}
|
|
|
|
if (!params.cookie) {
|
|
return null;
|
|
}
|
|
|
|
if (cookiePath === '') {
|
|
logger.warn('SSO auth not available since no cookie path was provided');
|
|
return null;
|
|
}
|
|
|
|
const cookieFile = readCookie(cookiePath);
|
|
|
|
if (
|
|
cookieFile.trim() === params.cookie.trim() ||
|
|
nodeEnv === 'development'
|
|
) {
|
|
refreshCookie(cookiePath);
|
|
const token = jwt.sign({ user: SSO_ACCOUNT }, secret);
|
|
|
|
res.setHeader(
|
|
'Set-Cookie',
|
|
cookie.serialize('SSOAuth', token, { httpOnly: true, sameSite: true })
|
|
);
|
|
return true;
|
|
}
|
|
|
|
logger.debug(`Cookie ${params.cookie} different to file ${cookieFile}`);
|
|
return null;
|
|
},
|
|
getSessionToken: async (
|
|
_: undefined,
|
|
params: any,
|
|
context: ContextType
|
|
) => {
|
|
const { ip, secret, res } = context;
|
|
await requestLimiter(ip, 'getSessionToken');
|
|
|
|
const account = context.accounts.find(a => a.id === params.id) || null;
|
|
|
|
if (!account) {
|
|
logger.debug(`Account ${params.id} not found`);
|
|
return null;
|
|
}
|
|
|
|
const isPassword = bcrypt.compareSync(params.password, account.password);
|
|
|
|
if (!isPassword) {
|
|
throw new Error('WrongPasswordForLogin');
|
|
}
|
|
|
|
logger.debug(`Correct password for account ${params.id}`);
|
|
const token = jwt.sign(
|
|
{
|
|
id: params.id,
|
|
},
|
|
secret
|
|
);
|
|
res.setHeader(
|
|
'Set-Cookie',
|
|
cookie.serialize('AccountAuth', token, {
|
|
httpOnly: true,
|
|
sameSite: true,
|
|
})
|
|
);
|
|
return true;
|
|
},
|
|
},
|
|
Mutation: {
|
|
logout: async (_: undefined, params: any, context: ContextType) => {
|
|
const { ip, res } = context;
|
|
await requestLimiter(ip, 'logout');
|
|
|
|
if (params.type === SSO_ACCOUNT) {
|
|
res.setHeader(
|
|
'Set-Cookie',
|
|
cookie.serialize('SSOAuth', '', { maxAge: 1 })
|
|
);
|
|
return true;
|
|
}
|
|
if (params.type === SERVER_ACCOUNT) {
|
|
res.setHeader(
|
|
'Set-Cookie',
|
|
cookie.serialize('AccountAuth', '', { maxAge: 1 })
|
|
);
|
|
return true;
|
|
}
|
|
return true;
|
|
},
|
|
},
|
|
};
|