[수정] member.module와 auth.module 서로 각각의 service를 providers 한 다면 종속성 오류가 난다.
아래 사이트 내용을 봐야 할거 같다.
ichi.pro/ko/nestjs-tamsaeg-nestui-modyul-siseutem-150387603343728
jwt 하다가 환경변수 부분으로 샛길로 빠졌었다. 다시 돌아와서 ....
auth.module
import { Module } from '@nestjs/common';
import { AuthService } from './auth.service';
import { MemberModule } from '../member.module';
import { PassportModule } from '@nestjs/passport';
import { LocalStrategy } from './strategies/local.strategy';
import { JwtStrategy } from './strategies/jwt.strategy';
import { JwtModule } from '@nestjs/jwt';
@Module({
imports: [
MemberModule,
PassportModule,
JwtModule.register({
secret: process.env.JWT_SECRETKEY, // env에 추가 필요 JWT_SECRETKEY: 아무거나
signOptions: { expiresIn: '60s' }, //토큰의 만료시간 60초
}),
],
controllers: [],
providers: [AuthService, LocalStrategy, JwtStrategy],
exports: [AuthService],
})
export class AuthModule {}
JwtModule을 사용하게 구성한다. register에 구성 개체를 전달.
secret 값은 env 환경변수에서 가져오는것으로 변경 ( 공식 문서에서는 ts 파일에 클레스를 만들었지만 그럴경우 secret 값이 노출 되어 진다. 위험)
signOptions는 많은 항목이 있지만 우선 expiresIn의 값을 설정 한다. 토큰의 만료 시간으로
현재는 60초를 하였다. 나중에 테스트 후 정상 확인을 하면 값을 변경할 필요가 있다 더 길게~
구성옵션은 아래 참고
github.com/auth0/node-jsonwebtoken#usage
아래 코드는 공식문서와는 다르지만 결론은 authService에 login클래스에 아이디를 전달해서
로그인을 하고 생성된 토큰을 받아와서 반환 해 주는 것
@UseGuards(LocalAuthGuard)
@Post('/login')
async login(@Body() logins: LoginMemberDto): Promise<Response> {
const tokens = this.authService.login(logins.LOGIN_ID);
return new ResponseMessage().success().body(tokens).build();
}
이다음은 API의 엔드포인트에 접근 했을 경우 jwt를 요구하여 유효한지 확인하는
jwt.strategy 생성
import { ExtractJwt, Strategy } from 'passport-jwt';
import { PassportStrategy } from '@nestjs/passport';
import { Injectable } from '@nestjs/common';
@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
constructor() {
super({
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
ignoreExpiration: false,
secretOrKey: process.env.JWT_SECRETKEY,
});
}
async validate(payload: any) {
return { userId: payload.sub, username: payload.username };
}
}
super 호출 시 초기화 옵션은 아래 확인
github.com/mikenicholson/passport-jwt#configure-strategy
github.com/mikenicholson/passport-jwt#extracting-the-jwt-from-the-request
jwtFromRequest:에서 JWT를 추출하는 방법을 제공합니다 Request. API 요청의 Authorization 헤더에 전달자 토큰을 제공하는 표준 접근 방식을 사용합니다.
ignoreExpiration: 명시 적으로 false말하자면 JWT가 Passport 모듈에 만료되지 않았는지 확인하는 책임을 위임 하는 기본 설정 을 선택합니다 . 즉, 만료 된 JWT와 함께 경로가 제공되면 요청이 거부되고 401 Unauthorized응답이 전송됩니다. Passport는이를 자동으로 처리합니다.
이 validate()방법은 논의 할 가치가 있습니다. jwt-strategy의 경우 Passport는 먼저 JWT의 서명을 확인하고 JSON을 디코딩합니다. 그런 다음 validate()디코딩 된 JSON을 단일 매개 변수로 전달하는 메서드 를 호출합니다 . JWT 서명이 작동하는 방식에 따라 이전에 서명하여 유효한 사용자에게 발행 한 유효한 토큰 을 받고 있음을 보장합니다 .
생성된 jwt.strategy를 auth.module에 providers에 추가를 합니다.
JWT에 서명 할 때 사용한 것과 동일한 비밀을 가져옴 으로써 Passport에서 수행 한 확인 단계와 AuthService에서 수행 한 서명 단계가 공통 비밀을 사용 하는지 확인 합니다.
마지막으로 JwtAuthGuard내장을 확장하는 클래스를 정의합니다 AuthGuard.
jwt-auth.guard 생성
import { Injectable } from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';
@Injectable()
export class JwtAuthGuard extends AuthGuard('jwt') {}
보호 경로 및 JWT 전략 가드 구현
이제 보호 된 경로와 관련 가드를 구현할 수 있습니다.
app.controller.ts파일을 열고 아래와 같이 업데이트합니다.
@UseGuards(LocalAuthGuard)
@Post('/login')
async login(@Body() logins: LoginMemberDto): Promise<Response> {
const tokens = this.authService.login(logins.LOGIN_ID);
return new ResponseMessage().success().body(tokens).build();
}
@UseGuards(JwtAuthGuard)
@Post()
async addMember(@Body() register: CreateMemberDto): Promise<Response> {
try {
login을 하고 Post할경우 성공 60초가 지나면 401 에러가 난다.
guard 확장
import {
ExecutionContext,
Injectable,
UnauthorizedException,
} from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';
@Injectable()
export class JwtAuthGuard extends AuthGuard('jwt') {
canActivate(context: ExecutionContext) {
// Add your custom authentication logic here
// for example, call super.logIn(request) to establish a session.
return super.canActivate(context);
}
handleRequest(err, user, info) {
// You can throw an exception based on either "info" or "err" arguments
if (err || !user) {
throw err || new UnauthorizedException();
}
return user;
}
}
이부분은 구현하지 않았으니 다음에 필요시에 찾아 보자
docs.nestjs.com/security/authentication#extending-guards
git에 해당 내용을 작업을 하였으며
퇴근 후 pull을 한 뒤에 오류나는 부분을 수정을 하자.
끝
여기까지 작성된 내용은 수정을 하지 않고 git은 몇부분 수정을 함
github.com/dittyBox/study-nestjs
이전글
'Learning > NestJS' 카테고리의 다른 글
INSOMNIA 사용하여 Header에 token 사용 (1) | 2021.01.12 |
---|---|
NestJS Authentication(3) 환경변수 (0) | 2021.01.07 |
NestJS Authentication(2) jwt+환경변수 (0) | 2021.01.06 |
NestJS Authentication(1) Login (0) | 2021.01.03 |
DTO (Data Transfer Object) (0) | 2021.01.02 |