Files
hoppscotch/packages/hoppscotch-backend/src/auth/helper.ts
2024-03-05 18:05:58 +05:30

128 lines
3.5 KiB
TypeScript

import { HttpException, HttpStatus } from '@nestjs/common';
import { DateTime } from 'luxon';
import { AuthTokens } from 'src/types/AuthTokens';
import { Response } from 'express';
import * as cookie from 'cookie';
import { AUTH_PROVIDER_NOT_SPECIFIED, COOKIES_NOT_FOUND } from 'src/errors';
import { throwErr } from 'src/utils';
import { ConfigService } from '@nestjs/config';
enum AuthTokenType {
ACCESS_TOKEN = 'access_token',
REFRESH_TOKEN = 'refresh_token',
}
export enum Origin {
ADMIN = 'admin',
APP = 'app',
}
export enum AuthProvider {
GOOGLE = 'GOOGLE',
GITHUB = 'GITHUB',
MICROSOFT = 'MICROSOFT',
EMAIL = 'EMAIL',
}
/**
* Sets and returns the cookies in the response object on successful authentication
* @param res Express Response Object
* @param authTokens Object containing the access and refresh tokens
* @param redirect if true will redirect to provided URL else just send a 200 status code
*/
export const authCookieHandler = (
res: Response,
authTokens: AuthTokens,
redirect: boolean,
redirectUrl: string | null,
) => {
const configService = new ConfigService();
const currentTime = DateTime.now();
const accessTokenValidity = currentTime
.plus({
milliseconds: parseInt(configService.get('ACCESS_TOKEN_VALIDITY')),
})
.toMillis();
const refreshTokenValidity = currentTime
.plus({
milliseconds: parseInt(configService.get('REFRESH_TOKEN_VALIDITY')),
})
.toMillis();
res.cookie(AuthTokenType.ACCESS_TOKEN, authTokens.access_token, {
httpOnly: true,
secure: true,
sameSite: 'lax',
maxAge: accessTokenValidity,
});
res.cookie(AuthTokenType.REFRESH_TOKEN, authTokens.refresh_token, {
httpOnly: true,
secure: true,
sameSite: 'lax',
maxAge: refreshTokenValidity,
});
if (!redirect) {
return res.status(HttpStatus.OK).send();
}
// check to see if redirectUrl is a whitelisted url
const whitelistedOrigins = configService
.get('WHITELISTED_ORIGINS')
.split(',');
if (!whitelistedOrigins.includes(redirectUrl))
// if it is not redirect by default to REDIRECT_URL
redirectUrl = configService.get('REDIRECT_URL');
return res.status(HttpStatus.OK).redirect(redirectUrl);
};
/**
* Decode the cookie header from incoming websocket connects and returns a auth token pair
* @param rawCookies cookies from the websocket connection
* @returns AuthTokens for JWT strategy to use
*/
export const subscriptionContextCookieParser = (rawCookies: string) => {
const cookies = cookie.parse(rawCookies);
if (
!cookies[AuthTokenType.ACCESS_TOKEN] &&
!cookies[AuthTokenType.REFRESH_TOKEN]
) {
throw new HttpException(COOKIES_NOT_FOUND, 400, {
cause: new Error(COOKIES_NOT_FOUND),
});
}
return <AuthTokens>{
access_token: cookies[AuthTokenType.ACCESS_TOKEN],
refresh_token: cookies[AuthTokenType.REFRESH_TOKEN],
};
};
/**
* Check to see if given auth provider is present in the VITE_ALLOWED_AUTH_PROVIDERS env variable
*
* @param provider Provider we want to check the presence of
* @returns Boolean if provider specified is present or not
*/
export function authProviderCheck(
provider: string,
VITE_ALLOWED_AUTH_PROVIDERS: string,
) {
if (!provider) {
throwErr(AUTH_PROVIDER_NOT_SPECIFIED);
}
const envVariables = VITE_ALLOWED_AUTH_PROVIDERS
? VITE_ALLOWED_AUTH_PROVIDERS.split(',').map((provider) =>
provider.trim().toUpperCase(),
)
: [];
if (!envVariables.includes(provider.toUpperCase())) return false;
return true;
}