Skip to content

Commit

Permalink
Feature/#55 - 서버는 쿠키를 클라이언트에 전달한다. (#154)
Browse files Browse the repository at this point in the history
  • Loading branch information
xjfcnfw3 authored Nov 13, 2024
2 parents 53e7fc2 + 15b328a commit 91fed6d
Show file tree
Hide file tree
Showing 12 changed files with 139 additions and 16 deletions.
2 changes: 2 additions & 0 deletions packages/backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
"class-transformer": "^0.5.1",
"class-validator": "^0.14.1",
"dotenv": "^16.4.5",
"express-session": "^1.18.1",
"mysql2": "^3.11.4",
"nest-winston": "^1.9.7",
"passport": "^0.7.0",
Expand All @@ -47,6 +48,7 @@
"@nestjs/schematics": "^10.0.0",
"@nestjs/testing": "^10.0.0",
"@types/express": "^5.0.0",
"@types/express-session": "^1.18.0",
"@types/jest": "^29.5.2",
"@types/node": "^20.3.1",
"@types/passport-google-oauth20": "^2.0.16",
Expand Down
13 changes: 10 additions & 3 deletions packages/backend/src/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,24 @@ import { TypeOrmModule } from '@nestjs/typeorm';
import { WinstonModule } from 'nest-winston';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { AuthModule } from '@/auth/auth.module';
import { logger } from '@/configs/logger.config';
import { typeormConfig } from '@/configs/typeorm.config';
import {
typeormDevelopConfig,
typeormProductConfig,
} from '@/configs/devTypeormConfig';
import { StockModule } from '@/stock/stock.module';
import { UserModule } from '@/user/user.module';
import { AuthModule } from '@/auth/auth.module';

@Module({
imports: [
StockModule,
UserModule,
TypeOrmModule.forRoot(typeormConfig),
TypeOrmModule.forRoot(
process.env.NODE_ENV === 'production'
? typeormProductConfig
: typeormDevelopConfig,
),
WinstonModule.forRoot(logger),
AuthModule,
],
Expand Down
5 changes: 3 additions & 2 deletions packages/backend/src/auth/auth.module.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { Module } from '@nestjs/common';
import { GoogleStrategy } from '@/auth/google.strategy';
import { GoogleAuthController } from '@/auth/googleAuth.controller';
import { GoogleAuthService } from '@/auth/googleAuth.service';
import { GoogleStrategy } from '@/auth/passport/google.strategy';
import { SessionSerializer } from '@/auth/passport/session.serializer';
import { UserModule } from '@/user/user.module';

@Module({
imports: [UserModule],
controllers: [GoogleAuthController],
providers: [GoogleStrategy, GoogleAuthService],
providers: [GoogleStrategy, GoogleAuthService, SessionSerializer],
})
export class AuthModule {}
22 changes: 20 additions & 2 deletions packages/backend/src/auth/googleAuth.controller.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { Controller, Get, Req, UseGuards } from '@nestjs/common';
import { ApiOperation, ApiTags } from '@nestjs/swagger';
import { ApiOkResponse, ApiOperation, ApiTags } from '@nestjs/swagger';
import { Request } from 'express';
import { GoogleAuthGuard } from '@/auth/guard/google.guard';
import { User } from '@/user/domain/user.entity';

@ApiTags('Auth')
@Controller('auth/google')
Expand All @@ -21,6 +22,23 @@ export class GoogleAuthController {
@Get('/redirect')
@UseGuards(GoogleAuthGuard)
async handleRedirect(@Req() request: Request) {
return request.user;
const user = request.user as User;
return { nickname: user.nickname, email: user.email };
}

@ApiOperation({
summary: '로그인 상태 확인',
description: '로그인 상태를 확인합니다.',
})
@ApiOkResponse({
description: '로그인된 상태',
example: { message: 'Authenticated' },
})
@Get('/status')
async user(@Req() request: Request) {
if (request.user) {
return { message: 'Authenticated' };
}
return { message: 'Not Authenticated' };
}
}
2 changes: 1 addition & 1 deletion packages/backend/src/auth/googleAuth.service.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { OauthUserInfo } from '@/auth/google.strategy';
import { GoogleAuthService } from '@/auth/googleAuth.service';
import { OauthUserInfo } from '@/auth/passport/google.strategy';
import { OauthType } from '@/user/domain/ouathType';
import { Role } from '@/user/domain/role';
import { User } from '@/user/domain/user.entity';
Expand Down
2 changes: 1 addition & 1 deletion packages/backend/src/auth/googleAuth.service.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Injectable, UnauthorizedException } from '@nestjs/common';
import { OauthUserInfo } from '@/auth/google.strategy';
import { OauthUserInfo } from '@/auth/passport/google.strategy';
import { UserService } from '@/user/user.service';

@Injectable()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,6 @@ export class GoogleStrategy extends PassportStrategy(Strategy) {
familyName: name?.familyName,
};
const user = await this.googleAuthService.attemptAuthentication(userInfo);
done(null, false);
done(null, user);
}
}
24 changes: 24 additions & 0 deletions packages/backend/src/auth/passport/session.serializer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { Injectable } from '@nestjs/common';
import { PassportSerializer } from '@nestjs/passport';
import { User } from '@/user/domain/user.entity';

@Injectable()
export class SessionSerializer extends PassportSerializer {
constructor() {
super();
}

async serializeUser(
user: User,
done: (err: Error | null, user: User) => void,
) {
done(null, user);
}

async deserializeUser(
user: User,
done: (err: Error | null, user: User | null) => void,
): Promise<void> {
return user ? done(null, user) : done(null, null);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,23 @@ import * as dotenv from 'dotenv';

dotenv.config();

export const typeormConfig: TypeOrmModuleOptions = {
export const typeormProductConfig: TypeOrmModuleOptions = {
type: 'mysql',
host: process.env.DB_HOST,
port: Number(process.env.DB_PORT),
username: process.env.DB_USER,
password: process.env.DB_PASS,
database: process.env.DB_NAME,
entities: [__dirname + '/../**/*.entity.{js,ts}'],
logging: true,
};

export const typeormDevelopConfig: TypeOrmModuleOptions = {
type: 'mysql',
host: process.env.DB_HOST,
port: Number(process.env.DB_PORT),
username: process.env.DB_USER,
password: process.env.DB_PASS,
database: process.env.DB_NAME,
entities: [__dirname + '/../**/*.entity.{js,ts}'],
logging: true,
};
13 changes: 13 additions & 0 deletions packages/backend/src/configs/session.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { randomUUID } from 'node:crypto';
import * as dotenv from 'dotenv';

dotenv.config();

export const sessionConfig = {
secret: process.env.COOKIE_SECRET || randomUUID().toString(),
resave: false,
saveUninitialized: false,
cookie: {
maxAge: Number(process.env.COOKIE_MAX_AGE),
},
};
9 changes: 7 additions & 2 deletions packages/backend/src/main.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
import { ValidationPipe } from '@nestjs/common';
import { NestFactory } from '@nestjs/core';
import * as session from 'express-session';
import * as passport from 'passport';
import { AppModule } from './app.module';
import { sessionConfig } from '@/configs/session.config';
import { useSwagger } from '@/configs/swagger.config';

async function bootstrap() {
const app = await NestFactory.create(AppModule);

app.use(session(sessionConfig));
app.useGlobalPipes(new ValidationPipe({ transform: true }));
useSwagger(app);

app.use(passport.initialize());
app.use(passport.session());
await app.listen(process.env.PORT ?? 3000);
}

bootstrap();
47 changes: 45 additions & 2 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1460,6 +1460,13 @@
"@types/range-parser" "*"
"@types/send" "*"

"@types/express-session@^1.18.0":
version "1.18.0"
resolved "https://registry.yarnpkg.com/@types/express-session/-/express-session-1.18.0.tgz#7c6f25c3604b28d6bc08a2e3929997bbc7672fa2"
integrity sha512-27JdDRgor6PoYlURY+Y5kCakqp5ulC0kmf7y+QwaY+hv9jEFuQOThgkjyA53RP3jmKuBsH5GR6qEfFmvb8mwOA==
dependencies:
"@types/express" "*"

"@types/express@*", "@types/express@^5.0.0":
version "5.0.0"
resolved "https://registry.yarnpkg.com/@types/express/-/express-5.0.0.tgz#13a7d1f75295e90d19ed6e74cab3678488eaa96c"
Expand Down Expand Up @@ -2792,12 +2799,17 @@ [email protected]:
resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c"
integrity sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==

[email protected]:
version "1.0.7"
resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.7.tgz#ab5dd7ab757c54e60f37ef6550f481c426d10454"
integrity sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==

[email protected]:
version "0.7.1"
resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.7.1.tgz#2f73c42142d5d5cf71310a74fc4ae61670e5dbc9"
integrity sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==

cookie@~0.7.2:
cookie@0.7.2, cookie@~0.7.2:
version "0.7.2"
resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.7.2.tgz#556369c472a2ba910f2979891b526b3436237ed7"
integrity sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==
Expand Down Expand Up @@ -3023,7 +3035,7 @@ denque@^2.1.0:
resolved "https://registry.yarnpkg.com/denque/-/denque-2.1.0.tgz#e93e1a6569fb5e66f16a3c2a2964617d349d6ab1"
integrity sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==

[email protected]:
[email protected], depd@~2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df"
integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==
Expand Down Expand Up @@ -3638,6 +3650,20 @@ expect@^29.0.0, expect@^29.7.0:
jest-message-util "^29.7.0"
jest-util "^29.7.0"

express-session@^1.18.1:
version "1.18.1"
resolved "https://registry.yarnpkg.com/express-session/-/express-session-1.18.1.tgz#88d0bbd41878882840f24ec6227493fcb167e8d5"
integrity sha512-a5mtTqEaZvBCL9A9aqkrtfz+3SMDhOVUnjafjo+s7A9Txkq+SVX2DLvSp1Zrv4uCXa3lMSK3viWnh9Gg07PBUA==
dependencies:
cookie "0.7.2"
cookie-signature "1.0.7"
debug "2.6.9"
depd "~2.0.0"
on-headers "~1.0.2"
parseurl "~1.3.3"
safe-buffer "5.2.1"
uid-safe "~2.1.5"

[email protected]:
version "4.21.1"
resolved "https://registry.yarnpkg.com/express/-/express-4.21.1.tgz#9dae5dda832f16b4eec941a4e44aa89ec481b281"
Expand Down Expand Up @@ -5774,6 +5800,11 @@ [email protected]:
dependencies:
ee-first "1.1.1"

on-headers@~1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.2.tgz#772b0ae6aaa525c399e489adfad90c403eb3c28f"
integrity sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==

once@^1.3.0, once@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
Expand Down Expand Up @@ -6184,6 +6215,11 @@ queue-microtask@^1.2.2:
resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243"
integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==

random-bytes@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/random-bytes/-/random-bytes-1.0.0.tgz#4f68a1dc0ae58bd3fb95848c30324db75d64360b"
integrity sha512-iv7LhNVO047HzYR3InF6pUcUsPQiHTM1Qal51DcGSuZFBil1aBBWG5eHPNek7bvILMaYJ/8RU1e8w1AMdHmLQQ==

randombytes@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a"
Expand Down Expand Up @@ -7317,6 +7353,13 @@ typescript@^5.1.3, typescript@^5.6.3, typescript@~5.6.2:
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.6.3.tgz#5f3449e31c9d94febb17de03cc081dd56d81db5b"
integrity sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==

uid-safe@~2.1.5:
version "2.1.5"
resolved "https://registry.yarnpkg.com/uid-safe/-/uid-safe-2.1.5.tgz#2b3d5c7240e8fc2e58f8aa269e5ee49c0857bd3a"
integrity sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==
dependencies:
random-bytes "~1.0.0"

[email protected]:
version "0.0.4"
resolved "https://registry.yarnpkg.com/uid2/-/uid2-0.0.4.tgz#033f3b1d5d32505f5ce5f888b9f3b667123c0a44"
Expand Down

0 comments on commit 91fed6d

Please sign in to comment.