📝인증 및 인가
import { ApolloServer } from '@apollo/server';
import { startStandaloneServer } from '@apollo/server/standalone';
import { GraphQLError } from 'graphql';
interface MyContext {
user: UserInterface;
}
const server = new ApolloServer<MyContext>({
typeDefs,
resolvers,
});
const { url } = await startStandaloneServer(server, {
context: async ({ req }) => {
// get the user token from the headers
const token = req.headers.authorization || '';
// try to retrieve a user with the token
const user = getUser(token);
// optionally block the user
// we could also check user roles/permissions here
if (!user)
// throwing a `GraphQLError` here allows us to specify an HTTP status code,
// standard `Error`s will have a 500 status code by default
throw new GraphQLError('User is not authenticated', {
extensions: {
code: 'UNAUTHENTICATED',
http: { status: 401 },
},
});
// add the user to the context
return { user };
},
});
console.log(`🚀 Server listening at: ${url}`);
Apollo Server에서는 contextValue라는 걸 제공하는데 헤더에 대한 정보를 추출할 수 있습니다 이걸 이용해 인증 및 인가에 대한 처리가 가능합니다
const resolvers = {
Query: {
adminData: (parent, args, context) => {
if (!context.user || context.user.role !== 'ADMIN') {
throw new AuthenticationError('You must be an admin to view this data');
}
return "This is private data only for administrators.";
}
}
};
Resolver에서도 가능합니다
const typeDefs = `#graphql
directive @auth(requires: Role = ADMIN) on OBJECT | FIELD_DEFINITION
enum Role {
ADMIN
REVIEWER
USER
}
type User @auth(requires: USER) {
name: String
banned: Boolean @auth(requires: ADMIN)
canPost: Boolean @auth(requires: REVIEWER)
}
`;
Directive로 설정도 가능합니다
자세한 건 공식 문서를 참고바랍니다
https://www.apollographql.com/docs/apollo-server/security/authentication
📝CORS
CORS 설정이 기본적으로 되어있다
자세한 건 공식 문서를 참고바랍니다
https://www.apollographql.com/docs/apollo-server/security/cors
📝SSL
import { ApolloServer } from '@apollo/server';
import { expressMiddleware } from '@apollo/server/express4';
import { ApolloServerPluginDrainHttpServer } from '@apollo/server/plugin/drainHttpServer';
import typeDefs from './graphql/schema';
import resolvers from './graphql/resolvers';
import cors from 'cors';
import express from 'express';
import http from 'http';
import https from 'https';
import fs from 'fs';
const configurations = {
// Note: You may need sudo to run on port 443
production: { ssl: true, port: 443, hostname: 'example.com' },
development: { ssl: false, port: 4000, hostname: 'localhost' },
};
const environment = process.env.NODE_ENV || 'production';
const config = configurations[environment];
const server = new ApolloServer({
typeDefs,
resolvers,
});
await server.start();
const app = express();
// our express server is mounted at /graphql
app.use('/graphql', cors<cors.CorsRequest>(), express.json(), expressMiddleware(server));
// Create the HTTPS or HTTP server, per configuration
let httpServer;
if (config.ssl) {
// Assumes certificates are in a .ssl folder off of the package root.
// Make sure these files are secured.
httpServer = https.createServer(
{
key: fs.readFileSync(`./ssl/${environment}/server.key`),
cert: fs.readFileSync(`./ssl/${environment}/server.crt`),
},
app,
);
} else {
httpServer = http.createServer(app);
}
await new Promise<void>((resolve) => httpServer.listen({ port: config.port }, resolve));
console.log('🚀 Server ready at', `http${config.ssl ? 's' : ''}://${config.hostname}:${config.port}/graphql`);
SSL 설정을 프로뎍선 레벨과 개발 레벨로 나눌 수 있다
자세한 건 공식 문서를 참고바랍니다
https://www.apollographql.com/docs/apollo-server/security/terminating-ssl
📝Proxy (프록시)
나가는 요청등에 대한 프록시 설정이 가능한데 자세한 건 문서를 참고바랍니다
https://www.apollographql.com/docs/apollo-server/security/proxy-configuration
📝클라우드 서버 배포 (Lambda, Heroku)
클라우드 서버에 가장 많이 배포하는 유형에 대한 설명이 있습니다 AWS의 Lambda와 Heroku가 있으니 자세한건 문서 참고 바랍니다
https://www.apollographql.com/docs/apollo-server/deployment/lambda
https://www.apollographql.com/docs/apollo-server/deployment/heroku
📝로깅 (Logging)
GRAPH OS라는 제품을 제공하는데 이걸 이용해 로깅을 따로 집계하고 통계를 내는 등에 역할을 도와줍니다
const myPlugin = {
// Fires whenever a GraphQL request is received from a client.
async requestDidStart(requestContext) {
console.log('Request started! Query:\n' + requestContext.request.query);
return {
// Fires whenever Apollo Server will parse a GraphQL
// request to create its associated document AST.
async parsingDidStart(requestContext) {
console.log('Parsing started!');
},
// Fires whenever Apollo Server will validate a
// request's document AST against your GraphQL schema.
async validationDidStart(requestContext) {
console.log('Validation started!');
},
};
},
};
const server = new ApolloServer({
typeDefs,
resolvers,
plugins: [myPlugin],
});
또한 사용자 정의 플러그인을 이용해 세분화된 작업 로깅을 설정할 수 있습니다
자세한 사항은 공식 문서를 참고바랍니다
https://www.apollographql.com/docs/apollo-server/monitoring/metrics