Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .migrate
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
{
"lastRun": "1720532975152-add-isfetchingintialdata.ts",
"lastRun": "1738072787796-update-user-documents-for-telegram-login.ts",
"migrations": [
{
"title": "1720532975152-add-isfetchingintialdata.ts",
"timestamp": 1720533282435
"title": "1738072787796-update-user-documents-for-telegram-login.ts",
"timestamp": 1738073593695
}
]
}
95 changes: 51 additions & 44 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
"@notionhq/client": "^2.2.3",
"@sentry/node": "^7.50.0",
"@temporalio/client": "^1.11.3",
"@togethercrew.dev/db": "^3.0.79",
"@togethercrew.dev/db": "^3.2.3",
"@togethercrew.dev/tc-messagebroker": "^0.0.50",
"@types/express-session": "^1.17.7",
"@types/morgan": "^1.9.5",
Expand All @@ -54,7 +54,7 @@
"moment": "^2.29.4",
"moment-timezone": "^0.5.40",
"mongodb": "^4.12.1",
"mongoose": "^6.7.5",
"mongoose": "^6.13.8",
"morgan": "^1.10.0",
"neo4j-driver": "^5.9.0",
"node-fetch": "^2.6.7",
Expand Down
17 changes: 9 additions & 8 deletions src/app.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
import compression from 'compression';
import cors from 'cors';
import express, { Application } from 'express';
import session from 'express-session';
import helmet from 'helmet';
import compression from 'compression';
import httpStatus from 'http-status';
import passport from 'passport';

import { bullBoardServerAdapter } from './bullmq';
import config from './config';
import morgan from './config/morgan';
import { jwtStrategy } from './config/passport';
import cors from 'cors';
import httpStatus from 'http-status';
import { error, sentry } from './middlewares';
import { ApiError } from './utils';
import routes from './routes/v1';
import morgan from './config/morgan';
import config from './config';
import session from 'express-session';
import { bullBoardServerAdapter } from './bullmq';
import { ApiError } from './utils';

const app: Application = express();

Expand Down
4 changes: 4 additions & 0 deletions src/config/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ const envVarsSchema = Joi.object()
RABBIT_PORT: Joi.string().required().description('RabbitMQ port'),
RABBIT_USER: Joi.string().required().description('RabbitMQ username'),
RABBIT_PASSWORD: Joi.string().required().description('RabbitMQ password'),
TELEGRAM_BOT_TOKEN: Joi.string().required().description('Telegram bot token'),
DISCORD_CLIENT_ID: Joi.string().required().description('Discord clinet id'),
DISCORD_CLIENT_SECRET: Joi.string().required().description('Discord clinet secret'),
DISCORD_BOT_TOKEN: Joi.string().required().description('Discord bot token'),
Expand Down Expand Up @@ -134,6 +135,9 @@ export default {
connect: envVars.NOTION_CONNECT_CALLBACK_URI,
},
},
telegram: {
botToken: envVars.TELEGRAM_BOT_TOKEN,
},
},
jwt: {
secret: envVars.JWT_SECRET,
Expand Down
62 changes: 26 additions & 36 deletions src/controllers/auth.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import querystring from 'querystring';
import config from '../config';
import logger from '../config/logger';
import { discord, generateState } from '../config/oAtuh2';
import { ISessionRequest } from '../interfaces';
import { authService, discordServices, tokenService, userService } from '../services';
import { ISessionRequest, TelegramCallbackParams } from '../interfaces';
import { authService, discordServices, telegramService, tokenService } from '../services';
import { catchAsync } from '../utils';

const discordAuthorize = catchAsync(async function (req: ISessionRequest, res: Response) {
Expand All @@ -18,47 +18,41 @@ const discordAuthorize = catchAsync(async function (req: ISessionRequest, res: R
});

const discordAuthorizeCallback = catchAsync(async function (req: ISessionRequest, res: Response) {
const STATUS_CODE_SINGIN = 1001;
const STATUS_CODE_LOGIN = 1002;
const STATUS_CODE_ERROR = 1003;
const code = req.query.code as string;
const returnedState = req.query.state as string;
const storedState = req.session.state;
let statusCode = STATUS_CODE_LOGIN;
try {
if (!code || !returnedState || returnedState !== storedState) {
throw new Error('Invalid code or state mismatch');
}
const discordOathCallback = await discordServices.coreService.exchangeCode(
const code = req.query.code as string;
const returnedState = req.query.state as string;
const storedState = req.session.state;
const redirectUrl = await discordServices.authService.handleOAuthCallback({
code,
config.oAuth2.discord.callbackURI.authorize,
);
const discordUser = await discordServices.coreService.getUserFromDiscordAPI(discordOathCallback.access_token);
let user = await userService.getUserByFilter({ discordId: discordUser.id });
state: returnedState,
storedState,
});

if (!user) {
user = await userService.createUser({ discordId: discordUser.id });
statusCode = STATUS_CODE_SINGIN;
}
tokenService.saveDiscordOAuth2Tokens(user.id, discordOathCallback);
const tokens = await tokenService.generateAuthTokens(user);
res.redirect(redirectUrl);
} catch (err) {
logger.error({ err }, 'Failed to authorize Discord account');
const params = {
statusCode: statusCode,
accessToken: tokens.access.token,
accessExp: tokens.access.expires.toString(),
refreshToken: tokens.refresh.token,
refreshExp: tokens.refresh.expires.toString(),
statusCode: 1003,
};
const query = querystring.stringify(params);
res.redirect(`${config.frontend.url}/callback?` + query);
res.redirect(`${config.frontend.url}/callback?${query}`);
}
});
Comment on lines +22 to +40
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add explicit state validation before proceeding with OAuth.

While the code handles the state parameter, it should explicitly validate that both states exist and match before proceeding with the OAuth callback.

Consider this improvement:

     const code = req.query.code as string;
     const returnedState = req.query.state as string;
     const storedState = req.session.state;
+    if (!returnedState || !storedState || returnedState !== storedState) {
+      throw new Error('Invalid state parameter');
+    }
     const redirectUrl = await discordServices.authService.handleOAuthCallback({
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const code = req.query.code as string;
const returnedState = req.query.state as string;
const storedState = req.session.state;
const redirectUrl = await discordServices.authService.handleOAuthCallback({
code,
config.oAuth2.discord.callbackURI.authorize,
);
const discordUser = await discordServices.coreService.getUserFromDiscordAPI(discordOathCallback.access_token);
let user = await userService.getUserByFilter({ discordId: discordUser.id });
state: returnedState,
storedState,
});
if (!user) {
user = await userService.createUser({ discordId: discordUser.id });
statusCode = STATUS_CODE_SINGIN;
}
tokenService.saveDiscordOAuth2Tokens(user.id, discordOathCallback);
const tokens = await tokenService.generateAuthTokens(user);
res.redirect(redirectUrl);
} catch (err) {
logger.error({ err }, 'Failed to authorize Discord account');
const params = {
statusCode: statusCode,
accessToken: tokens.access.token,
accessExp: tokens.access.expires.toString(),
refreshToken: tokens.refresh.token,
refreshExp: tokens.refresh.expires.toString(),
statusCode: 1003,
};
const query = querystring.stringify(params);
res.redirect(`${config.frontend.url}/callback?` + query);
res.redirect(`${config.frontend.url}/callback?${query}`);
}
});
const code = req.query.code as string;
const returnedState = req.query.state as string;
const storedState = req.session.state;
if (!returnedState || !storedState || returnedState !== storedState) {
throw new Error('Invalid state parameter');
}
const redirectUrl = await discordServices.authService.handleOAuthCallback({
code,
state: returnedState,
storedState,
});
res.redirect(redirectUrl);
} catch (err) {
logger.error({ err }, 'Failed to authorize Discord account');
const params = {
statusCode: 1003,
};
const query = querystring.stringify(params);
res.redirect(`${config.frontend.url}/callback?${query}`);
}
});


const telegramAuthorizeCallback = catchAsync(async function (req: Request, res: Response) {
try {
const params: TelegramCallbackParams = req.query as unknown as TelegramCallbackParams;

const redirectUrl = await telegramService.authService.handleOAuthCallback(params);
res.redirect(redirectUrl);
} catch (err) {
logger.error({ err }, 'Failed to authorize discord account');
logger.error({ err }, 'Failed to authorize Telegram account');

const params = {
statusCode: STATUS_CODE_ERROR,
statusCode: 1003,
};
const query = querystring.stringify(params);
res.redirect(`${config.frontend.url}/callback?` + query);
res.redirect(`${config.frontend.url}/callback?${query}`);
}
});

Expand All @@ -78,10 +72,6 @@ const generateToken = catchAsync(async function (req: Request, res: Response) {
res.send(token);
});

const telegramAuthorizeCallback = catchAsync(async function (req: Request, res: Response) {
console.log(req.body, req.query, req.params);
res.send('Hi');
});
export default {
discordAuthorize,
discordAuthorizeCallback,
Expand Down
Loading