"use strict"; require("dotenv").config(); const cors = require("cors"); const express = require("express"); const helmet = require("helmet"); const http = require("http"); const jwksClient = require("jwks-rsa"); const jwt = require("jsonwebtoken"); const { MongoClient } = require("mongodb"); const { ApolloServer, AuthenticationError, gql } = require("apollo-server-express"); const { ApolloServerPluginDrainHttpServer } = require("apollo-server-core"); const corsOrigins = process.env.APP_CORS_ORIGINS.split(","); const app = express(); app.enable("trust proxy"); app.use(cors({ origin: corsOrigins })); if (app.get("env") === "production") { app.use(helmet()); app.use(helmet.contentSecurityPolicy()); } const httpServer = http.createServer(app); const typeDefs = gql` "Party definition." type Party { "Unique party identifier" _id: ID! "Full name, concatenation of first, last, and middle." name: String! """ Auth0 user identifier. Application access granted when set. """ user_id: String "On-boarded in the application?." onboarded: Boolean! } "Query definitions." type Query { "Get party by identifier." getParty(_id: ID!): Party! } `; const resolvers = { Query: { getParty: async (parent, args, { user, dataSources }) => { const parties = dataSources.mongodb.collection("parties"); const party = await parties.findOne({ _id: args._id }); return party; } } }; let client = jwksClient({ jwksUri: `https://${process.env.AUTH0_DOMAIN}/.well-known/jwks.json` }); const authentication = async context => { const token = context.req.headers.authorization || ""; if (!token) throw new AuthenticationError("Authentication required"); const keys = await client.getSigningKeys(); const user = await jwt.verify(token, keys[0].getPublicKey(), { algorithms: [ "RS256" ] }); if (!user.email) throw new AuthenticationError("Wrong token presented"); return { user }; } const mongodb = new MongoClient(process.env.MONGODB_STRING, { useNewUrlParser: true, useUnifiedTopology: true }); mongodb.connect(); const apollo = new ApolloServer({ typeDefs, resolvers, dataSources: _ => ({ mongodb: mongodb.db(process.env.MONGODB_DB) }), plugin: [ApolloServerPluginDrainHttpServer({ httpServer })], context: authentication }); apollo.start().then(_ => { apollo.applyMiddleware({ app }); app.all("*", (request, response) => response.send("")); httpServer.listen(process.env.APP_PORT); let apolloData = httpServer.address(); console.log(`GraphQL service listening on ${apolloData.address}:${apolloData.port}${apollo.graphqlPath}`); }).catch(error => console.log(error.message));