URL 단축기 만들기 - 14.2 로그인 직접 구현하기
아무래도 fastify + passport + nestjs 조합은 힘들거같아 직접 구현하기로 했어요.
그럼 전에 설치했던 모듈들 싹 지워줄게요.
yarn remove passport passport-discord @nestjs/passport @fastify/session @fastify/cookie
types 패키지는 저기서 알아서 지워주니까 딱히 따로 지울 필요는 없어요.
그다음 passport module과 strategy도 지워줄게요.
discord.strategy.ts를 지우고 PassportModule 임포트도 제거해줬어요.
그리고 메인파일도 원래대로 돌려뒀어요.
import { NestFactory } from '@nestjs/core'
import { ValidationPipe } from '@nestjs/common'
import { AppModule } from './app.module'
import {
NestFastifyApplication,
FastifyAdapter,
} from '@nestjs/platform-fastify'
async function bootstrap() {
const app = await NestFactory.create<NestFastifyApplication>(
AppModule,
new FastifyAdapter(),
)
app.useGlobalPipes(
new ValidationPipe({
whitelist: true,
}),
)
await app.listen(3000, '0.0.0.0')
}
bootstrap()
일단 리다이렉트를 시켜볼게요.
@Get('/login')
async login(@Response() res: FastifyReply, @Query('code') code: string) {
if (!code) {
res.redirect(
302,
`https://discord.com/api/oauth2/authorize?${new URLSearchParams({
client_id: config.auth.discord.clientId,
scope: 'identify',
redirect_uri: config.auth.discord.redirectUri,
response_type: 'code',
})}`,
)
return
}
console.log(code)
}

일단 리다이렉트는 성공했어요. 이제 code를 이용해서 유저정보를 불러와볼게요.
code로부터 유저 정보 가져오기
일단 이 과정을 위해서는 웹 요청을 보내야해요. axios를 설치해 줄게요.
yarn add axios
그리고 디스코드 api를 사용하기 때문에 관련 타입도 설치해 줄게요.
yarn add discord-api-types
디스코드 api용 axios 인스턴스를 만들어 줬어요.
import axios from 'axios'
const discordApi = axios.create({
baseURL: 'https://discord.com/api/v10',
})
이제 code에서 토큰을 가져와볼게요.
const { data: tokens } =
await discordApi.post<RESTPostOAuth2AccessTokenResult>(
Routes.oauth2TokenExchange(),
new URLSearchParams({
client_id: config.auth.discord.clientId,
client_secret: config.auth.discord.clientSecret,
redirect_uri: config.auth.discord.redirectUri,
grant_type: 'authorization_code',
code,
}),
{
headers: {
'content-type': 'application/x-www-form-urlencoded',
},
},
)
const accessToken = tokens.access_token
이 코드는 디스코드 api를 이용해서 oauth2 code로 액세스 토큰을 받아와요. 이제 이 액세스 토큰을 이용해서 유저정보를 불러올 수 있어요.
const { data: discordUser } = await discordApi.get<APIUser>(Routes.user(), {
headers: {
authorization: `Bearer ${accessToken}`,
},
})
이렇게 토큰을 이용해 유저를 가져왔어요.
이제 이 정보에 맞는 계정을 생성하거나 가져와서 토큰으로 변환해줄 거에요.
const user = await this.authService.findOrCreateUser(discordUser.id, discordUser.username)
먼저 유저 가입 처리?를 먼저 해줬어요.
아직 jwt 모듈 세팅을 안해둬서 이제 해볼게요.
JWT 세팅
yarn add @nestjs/jwt
JwtModule.register({
secret: config.auth.secret,
signOptions: {
expiresIn: '7d',
},
}),
그리고 AuthService도 export 해주세요.
그 다음 AuthService에 메서드를 하나 추가해 줄게요.
먼저 constructor에 jwt service를 추가해 줄게요.
constructor(
private usersService: UsersService,
private jwtService: JwtService,
) {}
그 다음 메서드를 추가해 줬어요.
async createToken(user: User): Promise<string> {
return this.jwtService.signAsync({
id: user.id,
})
}
일단 서비스 세팅은 끝났...을 거에요. 아마도...
토큰 응답 보내기
이제 토큰을 생성해 줄거에요.
const token = await this.authService.createToken(user)
이제 토큰을 만들었으니 응답을 보내볼 차례에요. 리다이렉트를 시켜줄게요.
res.redirect(302, '/#/auth/callback?token=' + token)
이제 이러면 리다이렉트가...되겠죠?

다음 글에서 이 토큰을 사용해서 요청을 처리하는 시스템을 구축해 볼거에요.
다음이 언제일지는 모르겠지만...