{"id":23082,"date":"2018-10-29T11:33:36","date_gmt":"2018-10-29T09:33:36","guid":{"rendered":"http:\/\/www.webcodegeeks.com\/?p=23082"},"modified":"2018-11-05T09:03:46","modified_gmt":"2018-11-05T07:03:46","slug":"build-simple-graphql-api-service-express","status":"publish","type":"post","link":"https:\/\/www.webcodegeeks.com\/web-development\/build-simple-graphql-api-service-express\/","title":{"rendered":"Build a Simple GraphQL API Service with Express"},"content":{"rendered":"<p><span style=\"font-size: 20px;\"><b>\u201cI love writing authentication and authorization code.\u201d ~ No Web Developer Ever.<\/b> Tired of building the same login screens over and over? <a href=\"https:\/\/developer.okta.com\/signup\/?utm_source=web%20Code%20Geeks&#038;utm_medium=Content%20Syndication&#038;utm_campaign=express%20graphql%20api\">Try the Okta API for hosted authentication, authorization, and multi-factor auth.<\/a> <\/span><\/p>\n<p>GraphQL has become an immensely popular alternative to REST APIs. The flexibility you get from using GraphQL makes it easier for developers to get any information they need for an app, and\u00a0<em>just<\/em>\u00a0the information they need for that portion of the app. That gives you the feel of a very customized API and can help cut down on bandwidth.<\/p>\n<p>In this tutorial, I\u2019ll show you how to write a custom GraphQL API using Node and Express. I\u2019ll also show you how to secure parts of the API while making other parts open to the public.<\/p>\n<h2 id=\"create-the-graphql-api-with-express\">Create the GraphQL API with Express<\/h2>\n<p>If you\u2019re in a hurry and would rather cut to the chase, you can find the final sample code\u00a0<a href=\"https:\/\/github.com\/oktadeveloper\/okta-express-graphql-example\">on GitHub<\/a>. However, if you want to follow along to get more detail and see how the code was put together, keep reading.<\/p>\n<p>To create the API, start by creating a new folder and creating a\u00a0<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">package.json<\/code>\u00a0file to manage your dependencies. You\u2019ll also need to install a few dependencies to get GraphQL with Express up and running:<\/p>\n<pre class=\"gutter: false;brush:bash\">mkdir graphql-express\r\ncd graphql-express\r\nnpm init -y\r\nnpm install express@2.8.4 express-graphql@0.6.12 graphql@14.0.2 graphql-tag@2.9.2 cors@2.8.4<\/pre>\n<p>Now create a file named\u00a0<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">index.js<\/code>. This will be your main entry point:<\/p>\n<pre class=\"gutter: false;brush:js\">const express = require('express')\r\nconst cors = require('cors')\r\nconst graphqlHTTP = require('express-graphql')\r\nconst gql = require('graphql-tag')\r\nconst { buildASTSchema } = require('graphql')\r\n\r\nconst app = express()\r\napp.use(cors())\r\n\r\nconst schema = buildASTSchema(gql`\r\n  type Query {\r\n    hello: String\r\n  }\r\n`)\r\n\r\nconst rootValue = {\r\n  hello: () =&gt; 'Hello, world'\r\n}\r\n\r\napp.use('\/graphql', graphqlHTTP({ schema, rootValue }))\r\n\r\nconst port = process.env.PORT || 4000\r\napp.listen(port)\r\nconsole.log(`Running a GraphQL API server at localhost:${port}\/graphql`)<\/pre>\n<p>This is about as simple as a GraphQL server gets. All this does is return \u201cHello, world\u201d when you query \u201chello\u201d, but it\u2019s a start. To take it for a test spin, run\u00a0<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">node .<\/code>, then in another tab open your browser to the\u00a0<a href=\"https:\/\/graphqlbin.com\/\">GraphQL Playground<\/a>. Once there, enter\u00a0<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">http:\/\/localhost:4000\/graphql<\/code>\u00a0to access your GraphQL server.<\/p>\n<p><a href=\"http:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2018\/10\/1.png\"><img decoding=\"async\" class=\"aligncenter wp-image-23083\" style=\"border: none;\" src=\"http:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2018\/10\/1.png\" alt=\"GraphQL API\" width=\"820\" height=\"471\" srcset=\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2018\/10\/1.png 1588w, https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2018\/10\/1-300x172.png 300w, https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2018\/10\/1-768x442.png 768w, https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2018\/10\/1-1024x589.png 1024w\" sizes=\"(max-width: 820px) 100vw, 820px\" \/><\/a><\/p>\n<p>The GraphQL Playground will help explore your schema and test out queries. It even automatically creates some documentation for you.<\/p>\n<p><a href=\"http:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2018\/10\/2.png\"><img decoding=\"async\" class=\"aligncenter wp-image-23084\" style=\"border: none;\" src=\"http:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2018\/10\/2.png\" alt=\"GraphQL API\" width=\"820\" height=\"548\" srcset=\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2018\/10\/2.png 1200w, https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2018\/10\/2-300x201.png 300w, https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2018\/10\/2-768x513.png 768w, https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2018\/10\/2-1024x684.png 1024w\" sizes=\"(max-width: 820px) 100vw, 820px\" \/><\/a><\/p>\n<p>Try querying for\u00a0<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">hello<\/code>\u00a0using the following query:<\/p>\n<pre class=\"gutter: false;brush:bash\">query {\r\n  hello\r\n}<\/pre>\n<p><a href=\"http:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2018\/10\/3.png\"><img decoding=\"async\" class=\"aligncenter wp-image-23085\" style=\"border: none;\" src=\"http:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2018\/10\/3.png\" alt=\"GraphQL API\" width=\"820\" height=\"439\" srcset=\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2018\/10\/3.png 1591w, https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2018\/10\/3-300x160.png 300w, https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2018\/10\/3-768x411.png 768w, https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2018\/10\/3-1024x548.png 1024w\" sizes=\"(max-width: 820px) 100vw, 820px\" \/><\/a><\/p>\n<h2 id=\"improve-your-graphql-developer-experience\">Improve Your GraphQL Developer Experience<\/h2>\n<p>Here are a couple quick tips to help make your development experience a little better:<\/p>\n<ol>\n<li>Install a linter to help catch bugs in your editor. This will help keep your styling consistent and catch any easily-avoidable bugs.\n<ul>\n<li>To install\u00a0<a href=\"https:\/\/standardjs.com\/\">StandardJS<\/a>, type\u00a0<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">npm install --save-dev standard@12.0.1<\/code>. Most editors will be able to show you warnings and errors as you type.<\/li>\n<li>You can also edit the\u00a0<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">scripts<\/code>\u00a0object of your\u00a0<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">package.json<\/code>\u00a0so that you can run the linter at any time with\u00a0<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">npm test<\/code>:\n<pre class=\"gutter: false;brush:js\">\"scripts\": {\r\n  \"test\": \"standard\"\r\n},<\/pre>\n<\/li>\n<\/ul>\n<\/li>\n<li>Automatically restart the server when you make changes.\n<ul>\n<li>Install\u00a0<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">nodemon<\/code>\u00a0with\u00a0<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">npm install --save-dev nodemon@1.18.4<\/code><\/li>\n<li>Add another script to\u00a0<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">package.json<\/code>, so you can run the server with\u00a0<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">npm start<\/code>. Combined with the above, your\u00a0<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">scripts<\/code>\u00a0object should look like this:\n<pre class=\"gutter: false;brush:js\">\"scripts\": {\r\n  \"test\": \"standard\",\r\n  \"start\": \"nodemon .\"\r\n},<\/pre>\n<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n<p>Go ahead and close the server you had run with\u00a0<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">node .<\/code>\u00a0and now type\u00a0<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">npm start<\/code>\u00a0to restart the development server. From now on, any changes you make will automatically restart the server.<\/p>\n<h2 id=\"create-the-graphql-queries\">Create the GraphQL Queries<\/h2>\n<p>To get something a little more useful, let\u2019s make a post editor. GraphQL is strongly typed, allowing you to create a type for each object and connect them. A common scenario might be to have a post with some text, that was written by a person. Update your schema to include these types. You can also update your\u00a0<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">Query<\/code>\u00a0type to utilize these new types.<\/p>\n<pre class=\"gutter: false;brush:js\">type Query {\r\n    posts: [Post]\r\n    post(id: ID): Post\r\n    authors: [Person]\r\n    author(id: ID): Person\r\n  }\r\n\r\n  type Post {\r\n    id: ID\r\n    author: Person\r\n    body: String\r\n  }\r\n\r\n  type Person {\r\n    id: ID\r\n    posts: [Post]\r\n    firstName: String\r\n    lastName: String\r\n  }<\/pre>\n<p>Even though the resolvers aren\u2019t set up, you can already go back to GraphQL Playground and refresh the schema by clicking the circular arrow icon next to the\u00a0<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">localhost<\/code>\u00a0URL.<\/p>\n<p><a href=\"http:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2018\/10\/4.png\"><img decoding=\"async\" class=\"aligncenter wp-image-23088 size-full\" style=\"border: none;\" src=\"http:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2018\/10\/4.png\" alt=\"GraphQL API\" width=\"634\" height=\"58\" srcset=\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2018\/10\/4.png 634w, https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2018\/10\/4-300x27.png 300w, https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2018\/10\/4-620x58.png 620w\" sizes=\"(max-width: 634px) 100vw, 634px\" \/><\/a><\/p>\n<p>The schema explorer is really useful for figuring out how to create your query. Click the green\u00a0<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">SCHEMA<\/code>\u00a0button to check out your new schema.<\/p>\n<p><a href=\"http:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2018\/10\/5.png\"><img decoding=\"async\" class=\"aligncenter wp-image-23089\" style=\"border: none;\" src=\"http:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2018\/10\/5.png\" alt=\"GraphQL API\" width=\"820\" height=\"389\" srcset=\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2018\/10\/5.png 1800w, https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2018\/10\/5-300x142.png 300w, https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2018\/10\/5-768x364.png 768w, https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2018\/10\/5-1024x486.png 1024w\" sizes=\"(max-width: 820px) 100vw, 820px\" \/><\/a><\/p>\n<p>You\u2019ll need some way to store the data. To keep it simple, use JavaScript\u2019s\u00a0<a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/JavaScript\/Reference\/Global_Objects\/Map\"><code class=\"highlighter-rouge\" style=\"font-size: 13px;\">Map<\/code><\/a>\u00a0object for in-memory storage. You can also create some classes that will help connect the data from one object to another.<\/p>\n<pre class=\"gutter: false;brush:js\">const PEOPLE = new Map()\r\nconst POSTS = new Map()\r\n\r\nclass Post {\r\n  constructor (data) { Object.assign(this, data) }\r\n  get author () {\r\n    return PEOPLE.get(this.authorId)\r\n  }\r\n}\r\n\r\nclass Person {\r\n  constructor (data) { Object.assign(this, data) }\r\n  get posts () {\r\n    return [...POSTS.values()].filter(post =&gt; post.authorId === this.id)\r\n  }\r\n}<\/pre>\n<p>Now if you have an instance of a\u00a0<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">Person<\/code>, you can find all of their posts by simply asking for\u00a0<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">person.posts<\/code>. Since GraphQL lets you only ask for the data you want, the\u00a0<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">posts<\/code>\u00a0getter will never get called unless you ask for it, which could speed up the query if that\u2019s an expensive operation.<\/p>\n<p>You\u2019ll also need to update your resolvers (the functions in\u00a0<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">rootValue<\/code>) in order to accommodate these new types.<\/p>\n<pre class=\"gutter: false;brush:js\">const rootValue = {\r\n  posts: () =&gt; POSTS.values(),\r\n  post: ({ id }) =&gt; POSTS.get(id),\r\n  authors: () =&gt; PEOPLE.values(),\r\n  author: ({ id }) =&gt; PEOPLE.get(id)\r\n}<\/pre>\n<p>This is great, but there\u2019s no data yet. For now, stub in some fake data. You can add this function and the call to it right after the assignment to\u00a0<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">rootValue<\/code>.<\/p>\n<pre class=\"gutter: false;brush:js\">const initializeData = () =&gt; {\r\n  const fakePeople = [\r\n    { id: '1', firstName: 'John', lastName: 'Doe' },\r\n    { id: '2', firstName: 'Jane', lastName: 'Doe' }\r\n  ]\r\n\r\n  fakePeople.forEach(person =&gt; PEOPLE.set(person.id, new Person(person)))\r\n\r\n  const fakePosts = [\r\n    { id: '1', authorId: '1', body: 'Hello world' },\r\n    { id: '2', authorId: '2', body: 'Hi, planet!' }\r\n  ]\r\n\r\n  fakePosts.forEach(post =&gt; POSTS.set(post.id, new Post(post)))\r\n}\r\n\r\ninitializeData()<\/pre>\n<p>Now that you have your queries all set up and some data stubbed in, go back to GraphQL Playground and play around a bit. Try getting all the posts, or get all the authors and posts associated with each one.<\/p>\n<pre class=\"gutter: false;brush:js\">query {\r\n  posts {\r\n    id\r\n    author {\r\n      id\r\n      firstName\r\n      lastName\r\n    }\r\n    body\r\n  }\r\n}<\/pre>\n<p><a href=\"http:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2018\/10\/6.png\"><img decoding=\"async\" class=\"aligncenter wp-image-23090\" style=\"border: none;\" src=\"http:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2018\/10\/6.png\" alt=\"GraphQL API\" width=\"820\" height=\"709\" srcset=\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2018\/10\/6.png 1938w, https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2018\/10\/6-300x259.png 300w, https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2018\/10\/6-768x664.png 768w, https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2018\/10\/6-1024x886.png 1024w\" sizes=\"(max-width: 820px) 100vw, 820px\" \/><\/a><br \/>\nOr get weird and get a single post by id, then the author for that post, and all of that author\u2019s posts (including the one you just queried).<\/p>\n<pre class=\"gutter: false;brush:js\">query {\r\n  post(id: 2) {\r\n    id\r\n    author {\r\n      firstName\r\n      posts {\r\n        id\r\n        body\r\n      }\r\n    }\r\n    body\r\n  }\r\n}<\/pre>\n<p><a href=\"http:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2018\/10\/7.png\"><img decoding=\"async\" class=\"aligncenter wp-image-23091\" style=\"border: none;\" src=\"http:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2018\/10\/7.png\" alt=\"GraphQL API\" width=\"820\" height=\"709\" srcset=\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2018\/10\/7.png 1938w, https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2018\/10\/7-300x259.png 300w, https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2018\/10\/7-768x664.png 768w, https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2018\/10\/7-1024x886.png 1024w\" sizes=\"(max-width: 820px) 100vw, 820px\" \/><\/a><\/p>\n<h2 id=\"add-user-authentication-to-your-express--graphql-api\">Add User Authentication to Your Express + GraphQL API<\/h2>\n<p>One simple way to add authentication to your project is with Okta. Okta is a cloud service that allows developers to create, edit, and securely store user accounts and user account data, and connect them with one or multiple applications. If you don\u2019t already have one,\u00a0<a href=\"https:\/\/developer.okta.com\/signup\/\">sign up for a forever-free developer account<\/a>.<\/p>\n<p>You\u2019re going to need to save some information to use in the app. Create a new file named\u00a0<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">.env<\/code>. In it, enter in your organization URL.<\/p>\n<pre class=\"gutter: false;brush:bash\">HOST_URL=http:\/\/localhost:4000\r\nOKTA_ORG_URL=https:\/\/{yourOktaOrgUrl}<\/pre>\n<p>You will also need a random string to use as an App Secret for sessions. You can generate this with the following commands:<\/p>\n<pre class=\"gutter: false;brush:bash\">npm install -g uuid-cli\r\necho \"APP_SECRET=`uuid`\" &gt;&gt; .env<\/pre>\n<p>Next, log in to your developer console, navigate to\u00a0<strong>Applications<\/strong>, then click\u00a0<strong>Add Application<\/strong>. Select\u00a0<strong>Web<\/strong>, then click\u00a0<strong>Next<\/strong>.<\/p>\n<p><a href=\"http:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2018\/10\/8.png\"><img decoding=\"async\" class=\"aligncenter wp-image-23092\" style=\"border: none;\" src=\"http:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2018\/10\/8.png\" alt=\"GraphQL API\" width=\"820\" height=\"995\" srcset=\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2018\/10\/8.png 1310w, https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2018\/10\/8-247x300.png 247w, https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2018\/10\/8-768x932.png 768w, https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2018\/10\/8-844x1024.png 844w\" sizes=\"(max-width: 820px) 100vw, 820px\" \/><\/a><\/p>\n<p>The page you come to after creating an application has some more information you need to save to your\u00a0<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">.env<\/code>\u00a0file. Copy in the client ID and client secret.<\/p>\n<pre class=\"gutter: false;brush:bash\">OKTA_CLIENT_ID={yourClientId}\r\nOKTA_CLIENT_SECRET={yourClientSecret}<\/pre>\n<p>The last piece of information you need from Okta is an API token. In your developer console, navigate to\u00a0<strong>API<\/strong>\u00a0-&gt;\u00a0<strong>Tokens<\/strong>, then click on\u00a0<strong>Create Token<\/strong>. You can have many tokens, so just give this one a name that reminds you what it\u2019s for, like \u201cGraphQL Express\u201d. You\u2019ll be given a token that you can only see right now. If you lose the token, you\u2019ll have to create another one. Add this to\u00a0<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">.env<\/code>\u00a0also.<\/p>\n<pre class=\"gutter: false;brush:bash\">OKTA_TOKEN={yourOktaAPIToken}<\/pre>\n<p>Create a new file named\u00a0<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">okta.js<\/code>. This is where you\u2019ll create some utility functions, as well as get the app initialized for Okta. When authenticated through Okta, your app will authenticate through an access token using JWT. You can use this to determine who a user is. To avoid dealing directly with authentication in your app, a user would sign in on Okta\u2019s servers, then send you a JWT that you can verify.<\/p>\n<p><strong>okta.js<\/strong><\/p>\n<pre class=\"gutter: false;brush:js\">const session = require('express-session')\r\n\r\nconst OktaJwtVerifier = require('@okta\/jwt-verifier')\r\nconst verifier = new OktaJwtVerifier({\r\n  clientId: process.env.OKTA_CLIENT_ID,\r\n  issuer: `${process.env.OKTA_ORG_URL}\/oauth2\/default`\r\n})\r\n\r\nconst { Client } = require('@okta\/okta-sdk-nodejs')\r\nconst client = new Client({\r\n  orgUrl: process.env.OKTA_ORG_URL,\r\n  token: process.env.OKTA_TOKEN\r\n})\r\n\r\nconst { ExpressOIDC } = require('@okta\/oidc-middleware')\r\nconst oidc = new ExpressOIDC({\r\n  issuer: `${process.env.OKTA_ORG_URL}\/oauth2\/default`,\r\n  client_id: process.env.OKTA_CLIENT_ID,\r\n  client_secret: process.env.OKTA_CLIENT_SECRET,\r\n  redirect_uri: `${process.env.HOST_URL}\/authorization-code\/callback`,\r\n  scope: 'openid profile'\r\n})\r\n\r\nconst initializeApp = (app) =&gt; {\r\n  app.use(session({\r\n    secret: process.env.APP_SECRET,\r\n    resave: true,\r\n    saveUninitialized: false\r\n  }))\r\n  app.use(oidc.router)\r\n  app.use('\/access-token', oidc.ensureAuthenticated(), async (req, res, next) =&gt; {\r\n    res.send(req.userContext.tokens.access_token)\r\n  })\r\n}\r\n\r\nmodule.exports = { client, verifier, initializeApp }<\/pre>\n<p>The\u00a0<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">initializeApp<\/code>\u00a0function adds some middleware to allow you to log in with Okta. Whenever you go to the\u00a0<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">http:\/\/localhost:4000\/access-token<\/code>, it will first check that you\u2019re logged in. If you aren\u2019t, it will first send you to Okta\u2019s servers to authenticate. Once authentication is successful, it returns you to the\u00a0<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">\/access-token<\/code>\u00a0route and will print out your current access token, which will be valid for about an hour.<\/p>\n<p>The\u00a0<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">client<\/code>\u00a0that you\u2019re exporting allows you to run some administrative calls on your server. You\u2019ll be using it later to get more information about a user based on their ID.<\/p>\n<p>the\u00a0<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">verifier<\/code>\u00a0is what you use to verify that a JWT is valid, and it gives you some basic information about a user, like their user ID and email address.<\/p>\n<p>Now, in\u00a0<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">index.js<\/code>, you\u2019ll need to import this file and call the\u00a0<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">initializeApp<\/code>\u00a0function. You also need to use a tool called\u00a0<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">dotenv<\/code>\u00a0that will read your\u00a0<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">.env<\/code>\u00a0file and add the variables to\u00a0<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">process.env<\/code>. At the very top of the file, add the following line:<\/p>\n<pre class=\"gutter: false;brush:js\">require('dotenv').config({ path: '.env' })<\/pre>\n<p>Just after the\u00a0<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">app.use(cors())<\/code>\u00a0line, add the following:<\/p>\n<pre class=\"gutter: false;brush:js\">const okta = require('.\/okta')\r\nokta.initializeApp(app)<\/pre>\n<p>To make this all work, you\u2019ll also need to install a few new dependencies:<\/p>\n<pre class=\"gutter: false;brush:bash; wrap-lines:false\">npm i @okta\/jwt-verifier@0.0.12 @okta\/oidc-middleware@1.0.0 @okta\/okta-sdk-nodejs@1.2.0 dotenv@6.0.0 express-session@1.15.6<\/pre>\n<p>You should now be able to go to\u00a0<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">http:\/\/localhost:4000\/access-token<\/code>\u00a0to log in and get an access token. If you were just at your developer console, you\u2019ll probably find you\u2019re already logged in. You can log out of your developer console to ensure the flow works properly.<\/p>\n<h2>Create GraphQL Mutations<\/h2>\n<p>Now it\u2019s time to use real data. There may be some real John and Jane Does out there, but chances are they don\u2019t have an account on your application yet. Next, I\u2019ll show you how to add some mutations that will use your current user to create, edit, or delete a post.<\/p>\n<p>To generate IDs for a post, you can use\u00a0<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">uuid<\/code>. Install it with\u00a0<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">npm install uuid@3.3.2<\/code>, then add it to\u00a0<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">index.js<\/code>\u00a0with:<\/p>\n<pre class=\"gutter: false;brush:js\">const uuid = require('uuid\/v4')<\/pre>\n<p>That should go near the top of the file, next to the other\u00a0<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">require<\/code>\u00a0statements.<\/p>\n<p>While still in\u00a0<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">index.js<\/code>, add the following types to your schema:<\/p>\n<pre class=\"gutter: false;brush:js\">type Mutation {\r\n    submitPost(input: PostInput!): Post\r\n    deletePost(id: ID!): Boolean\r\n  }\r\n\r\n  input PostInput {\r\n    id: ID\r\n    body: String!\r\n  }<\/pre>\n<p>To verify the user and save them as a new person, you\u2019ll need two new utility functions. Add these just before\u00a0<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">const rootValue<\/code>:<\/p>\n<pre class=\"gutter: false;brush:js\">const getUserId = async ({ authorization }) =&gt; {\r\n  try {\r\n    const accessToken = authorization.trim().split(' ')[1]\r\n    const { claims: { uid } } = await okta.verifier.verifyAccessToken(accessToken)\r\n\r\n    return uid\r\n  } catch (error) {\r\n    return null\r\n  }\r\n}\r\n\r\nconst saveUser = async (id) =&gt; {\r\n  try {\r\n    if (!PEOPLE.has(id)) {\r\n      const { profile: { firstName, lastName } } = await okta.client.getUser(id)\r\n\r\n      PEOPLE.set(id, new Person({ id, firstName, lastName }))\r\n    }\r\n  } catch (ignore) { }\r\n\r\n  return PEOPLE.get(id)\r\n}<\/pre>\n<p>The\u00a0<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">getUserId<\/code>\u00a0function will check that the\u00a0<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">authorization<\/code>\u00a0request header has a valid token. On success, it will return the user\u2019s ID.<\/p>\n<p>The\u00a0<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">saveUser<\/code>\u00a0function checks that the user isn\u2019t already saved. If they are, it simply returns the cached value. Otherwise, it will fetch the first and last name of the user and store that in the\u00a0<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">PEOPLE<\/code>\u00a0object.<\/p>\n<p>Now add the following resolvers to\u00a0<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">rootValue<\/code>:<\/p>\n<pre class=\"gutter: false;brush:js\">submitPost: async ({ input }, { headers }) =&gt; {\r\n    const authorId = await getUserId(headers)\r\n    if (!authorId) return null\r\n\r\n    const { id = uuid(), body } = input\r\n\r\n    if (POSTS.has(id) &amp;&amp; POSTS.get(id).authorId !== authorId) return null\r\n    await saveUser(authorId)\r\n\r\n    POSTS.set(id, new Post({ id, authorId, body }))\r\n\r\n    return POSTS.get(id)\r\n  },\r\n  deletePost: async ({ id }, { headers }) =&gt; {\r\n    if (!POSTS.has(id)) return false\r\n\r\n    const userId = await getUserId(headers)\r\n    if (POSTS.get(id).authorId !== userId) return false\r\n\r\n    POSTS.delete(id)\r\n\r\n    if (PEOPLE.get(userId).posts.length === 0) {\r\n      PEOPLE.delete(userId)\r\n    }\r\n\r\n    return true\r\n  }<\/pre>\n<p>The\u00a0<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">submitPost<\/code>\u00a0mutation first checks the user ID and returns\u00a0<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">null<\/code>\u00a0if there\u2019s no user. This means no operation will be done unless you\u2019re authenticated. It then gets the\u00a0<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">id<\/code>\u00a0and\u00a0<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">body<\/code>\u00a0off the input from the user. If there\u2019s no\u00a0<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">id<\/code>, it will generate a new one. If there\u2019s already a post with the provided ID, it checks that it\u2019s owned by the user trying to edit it. If not, it again returns\u00a0<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">null<\/code>.<\/p>\n<p>Once\u00a0<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">submitPost<\/code>\u00a0has determined that the user is able to add or edit this post, it makes a call to\u00a0<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">saveUser<\/code>. The\u00a0<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">saveUser<\/code>function won\u2019t do anything if the user already exists but will add the user if they don\u2019t. Next,\u00a0<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">submitPost<\/code>\u00a0adds the post to the\u00a0<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">POSTS<\/code>\u00a0object, and returns the value in case the client wants to query the added post (to get the ID, for example).<\/p>\n<p>The\u00a0<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">deletePost<\/code>\u00a0mutation will only let you delete a post if you\u2019re the user who created it. After successfully deleting a post, it checks to see if the user has any other posts. If that was their only post,\u00a0<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">deletePost<\/code>\u00a0will also remove that user from the dataset to clear up some (a rather small amount of) memory.<\/p>\n<p>You can also get rid of the\u00a0<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">initializeData<\/code>\u00a0function now that you have the ability to add real data.<\/p>\n<h2 id=\"test-the-new-graphql-mutations\">Test the New GraphQL Mutations<\/h2>\n<p>Try to make a call to the new mutation and create a post. Since you\u2019re not authenticated, you should get\u00a0<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">null<\/code>\u00a0in response.<\/p>\n<pre class=\"gutter: false;brush:js\">mutation {\r\n  submitPost(input: {\r\n    body: \"Hello, world!\"\r\n  }) {\r\n    id\r\n    body\r\n    author {\r\n      id\r\n      firstName\r\n      lastName\r\n      posts {\r\n        id\r\n        body\r\n      }\r\n    }\r\n  }\r\n}<\/pre>\n<p><a href=\"http:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2018\/10\/9.png\"><img decoding=\"async\" class=\"aligncenter wp-image-23093\" style=\"border: none;\" src=\"http:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2018\/10\/9.png\" alt=\"GraphQL API\" width=\"820\" height=\"554\" srcset=\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2018\/10\/9.png 1896w, https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2018\/10\/9-300x203.png 300w, https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2018\/10\/9-768x518.png 768w, https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2018\/10\/9-1024x691.png 1024w\" sizes=\"(max-width: 820px) 100vw, 820px\" \/><\/a><\/p>\n<p>Typically an app of some sort, whether a web app or a native app, will handle the UI for authentication and then seamlessly pass along the\u00a0<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">Authorization<\/code>\u00a0header to the API. In this case, since we\u2019re just focusing on the API, I had you implement an endpoint for grabbing the auth token manually.<\/p>\n<p>Head to\u00a0<a href=\"http:\/\/localhost:4000\/access-token\">http:\/\/localhost:4000\/access-token<\/a>\u00a0to sign in with Okta and get an access token. Copy the access token, then head back to the GraphQL Playground. At the bottom of the page, there\u2019s a link that says\u00a0<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">HTTP HEADERS<\/code>. When you click that, a section will open up that allows you to add some headers as JSON. Add the following, making sure to add\u00a0<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">Bearer<\/code>\u00a0to the front of the token, so it should look something like\u00a0<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">Bearer eyJraWQ...xHUOjj_A<\/code>\u00a0(although the real token will be much longer):<\/p>\n<pre class=\"gutter: false;brush:js\">{\r\n  \"authorization\": \"Bearer {yourAccessToken}\"\r\n}<\/pre>\n<p>You should now be authenticated, and the same mutation will return a valid post:<\/p>\n<p><a href=\"http:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2018\/10\/10.png\"><img decoding=\"async\" class=\"aligncenter wp-image-23094\" style=\"border: none;\" src=\"http:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2018\/10\/10.png\" alt=\"GraphQL API\" width=\"820\" height=\"659\" srcset=\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2018\/10\/10.png 1980w, https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2018\/10\/10-300x241.png 300w, https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2018\/10\/10-768x617.png 768w, https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2018\/10\/10-1024x823.png 1024w\" sizes=\"(max-width: 820px) 100vw, 820px\" \/><\/a><\/p>\n<p>If you want to mess around with other users, you can add people from the developer console by navigating to\u00a0<strong>Users<\/strong>\u00a0-&gt;\u00a0<strong>People<\/strong>, then clicking on\u00a0<strong>Add Person<\/strong>. You could then visit the\u00a0<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">\/access-token<\/code>\u00a0endpoint from an incognito window, or after logging out of the developer console.<\/p>\n<p><a href=\"http:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2018\/10\/11.png\"><img decoding=\"async\" class=\"aligncenter wp-image-23095\" style=\"border: none;\" src=\"http:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2018\/10\/11.png\" alt=\"GraphQL API\" width=\"820\" height=\"521\" srcset=\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2018\/10\/11.png 1916w, https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2018\/10\/11-300x191.png 300w, https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2018\/10\/11-768x488.png 768w, https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2018\/10\/11-1024x651.png 1024w\" sizes=\"(max-width: 820px) 100vw, 820px\" \/><\/a><\/p>\n<h2 id=\"learn-more-about-graphql-express-and-okta\">Learn more about GraphQL, Express, and Okta<\/h2>\n<p>Try playing around with the API a bit and see what fun stuff you can do with it. I think you\u2019ll quickly see what can make GraphQL so much more powerful than a traditional REST API, and how it can be fun to work with even if you\u2019re just using the Playground. See if you can come up data points to connect, or get data from external sources. Since resolvers are simply\u00a0<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">async<\/code>\u00a0functions, you could just as easily fetch data from an external API or from a database. Your imagination is the limit.<\/p>\n<p>If you want to see the final sample code, you can find it\u00a0<a href=\"https:\/\/github.com\/oktadeveloper\/okta-express-graphql-example\">on GitHub<\/a>.<\/p>\n<p>If you\u2019d like to learn more about GraphQL or Express, check out some of these other posts on the Okta developer blog:<\/p>\n<ul>\n<li><a href=\"https:\/\/developer.okta.com\/blog\/2018\/08\/16\/secure-api-spring-boot-graphql\">Build a Secure API with Spring Boot and GraphQL<\/a><\/li>\n<li><a href=\"https:\/\/developer.okta.com\/blog\/2018\/07\/11\/build-react-graphql-api-user-authentication\">Build a Health Tracking App with React, GraphQL, and User Authentication<\/a><\/li>\n<li><a href=\"https:\/\/developer.okta.com\/blog\/2018\/09\/13\/build-and-understand-express-middleware-through-examples\">Build and Understand Express Middleware through Examples<\/a><\/li>\n<li><a href=\"https:\/\/developer.okta.com\/blog\/2018\/08\/17\/build-and-understand-user-authentication-in-node\">Build and Understand a Simple Node.js Website with User Authentication<\/a><\/li>\n<li><a href=\"https:\/\/developer.okta.com\/blog\/2018\/06\/28\/tutorial-build-a-basic-crud-app-with-node\">Tutorial: Build a Basic CRUD App with Node.js<\/a><\/li>\n<\/ul>\n<p>If you have any questions about this post, please add a comment below. For more awesome content, follow\u00a0<a href=\"https:\/\/twitter.com\/oktadev\">@oktadev<\/a>\u00a0on Twitter, like us\u00a0<a href=\"https:\/\/www.facebook.com\/oktadevelopers\/\">on Facebook<\/a>, and subscribe to\u00a0<a href=\"https:\/\/www.youtube.com\/channel\/UC5AMiWqFVFxF1q9Ya1FuZ_Q\">our YouTube channel<\/a>.<\/p>\n<p><span style=\"font-size: 20px;\"><b>\u201cI love writing authentication and authorization code.\u201d ~ No Web Developer Ever.<\/b> Tired of building the same login screens over and over? <a href=\"https:\/\/developer.okta.com\/signup\/?utm_source=web%20Code%20Geeks&#038;utm_medium=Content%20Syndication&#038;utm_campaign=express%20graphql%20api\">Try the Okta API for hosted authentication, authorization, and multi-factor auth.<\/a> <\/span><\/p>\n<p><a href=\"https:\/\/developer.okta.com\/blog\/2018\/09\/27\/build-a-simple-api-service-with-express-and-graphql\" target=\"_blank\" rel=\"noopener\" data-saferedirecturl=\"https:\/\/www.google.com\/url?q=https:\/\/developer.okta.com\/blog\/2018\/09\/27\/build-a-simple-api-service-with-express-and-graphql&amp;source=gmail&amp;ust=1540885244347000&amp;usg=AFQjCNHayQJ10d90uJU4Kv1pQrCpoX3w4g\">Build a Simple API Service with Express and GraphQL&#8217;<\/a>\u00a0was originally published on the Okta developer blog on September 27, 2018.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u201cI love writing authentication and authorization code.\u201d ~ No Web Developer Ever. Tired of building the same login screens over and over? Try the Okta API for hosted authentication, authorization, and multi-factor auth. GraphQL has become an immensely popular alternative to REST APIs. The flexibility you get from using GraphQL makes it easier for developers &hellip;<\/p>\n","protected":false},"author":8215,"featured_media":927,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[8],"tags":[450],"class_list":["post-23082","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-web-development","tag-graphql"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v26.5 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Build a Simple GraphQL API Service with Express - Web Code Geeks - 2026<\/title>\n<meta name=\"description\" content=\"Interested to learn about GraphQL API? Check our article showing how to write a custom GraphQL API using Node and Express.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/developer.okta.com\/blog\/2018\/09\/27\/build-a-simple-api-service-with-express-and-graphql\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Build a Simple GraphQL API Service with Express - Web Code Geeks - 2026\" \/>\n<meta property=\"og:description\" content=\"Interested to learn about GraphQL API? Check our article showing how to write a custom GraphQL API using Node and Express.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/developer.okta.com\/blog\/2018\/09\/27\/build-a-simple-api-service-with-express-and-graphql\" \/>\n<meta property=\"og:site_name\" content=\"Web Code Geeks\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/webcodegeeks\" \/>\n<meta property=\"article:published_time\" content=\"2018-10-29T09:33:36+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2018-11-05T07:03:46+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/10\/web-dev-logo.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"150\" \/>\n\t<meta property=\"og:image:height\" content=\"150\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Braden Kelley\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@webcodegeeks\" \/>\n<meta name=\"twitter:site\" content=\"@webcodegeeks\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Braden Kelley\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"15 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/developer.okta.com\/blog\/2018\/09\/27\/build-a-simple-api-service-with-express-and-graphql#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/web-development\/build-simple-graphql-api-service-express\/\"},\"author\":{\"name\":\"Braden Kelley\",\"@id\":\"https:\/\/www.webcodegeeks.com\/#\/schema\/person\/d4c772abac1dfb78ec8fdc0955c6f095\"},\"headline\":\"Build a Simple GraphQL API Service with Express\",\"datePublished\":\"2018-10-29T09:33:36+00:00\",\"dateModified\":\"2018-11-05T07:03:46+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/web-development\/build-simple-graphql-api-service-express\/\"},\"wordCount\":2232,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/#organization\"},\"image\":{\"@id\":\"https:\/\/developer.okta.com\/blog\/2018\/09\/27\/build-a-simple-api-service-with-express-and-graphql#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/10\/web-dev-logo.jpg\",\"keywords\":[\"GraphQL\"],\"articleSection\":[\"Web Dev\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/developer.okta.com\/blog\/2018\/09\/27\/build-a-simple-api-service-with-express-and-graphql#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.webcodegeeks.com\/web-development\/build-simple-graphql-api-service-express\/\",\"url\":\"https:\/\/developer.okta.com\/blog\/2018\/09\/27\/build-a-simple-api-service-with-express-and-graphql\",\"name\":\"Build a Simple GraphQL API Service with Express - Web Code Geeks - 2026\",\"isPartOf\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/developer.okta.com\/blog\/2018\/09\/27\/build-a-simple-api-service-with-express-and-graphql#primaryimage\"},\"image\":{\"@id\":\"https:\/\/developer.okta.com\/blog\/2018\/09\/27\/build-a-simple-api-service-with-express-and-graphql#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/10\/web-dev-logo.jpg\",\"datePublished\":\"2018-10-29T09:33:36+00:00\",\"dateModified\":\"2018-11-05T07:03:46+00:00\",\"description\":\"Interested to learn about GraphQL API? Check our article showing how to write a custom GraphQL API using Node and Express.\",\"breadcrumb\":{\"@id\":\"https:\/\/developer.okta.com\/blog\/2018\/09\/27\/build-a-simple-api-service-with-express-and-graphql#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/developer.okta.com\/blog\/2018\/09\/27\/build-a-simple-api-service-with-express-and-graphql\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/developer.okta.com\/blog\/2018\/09\/27\/build-a-simple-api-service-with-express-and-graphql#primaryimage\",\"url\":\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/10\/web-dev-logo.jpg\",\"contentUrl\":\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/10\/web-dev-logo.jpg\",\"width\":150,\"height\":150},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/developer.okta.com\/blog\/2018\/09\/27\/build-a-simple-api-service-with-express-and-graphql#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.webcodegeeks.com\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Web Dev\",\"item\":\"https:\/\/www.webcodegeeks.com\/category\/web-development\/\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Build a Simple GraphQL API Service with Express\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.webcodegeeks.com\/#website\",\"url\":\"https:\/\/www.webcodegeeks.com\/\",\"name\":\"Web Code Geeks\",\"description\":\"Web Developers Resource Center\",\"publisher\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.webcodegeeks.com\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.webcodegeeks.com\/#organization\",\"name\":\"Exelixis Media P.C.\",\"url\":\"https:\/\/www.webcodegeeks.com\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.webcodegeeks.com\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png\",\"contentUrl\":\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png\",\"width\":864,\"height\":246,\"caption\":\"Exelixis Media P.C.\"},\"image\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/www.facebook.com\/webcodegeeks\",\"https:\/\/x.com\/webcodegeeks\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.webcodegeeks.com\/#\/schema\/person\/d4c772abac1dfb78ec8fdc0955c6f095\",\"name\":\"Braden Kelley\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.webcodegeeks.com\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/f7a19118235ccd8ddc4c8719de325cfaa654cc4269b3f00eb2b680029fa2774c?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/f7a19118235ccd8ddc4c8719de325cfaa654cc4269b3f00eb2b680029fa2774c?s=96&d=mm&r=g\",\"caption\":\"Braden Kelley\"},\"sameAs\":[\"https:\/\/developer.okta.com\/blog\/\"],\"url\":\"https:\/\/www.webcodegeeks.com\/author\/braden-kelley\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Build a Simple GraphQL API Service with Express - Web Code Geeks - 2026","description":"Interested to learn about GraphQL API? Check our article showing how to write a custom GraphQL API using Node and Express.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/developer.okta.com\/blog\/2018\/09\/27\/build-a-simple-api-service-with-express-and-graphql","og_locale":"en_US","og_type":"article","og_title":"Build a Simple GraphQL API Service with Express - Web Code Geeks - 2026","og_description":"Interested to learn about GraphQL API? Check our article showing how to write a custom GraphQL API using Node and Express.","og_url":"https:\/\/developer.okta.com\/blog\/2018\/09\/27\/build-a-simple-api-service-with-express-and-graphql","og_site_name":"Web Code Geeks","article_publisher":"https:\/\/www.facebook.com\/webcodegeeks","article_published_time":"2018-10-29T09:33:36+00:00","article_modified_time":"2018-11-05T07:03:46+00:00","og_image":[{"width":150,"height":150,"url":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/10\/web-dev-logo.jpg","type":"image\/jpeg"}],"author":"Braden Kelley","twitter_card":"summary_large_image","twitter_creator":"@webcodegeeks","twitter_site":"@webcodegeeks","twitter_misc":{"Written by":"Braden Kelley","Est. reading time":"15 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/developer.okta.com\/blog\/2018\/09\/27\/build-a-simple-api-service-with-express-and-graphql#article","isPartOf":{"@id":"https:\/\/www.webcodegeeks.com\/web-development\/build-simple-graphql-api-service-express\/"},"author":{"name":"Braden Kelley","@id":"https:\/\/www.webcodegeeks.com\/#\/schema\/person\/d4c772abac1dfb78ec8fdc0955c6f095"},"headline":"Build a Simple GraphQL API Service with Express","datePublished":"2018-10-29T09:33:36+00:00","dateModified":"2018-11-05T07:03:46+00:00","mainEntityOfPage":{"@id":"https:\/\/www.webcodegeeks.com\/web-development\/build-simple-graphql-api-service-express\/"},"wordCount":2232,"commentCount":0,"publisher":{"@id":"https:\/\/www.webcodegeeks.com\/#organization"},"image":{"@id":"https:\/\/developer.okta.com\/blog\/2018\/09\/27\/build-a-simple-api-service-with-express-and-graphql#primaryimage"},"thumbnailUrl":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/10\/web-dev-logo.jpg","keywords":["GraphQL"],"articleSection":["Web Dev"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/developer.okta.com\/blog\/2018\/09\/27\/build-a-simple-api-service-with-express-and-graphql#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.webcodegeeks.com\/web-development\/build-simple-graphql-api-service-express\/","url":"https:\/\/developer.okta.com\/blog\/2018\/09\/27\/build-a-simple-api-service-with-express-and-graphql","name":"Build a Simple GraphQL API Service with Express - Web Code Geeks - 2026","isPartOf":{"@id":"https:\/\/www.webcodegeeks.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/developer.okta.com\/blog\/2018\/09\/27\/build-a-simple-api-service-with-express-and-graphql#primaryimage"},"image":{"@id":"https:\/\/developer.okta.com\/blog\/2018\/09\/27\/build-a-simple-api-service-with-express-and-graphql#primaryimage"},"thumbnailUrl":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/10\/web-dev-logo.jpg","datePublished":"2018-10-29T09:33:36+00:00","dateModified":"2018-11-05T07:03:46+00:00","description":"Interested to learn about GraphQL API? Check our article showing how to write a custom GraphQL API using Node and Express.","breadcrumb":{"@id":"https:\/\/developer.okta.com\/blog\/2018\/09\/27\/build-a-simple-api-service-with-express-and-graphql#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/developer.okta.com\/blog\/2018\/09\/27\/build-a-simple-api-service-with-express-and-graphql"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/developer.okta.com\/blog\/2018\/09\/27\/build-a-simple-api-service-with-express-and-graphql#primaryimage","url":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/10\/web-dev-logo.jpg","contentUrl":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/10\/web-dev-logo.jpg","width":150,"height":150},{"@type":"BreadcrumbList","@id":"https:\/\/developer.okta.com\/blog\/2018\/09\/27\/build-a-simple-api-service-with-express-and-graphql#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.webcodegeeks.com\/"},{"@type":"ListItem","position":2,"name":"Web Dev","item":"https:\/\/www.webcodegeeks.com\/category\/web-development\/"},{"@type":"ListItem","position":3,"name":"Build a Simple GraphQL API Service with Express"}]},{"@type":"WebSite","@id":"https:\/\/www.webcodegeeks.com\/#website","url":"https:\/\/www.webcodegeeks.com\/","name":"Web Code Geeks","description":"Web Developers Resource Center","publisher":{"@id":"https:\/\/www.webcodegeeks.com\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.webcodegeeks.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.webcodegeeks.com\/#organization","name":"Exelixis Media P.C.","url":"https:\/\/www.webcodegeeks.com\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.webcodegeeks.com\/#\/schema\/logo\/image\/","url":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","contentUrl":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","width":864,"height":246,"caption":"Exelixis Media P.C."},"image":{"@id":"https:\/\/www.webcodegeeks.com\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/webcodegeeks","https:\/\/x.com\/webcodegeeks"]},{"@type":"Person","@id":"https:\/\/www.webcodegeeks.com\/#\/schema\/person\/d4c772abac1dfb78ec8fdc0955c6f095","name":"Braden Kelley","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.webcodegeeks.com\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/f7a19118235ccd8ddc4c8719de325cfaa654cc4269b3f00eb2b680029fa2774c?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/f7a19118235ccd8ddc4c8719de325cfaa654cc4269b3f00eb2b680029fa2774c?s=96&d=mm&r=g","caption":"Braden Kelley"},"sameAs":["https:\/\/developer.okta.com\/blog\/"],"url":"https:\/\/www.webcodegeeks.com\/author\/braden-kelley\/"}]}},"_links":{"self":[{"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/posts\/23082","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/users\/8215"}],"replies":[{"embeddable":true,"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/comments?post=23082"}],"version-history":[{"count":0,"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/posts\/23082\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/media\/927"}],"wp:attachment":[{"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/media?parent=23082"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/categories?post=23082"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/tags?post=23082"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}