토큰 재발급 API 실습 중 restoreAccessToken 401 에러
강사님 안녕하세요?
토큰 재발급 API 실습 중에 해결되지 않는 부분이 있어 질문드려요.
관련 코드는 강의에서 진행하는 대로 모두 작성하였고, 마지막 실습 부분에서 막힙니다.
login 과

fetchUser 까지는 진행이 잘 되는데


문제는,
restoreAccessToken 부분에서 401 에러가 발생합니다.

관련 에러 명령 프롬프트 화면입니다. 
관련 쿠키 값 입니다.

(login 시도 시 쿠키 값)

코드는 실습대로 다 작성했구요.
실습도 그대로 따라하는 중 restoreAccessToken 부분만 에러가 나네요.
auth.resolver.ts 의 @UseGuards 데코레이터를 빼보기도 하고, 제 나름대로 해결책을 찾아보려 했는데 잘 모르겠네요. 구글링 해봐도 안되고,
혹시 제가 빼먹은 부분이나 잘못한 부분이 있을까요?
도움 부탁드립니다 :)
아래는 관련 제 코드들 입니다.
auth.module.ts
import { Module } from '@nestjs/common';
import { AuthResolver } from './auth.resolver';
import { AuthService } from './auth.service';
import { JwtModule } from '@nestjs/jwt';
import { UserService } from '../users/user.service';
import { TypeOrmModule } from '@nestjs/typeorm';
import { User } from '../users/entities/user.entity';
import { JwtRefreshStrategy } from 'src/commons/auth/jwt-refresh.strategy';
@Module({
imports: [
JwtModule.register({}), //
TypeOrmModule.forFeature([User]),
],
providers: [
JwtRefreshStrategy, //
AuthResolver,
AuthService,
UserService,
],
})
export class AuthModule {}
auth.resolver.ts
import { UnprocessableEntityException, UseGuards } from '@nestjs/common';
import { Args, Context, Mutation, Resolver } from '@nestjs/graphql';
import { UserService } from '../users/user.service';
import * as bcrypt from 'bcrypt';
import { AuthService } from './auth.service';
import { GqlAuthRefreshGuard } from 'src/commons/auth/gql-auth.guard';
import { CurrentUser } from 'src/commons/auth/gql-user.param';
@Resolver()
export class AuthResolver {
constructor(
private readonly userService: UserService, //
private readonly authService: AuthService,
) {}
@Mutation(() => String)
async login(
@Args('email') email: string, //
@Args('password') password: string,
@Context() context: any,
) {
// 1. 로그인(이메일이 일치하는 유저를 DB에서 찾기)
const user = await this.userService.findOne({ email });
// 2. 일치하는 이메일이 없으면 -> 에러 던지기!!
if (!user) throw new UnprocessableEntityException('이메일이 없습니다.');
// 3. 일치하는 이메일이 있지만, 비밀번호가 틀렸다면 -> 에러 던지기!!
const isAuth = await bcrypt.compare(password, user.password);
if (!isAuth) throw new UnprocessableEntityException('암호가 틀렸습니다.');
// 4. refreshToken(=JWT)을 만들어서 프론트엔드(쿠키)에 보내주기
this.authService.setRefreshToken({ user, res: context.res });
// 5. 이메일과 비밀번호 모두 일치한다면 -> accessToken(=JWT)을 만들어서 브라우저에 전달하기
return this.authService.getAccessToken({ user });
}
@UseGuards(GqlAuthRefreshGuard)
@Mutation(() => String)
restoreAccessToken(
@CurrentUser() currentUser: any, //
) {
return this.authService.getAccessToken({ user: currentUser });
}
}
auth.service.ts
import { Injectable } from '@nestjs/common';
import { JwtService } from '@nestjs/jwt';
@Injectable()
export class AuthService {
constructor(
private readonly jwtService: JwtService, //
) {}
setRefreshToken({ user, res }) {
const refreshToken = this.jwtService.sign(
{ email: user.email, sub: user.id },
{ secret: 'myRefreshKey', expiresIn: '2w' },
);
// 개발 환경
res.setHeader('Set-Cookie', `refreshToken=${refreshToken}`);
// 배포 환경
// res.setHeader('Access-Control-Allow-Origin', 'https://myfrontsite.com')
// res.setHeader(
// 'Set-Cookie',
// `refreshToken=${refreshToken}; path=/; domain=.mybacksite.com; SameSite=None; Secure; httpOnly;`
// )
}
getAccessToken({ user }) {
return this.jwtService.sign(
{ email: user.email, sub: user.id },
{ secret: 'myAccessKey', expiresIn: '30s' },
);
}
}
jwt-refresh.strategy.ts
import { PassportStrategy } from '@nestjs/passport';
import { Strategy } from 'passport-jwt';
export class JwtRefreshStrategy extends PassportStrategy(Strategy, 'refresh') {
constructor() {
super({
jwtFromRequest: (req) => {
const cookie = req.headers.cookie;
const refreshToken = cookie.replace('refreshToken=', '');
return refreshToken;
},
secretOrKey: 'myRefreshKey',
});
}
validate(payload) {
console.log(payload); // { email: c@c.com, sub: qkwefuasdij-012093sd }
return {
email: payload.email,
id: payload.sub,
};
}
}
gql-auth-guard.ts
import { ExecutionContext } from '@nestjs/common';
import { GqlExecutionContext } from '@nestjs/graphql';
import { AuthGuard } from '@nestjs/passport';
export class GqlAuthAccessGuard extends AuthGuard('access') {
getRequest(context: ExecutionContext) {
const ctx = GqlExecutionContext.create(context);
return ctx.getContext().req;
}
}
export class GqlAuthRefreshGuard extends AuthGuard('refresh') {
getRequest(context: ExecutionContext) {
const ctx = GqlExecutionContext.create(context);
return ctx.getContext().req;
}
}
app.module.ts
import { ApolloDriver, ApolloDriverConfig } from '@nestjs/apollo';
import { Module } from '@nestjs/common';
import { GraphQLModule } from '@nestjs/graphql';
import { TypeOrmModule } from '@nestjs/typeorm';
import { AuthModule } from './apis/auth/auth.module';
import { BoardModule } from './apis/boards/boards.module';
import { ProductModule } from './apis/products/product.module';
import { ProductCategoryModule } from './apis/productCategory/productCategory.module';
import { UserModule } from './apis/users/user.module';
// import { AppController } from './app.controller';
// import { AppService } from './app.service';
@Module({
imports: [
AuthModule,
BoardModule,
ProductModule,
ProductCategoryModule,
UserModule,
GraphQLModule.forRoot<ApolloDriverConfig>({
driver: ApolloDriver,
autoSchemaFile: 'src/commons/graphql/schema.gql',
context: ({ req, res }) => ({ req, res }),
}),
TypeOrmModule.forRoot({
type: 'mysql', // 데이터 베이스 타입
host: 'localhost', // local 환경으로 진행
port: 3306, // mysql은 기본 port는 3306
username: 'root', // mysql은 기본 user는 root로 지정
password: 'bada332@', // 본인의 mysql password
database: 'myproject03', // 연결할 데이터 베이스명
entities: [__dirname + '/apis/**/*.entity.*'], // 데이터 베이스와 연결할 entity
synchronize: true, // entity 테이블을 데이터베이스와 동기화할 것인지
logging: true, // 콘솔 창에 log를 표시할 것인지
}),
],
// controllers: [AppController],
// providers: [AppService],
})
export class AppModule {}
Câu trả lời 1
그래프 ql 문서 사용할때 느낌표 남는거 어떻게 없애나요?
0
86
2
강의 전체 소스 코드를 받고싶습니다.
0
77
2
fontawesome 사용 문의
0
81
2
소스 코드 부탁드립니다~
0
87
2
깃 레포지터리 소스
0
87
2
커리큘럼12.css 정렬 에 나오는 과제 정답알고싶어요
0
74
2
10-01 Entity TypeOrmModule.forRoot 에 entities
0
89
3
강의 버전관련 문의입니다
0
104
2
Ubuntu 설치 관련
0
62
1
schema.gql 질문 드립니다.
0
51
1
서버 재실행시 Many to Many
0
102
3
input 관련 문의
0
90
2
Rest API 보다는 graphql이 주된 내용인데
0
134
2
강의 전체 소스코드 받을수있을까요?
0
156
1
도커볼륨 마운트 관련
0
127
2
findOne 타입스크립트오류
0
109
1
http => htrtps 호출 인증서 신뢰 오류
0
356
1
self-signed certificate in certificate chain 에러 발생
0
421
1
mongoose 설치 오류
0
143
1
특정 API, 특정 IP 허용 (단일경로에 CORS 활성화)
0
285
2
08-06
0
180
3
구조랑 패턴 관련해서 질문
0
126
2
mydocker
0
129
2
coolsms statuscode 2000 인데 전송안돼는 경우 확인.
0
156
1

