인증 자체는 JwtStrategy 클래스를 작성하고,
컨트롤러 메서드에 @UseGuard(AuthGuard("jwt"))
를 붙이면 완성이다.
그러나 이번 포스팅에서는 NestJS의 인증과 Spring Security의 인증에 대해서 좀 더 자세히 살펴볼 것이다.
- NestJS에서 인증된 사용자 정보는 어디에 저장되는가?
- 그 정보를 어떻게 사용할 수 있는가?
바쁘신 분들은 맨 아래 요약만 보시면 됩니다 😆
JwtStrategy의 validate 메소드에 토큰 인증 로직을 작성한다.
코드는 따로 옮겨적지 않을 것이다.
헤더에서 JWT 추출 후 디코딩은 JwtStrategy 클래스가 알아서 해주고,
토큰 만료 여부와 DB에 해당회원의 존재를 검사한 뒤,
user 객체를 리턴한다.
그럼 로그인 이후 인증은 끝이다.
그런데 리턴한 user 값은 어디에 있을까?
// 정상 토큰이면 해당 토큰으로 Authentication을 가져와서 SecurityContext에 저장
if (accessToken.validate()) {
Authentication authentication = tokenProvider.getAuthentication(accessToken);
SecurityContextHolder.getContext().setAuthentication(authentication);
}
자바의 경우 Authentication 타입 객체를 만들어 Security Context에 저장한다.
결론부터 말하자면 Passport는
JWT 토큰으로 사용자를 인증하고, 인증된 사용자 정보를 '요청 객체'에 저장한다❗️
Spring Boot를 사용해서 애플리케이션을 만들 때,
인증된 사용자 정보가 필요하다면 @AuthenticationPrincipal을 사용하기만 하면 된다.
만약 NestJS에서 @AuthenticationPrincipal(과 같은 것)을 쓰고 싶다면?
구현해야 한다 ⭐️
나의 경우 AuthUser라는 데코레이터를 만들었다.
import { createParamDecorator, ExecutionContext } from "@nestjs/common";
const AuthUser = createParamDecorator(
(data: unknown, context: ExecutionContext) => {
const request = context.switchToHttp().getRequest();
return request.user;
}
)
export default AuthUser
간단히 request에서 유저 정보를 꺼내오는 역할이다.
사용법은 @AuthenticationPrincipal과 같다.
@Get()
@UseGuards(AuthGuard("jwt"))
getAllByUserId(@AuthUser() user): Promise<ChatRoomListDto[]> {
return this.chatService.getAllByUserId(user);
}
참고로 둘은 실행 시점도 다르다.
Spring Security가 DispatcherServlet보다 먼저 실행된다면,
Passport는 ApplicationInstance 이후, (대충 DispatcherServlet이랑 비슷한 놈이다) 컨트롤러 이전에 동작한다.
Spring의 Interceptor와 같은 시점에 동작한다고 보면 된다.
구분 | Spring Security | Passport |
---|---|---|
동작 시점 | DispatcherServlet 이전 | Application Instance 이후, Controller 이전 Spring Interceptor와 같은 시점 |
사용자 정보 저장 | Security Context에 저장 | Request 객체에 저장 |
사용자 정보 사용하기 | 구현된 어노테이션, 사용자 객체 있음 | 없음. 만들어야함 |