Skip to content

Commit 6b2aede

Browse files
authored
Merge pull request #78 from CS3219-AY2425S1/ms4
Milestone-D4
2 parents 353ec8d + 41dd2d6 commit 6b2aede

File tree

172 files changed

+13927
-1356
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

172 files changed

+13927
-1356
lines changed

.vscode/settings.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
{
2+
}

backend/auth-service/.env.example

Lines changed: 0 additions & 22 deletions
This file was deleted.

backend/auth-service/package-lock.json

Lines changed: 13 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

backend/auth-service/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
"bcryptjs": "^2.4.3",
3232
"class-transformer": "^0.5.1",
3333
"class-validator": "^0.14.1",
34+
"dotenv": "^16.4.5",
3435
"google-auth-library": "^9.14.1",
3536
"nodemailer": "^6.9.15",
3637
"passport": "^0.7.0",

backend/auth-service/src/app.module.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,19 +11,22 @@ import {
1111
GoogleStrategy,
1212
GithubStrategy,
1313
} from './strategies';
14+
import { config } from './configs';
1415

1516
@Module({
1617
imports: [
17-
PassportModule.register({ defaultStrategy: 'jwt' }),
18+
PassportModule.register({
19+
defaultStrategy: config.strategies.accessTokenStrategy,
20+
}),
1821
HttpModule,
1922
JwtModule.register({}),
2023
ClientsModule.register([
2124
{
2225
name: 'USER_SERVICE',
23-
transport: Transport.TCP,
26+
transport: config.userService.transport,
2427
options: {
25-
host: 'user-service',
26-
port: 3001,
28+
host: config.userService.host,
29+
port: config.userService.port,
2730
},
2831
},
2932
]),

backend/auth-service/src/app.service.ts

Lines changed: 32 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import axios, { AxiosResponse } from 'axios';
1717
import { Token, TokenPayload } from './interfaces';
1818
import { AccountProvider } from './constants/account-provider.enum';
1919
import * as nodemailer from 'nodemailer';
20+
import { config } from 'src/configs';
2021

2122
const SALT_ROUNDS = 10;
2223

@@ -30,9 +31,9 @@ export class AppService {
3031
@Inject('USER_SERVICE') private readonly userClient: ClientProxy,
3132
) {
3233
this.oauthClient = new OAuth2Client({
33-
clientId: process.env.GOOGLE_CLIENT_ID,
34-
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
35-
redirectUri: process.env.GOOGLE_CALLBACK_URL,
34+
clientId: config.auth.google.clientId,
35+
clientSecret: config.auth.google.clientSecret,
36+
redirectUri: config.auth.google.callbackUrl,
3637
});
3738
}
3839

@@ -154,7 +155,9 @@ export class AppService {
154155
}
155156
}
156157

157-
public async generateResetPasswordRequest(dto: ResetPasswordRequestDto): Promise<boolean> {
158+
public async generateResetPasswordRequest(
159+
dto: ResetPasswordRequestDto,
160+
): Promise<boolean> {
158161
const user = await firstValueFrom(
159162
this.userClient.send(
160163
{
@@ -171,8 +174,8 @@ export class AppService {
171174
const resetToken = this.jwtService.sign(
172175
{ userId: user._id.toString(), email: dto.email, type: 'reset-password' },
173176
{
174-
secret: process.env.JWT_SECRET,
175-
expiresIn: '1hr',
177+
secret: config.auth.local.jwtSecret,
178+
expiresIn: config.auth.local.jwtTokenExpiration,
176179
},
177180
);
178181

@@ -204,7 +207,7 @@ export class AppService {
204207
public async validatePasswordResetToken(token: string): Promise<any> {
205208
try {
206209
const decoded = this.jwtService.verify(token, {
207-
secret: process.env.JWT_SECRET,
210+
secret: config.auth.local.jwtSecret,
208211
});
209212
const { userId, email, type } = decoded;
210213
if (type !== 'reset-password') {
@@ -223,16 +226,16 @@ export class AppService {
223226
}
224227

225228
private async sendResetEmail(email: string, token: string) {
226-
const resetUrl = `${process.env.FRONTEND_URL}/reset-password?token=${token}`; // To change next time
229+
const resetUrl = `${config.frontendUrl}/reset-password?token=${token}`; // To change next time
227230

228231
const transporter = nodemailer.createTransport({
229232
service: 'gmail',
230233
host: 'smtp.gmail.com',
231234
port: 465,
232235
secure: true,
233236
auth: {
234-
user: process.env.NODEMAILER_GMAIL_USER,
235-
pass: process.env.NODEMAILER_GMAIL_PASSWORD,
237+
user: config.mailer.user,
238+
pass: config.mailer.password,
236239
},
237240
});
238241

@@ -253,7 +256,7 @@ export class AppService {
253256
public async validateAccessToken(accessToken: string): Promise<any> {
254257
try {
255258
const decoded = this.jwtService.verify(accessToken, {
256-
secret: process.env.JWT_SECRET,
259+
secret: config.auth.local.jwtSecret,
257260
});
258261
return decoded;
259262
} catch (error) {
@@ -264,7 +267,7 @@ export class AppService {
264267
public async validateRefreshToken(refreshToken: string): Promise<any> {
265268
try {
266269
const decoded = this.jwtService.verify(refreshToken, {
267-
secret: process.env.JWT_REFRESH_SECRET,
270+
secret: config.auth.local.jwtRefreshSecret,
268271
});
269272
return decoded;
270273
} catch (error) {
@@ -293,13 +296,13 @@ export class AppService {
293296

294297
const [accessToken, refreshToken] = await Promise.all([
295298
this.jwtService.signAsync(
296-
{
297-
sub: id,
298-
...rest,
299-
},
300-
{
301-
secret: process.env.JWT_SECRET,
302-
expiresIn: '1h', // 1 hour
299+
{
300+
sub: id,
301+
...rest,
302+
},
303+
{
304+
secret: config.auth.local.jwtSecret,
305+
expiresIn: config.auth.local.jwtTokenExpiration,
303306
},
304307
),
305308
this.jwtService.signAsync(
@@ -308,8 +311,8 @@ export class AppService {
308311
...rest,
309312
},
310313
{
311-
secret: process.env.JWT_REFRESH_SECRET,
312-
expiresIn: '7d', // 1 week
314+
secret: config.auth.local.jwtRefreshSecret,
315+
expiresIn: config.auth.local.jwtRefreshTokenExpiration,
313316
},
314317
),
315318
]);
@@ -321,8 +324,8 @@ export class AppService {
321324
}
322325

323326
getGoogleOAuthUrl(): string {
324-
const clientId = process.env.GOOGLE_CLIENT_ID;
325-
const redirectUri = process.env.GOOGLE_CALLBACK_URL;
327+
const clientId = config.auth.google.clientId;
328+
const redirectUri = config.auth.google.callbackUrl;
326329
const scope = encodeURIComponent('email profile');
327330
const responseType = 'code';
328331
const state = 'secureRandomState';
@@ -402,7 +405,7 @@ export class AppService {
402405

403406
const ticket = await this.oauthClient.verifyIdToken({
404407
idToken: tokens.id_token,
405-
audience: process.env.GOOGLE_CLIENT_ID,
408+
audience: config.auth.google.clientId,
406409
});
407410

408411
const payload = ticket.getPayload();
@@ -426,8 +429,8 @@ export class AppService {
426429
}
427430

428431
getGithubOAuthUrl(): string {
429-
const clientId = process.env.GITHUB_CLIENT_ID;
430-
const redirectUri = process.env.GITHUB_CALLBACK_URL;
432+
const clientId = config.auth.github.clientId;
433+
const redirectUri = config.auth.github.callbackUrl;
431434
const scope = 'user:email';
432435

433436
const githubLoginUrl = `https://github.com/login/oauth/authorize?client_id=${clientId}&redirect_uri=${encodeURIComponent(
@@ -484,10 +487,10 @@ export class AppService {
484487
private async exchangeGithubCodeForTokens(code: string) {
485488
try {
486489
const params = {
487-
client_id: process.env.GITHUB_CLIENT_ID,
488-
client_secret: process.env.GITHUB_CLIENT_SECRET,
490+
client_id: config.auth.github.clientId,
491+
client_secret: config.auth.github.clientSecret,
489492
code: code,
490-
redirect_uri: process.env.GITHUB_CALLBACK_URL,
493+
redirect_uri: config.auth.github.callbackUrl,
491494
};
492495
const headers = {
493496
Accept: 'application/json',
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import { Transport } from '@nestjs/microservices';
2+
import * as dotenv from 'dotenv';
3+
4+
dotenv.config();
5+
6+
function getEnvVar(name: string): string {
7+
const value = process.env[name];
8+
if (!value) {
9+
throw new Error(`Environment variable ${name} is not defined`);
10+
}
11+
return value;
12+
}
13+
14+
export const config = {
15+
userService: {
16+
port: parseInt(getEnvVar('USER_SERVICE_PORT')),
17+
host: getEnvVar('USER_SERVICE_HOST'),
18+
transport: Transport[getEnvVar('USER_SERVICE_TRANSPORT')] || Transport.TCP,
19+
},
20+
authService: {
21+
port: parseInt(getEnvVar('AUTH_SERVICE_PORT')),
22+
host: getEnvVar('AUTH_SERVICE_HOST'),
23+
transport: Transport[getEnvVar('AUTH_SERVICE_TRANSPORT')] || Transport.TCP,
24+
},
25+
strategies: {
26+
accessTokenStrategy: getEnvVar('ACCESS_TOKEN_STRATEGY'),
27+
refreshTokenStrategy: getEnvVar('REFRESH_TOKEN_STRATEGY'),
28+
googleStrategy: getEnvVar('GOOGLE_STRATEGY'),
29+
githubStrategy: getEnvVar('GITHUB_STRATEGY'),
30+
},
31+
auth: {
32+
local: {
33+
jwtSecret: getEnvVar('JWT_SECRET'),
34+
jwtTokenExpiration: getEnvVar('JWT_TOKEN_EXPIRATION'),
35+
jwtRefreshSecret: getEnvVar('JWT_REFRESH_SECRET'),
36+
jwtRefreshTokenExpiration: getEnvVar('JWT_REFRESH_TOKEN_EXPIRATION'),
37+
},
38+
google: {
39+
clientId: getEnvVar('GOOGLE_CLIENT_ID'),
40+
clientSecret: getEnvVar('GOOGLE_CLIENT_SECRET'),
41+
callbackUrl: getEnvVar('GOOGLE_CALLBACK_URL'),
42+
},
43+
github: {
44+
clientId: getEnvVar('GITHUB_CLIENT_ID'),
45+
clientSecret: getEnvVar('GITHUB_CLIENT_SECRET'),
46+
callbackUrl: getEnvVar('GITHUB_CALLBACK_URL'),
47+
},
48+
},
49+
mailer: {
50+
user: getEnvVar('NODEMAILER_GMAIL_USER'),
51+
password: getEnvVar('NODEMAILER_GMAIL_PASSWORD'),
52+
},
53+
frontendUrl: getEnvVar('FRONTEND_URL'),
54+
};
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { config } from './env.config';

backend/auth-service/src/main.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,24 @@ import { NestFactory } from '@nestjs/core';
22
import { AppModule } from './app.module';
33
import { MicroserviceOptions, Transport } from '@nestjs/microservices';
44
import { ValidationPipe } from '@nestjs/common';
5+
import { config } from 'src/configs';
6+
import * as dotenv from 'dotenv';
7+
8+
dotenv.config();
59

610
async function bootstrap() {
711
const app = await NestFactory.createMicroservice<MicroserviceOptions>(
812
AppModule,
913
{
10-
transport: Transport.TCP,
14+
transport: config.authService.transport,
1115
options: {
12-
host: '0.0.0.0',
13-
port: 3003,
16+
host: config.authService.host,
17+
port: config.authService.port,
1418
},
1519
},
1620
);
1721
app.useGlobalPipes(new ValidationPipe());
1822
await app.listen();
19-
console.log('Auth Service is listening on port 3003');
23+
console.log('Auth Service is listening on port', config.authService.port);
2024
}
2125
bootstrap();

backend/auth-service/src/strategies/access-token.strategy.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,18 @@
11
import { Injectable } from '@nestjs/common';
22
import { PassportStrategy } from '@nestjs/passport';
33
import { Strategy, ExtractJwt } from 'passport-jwt';
4+
import { config } from 'src/configs';
45

56
@Injectable()
6-
export class AccessTokenStrategy extends PassportStrategy(Strategy, 'jwt') {
7+
export class AccessTokenStrategy extends PassportStrategy(
8+
Strategy,
9+
config.strategies.accessTokenStrategy,
10+
) {
711
constructor() {
812
super({
913
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
1014
ignoreExpiration: false,
11-
secretOrKey: process.env.JWT_SECRET,
15+
secretOrKey: config.auth.local.jwtSecret,
1216
});
1317
}
1418

0 commit comments

Comments
 (0)