728x90
server.js
require("dotenv").config();
import logger from "morgan"; // 필요한지 잘 모르겠지만
import "./passport";
import passport from "passport";
// import { ApolloServer } from "apollo-server-express"; // 이걸로 하면 request context에 제대로 안날아옴
import { GraphQLServer } from "graphql-yoga";
import schema from "./schema";
import { authenticateJwt } from "./passport";
import express from "express";
import { isAuthenticated } from "./utils";
const PORT = process.env.PORT || 4000;
const server = new GraphQLServer({
schema,
context: ({ request }) => ({ request, isAuthenticated })
});
// 이렇게 하면 context에 request가 안날아옴
// const app = express();
// server.applyMiddleware({ app });
// app.listen({ port: PORT }, () => {
// console.log(`🚀 Server ready at http://localhost:4000${server.graphqlPath}`);
// });
// app.use(logger("dev"));
// app.use(authenticateJwt);
// express 서버에 접근. logger 미들웨어를 사용하도록 할거야. 사실은 모건 모듈이지.
server.express.use(logger("dev"));
server.express.use(authenticateJwt);
server.start({ port: PORT }, () => {
console.log(`🚀 Server running on http://localhost:${PORT}`);
}); // port: dotenv config에서 포트 읽어오도록 할 수 있어
passport.js
import { ExtractJwt, Strategy } from "passport-jwt";
import passport from "passport";
import { prisma } from "../generated/prisma-client";
require("dotenv").config();
const jwtOpts = {
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(), // Authorization 헤더에서 jwt 찾는 역할
secretOrKey: process.env.JWT_SECRET
};
// 토큰을 암호화하기 위한 문자열 = secret
// { id: 1 } 이런 사용자 정보가 암호화되어서 토큰에 담겨. JWT는 토큰을 입력받아서 정보 해석하고 해석된 정보를 콜백함수로 전달해줘.
// verifyUser 함수 만들자.
// 확인용 callback 함수도 추가. 옵션이 잘 맞게 적용되었을 때 JwtStrategy 함수가 토큰을 해석할거야.
// 우리가 사용자 찾았을 때 호출하는 함수야.
// user를 payload의 정보로 찾을 수 있어야 해.
const verifyUser = async (payload, done) => {
try {
const user = await prisma.user({ id: payload.id });
if (user !== null) {
return done(null, user);
} else {
return done(null, false);
// or create a new account. 토큰에 id가 있고 사용자가 없다면 계정을 생성해도 되지!
}
} catch (error) {
return done(error, false);
}
};
export const authenticateJwt = (req, res, next) =>
passport.authenticate("jwt", { session: false }, (error, user) => {
console.log("🧣", user);
if (user) {
req.user = user;
}
next();
// express에서는 미들웨어를 지나서 라우트가 실행돼. 토큰을 받아서 해석,사용자찾고 사용자 존재하면 req객체에 사용자 추가하고 나면 graphql 함수를 실행하는거야.
// 로그인 되어 있다면 모든 gql 요청에 사용자 정보가 추가되어서 요청되는거지.
})(req, res, next); // 함수가 리턴되는거야. Fn(req, res, next) 인거야. 이경우에는 실행해야 하는 함수가 gql 함수래. (?)
passport.use(new Strategy(jwtOpts, verifyUser));
passport.initialize();
.env // 이건 어디서 왔지?
JWT_SECRET="hjPedyU7yOHWm07BbP0ubJXzEt6XnGZW"
utils.js
require("dotenv").config();
import jwt from "jsonwebtoken";
export const generateToken = id => jwt.sign({ id }, process.env.JWT_SECRET);
export const isAuthenticated = request => {
console.log("1");
console.log("7");
console.log("7", !request.user);
if (!request.user) {
console.log("21");
throw Error("You need to log in to perform this action");
}
};
generatedToken은 회원가입 할 때 넣으면 되겠지.
getUser.js
import { prisma } from "../../../../generated/prisma-client";
export default {
Query: {
getUser: (_, __, { request, isAuthenticated }) => {
isAuthenticated(request);
return prisma.user({ id: request.user.id });
}
}
};
클라에서 보낼 땐
const client = new ApolloClient({
cache,
uri: 'http://localhost:4000',
typeDefs, // 로컬상태
resolvers, // 로컬상태
request: async operation => {
// 이 함수가 리턴하는 값은 요청마다 추가도ㅔㅐ. 이함수가 매 요청마다 호출되는거지.
// 매 요청을 중간에 가로채는거야.
const token = await AsyncStorage.getItem('jwt');
console.log('👨❤️💋👨', token);
return operation.setContext({
// 요청마다 이 함수가 실행돼.
headers: {Authorization: `Bearer ${token}`},
});
},
});
'Development > GraphQL' 카테고리의 다른 글
GQL서버 init (0) | 2020.04.10 |
---|---|
[GraphQL] apollo-server와 express 연결하기 (0) | 2020.03.22 |
[GraphQL / Apollo] 도입해보기 (0) | 2020.03.02 |
[GraphQL / Apollo] 오프라인 노트앱 만들기 (0) | 2020.02.16 |