티스토리 뷰
기술 스택 : GraphQL, mongoDB, mongoose
1. directive.ts
class AuthDirective extends SchemaDirectiveVisitor {
1) 해당 페이지에서 요구되는 타입 확인 (requires)
2) 해당 페이지에서 요구되는 타입(User)의 토큰을 가져온다. (userToken)
1-1) 토큰이 없으면 인증 x
3) 토큰을 복호화한 후 사용자를 조회 (인증)
2-1) 조회 결과 없으면 인증 x
4) 인증이 되면, 인증 성공
2. app.ts
const apolloServer = new ApolloServer({
schemaDirectives: {
auth: AuthDirective
}
})
3. schema.ts
directive @auth(requires: USER!) on FIELD_DEFINITION
- @auth로 사용가능
4. front에서 라우팅 처리
- 인증을 두번 해야하는 경우
// ex)
type Query {
users: String
isAuthorizedUser: Boolean
@hasRole(roles: [THIS_ADMIN, THIS_SUPER_ADMIN] @auth(requires: USER)
// auth가 먼저 실행되고 hasRole이 실행됨 -> 오른쪽부터 왼쪽으로
}
5. 적용 결과
import { SchemaDirectiveVisitor } from 'apollo-server-express';
import { defaultFieldResolver } from 'graphql';
import jwt from 'jsonwebtoken';
import Config from '../../config';
class AuthDirective extends SchemaDirectiveVisitor {
visitFieldDefinition(field) {
const requiredRole = this.args.requires;
const { resolve = defaultFieldResolver } = field;
// resolve: isAuthorizedUser
field.resolve = async (...args) => {
try {
const { req, res, dataSources } = args[2]; // context
const [token, type] = [req.signedCookies.userToken, 'User'];
if (!token) throw new Error('Unauthorized access'); // 인증 실패 시 처리 -> catch (err)
const decoded = jwt.verify(token, Config.JWT_SECRET);
const model = dataSources.model(type);
const result = await model.findOne({ _id: decoded.id });
if (result) return resolve.apply(this, args);
else {
throw new Error('You must be the authenticated');
}
} catch (err) {
// 인증 실패 시 로직
}
};
}
}
export default AuthDirective;
'Web' 카테고리의 다른 글
CRA 없이 React 개발 환경 구축하기 (0) | 2021.03.01 |
---|---|
AWS 도메인 연결하기 (Route 53, 호스팅케이알, EC2, 포트 리다이렉트) (0) | 2021.01.17 |
AWS EC2로 Node.js 배포하기 (Ubuntu, GitHub, PM2) (1) | 2021.01.17 |
RESTful API (0) | 2020.09.30 |