{"id":5359,"date":"2018-06-28T07:00:12","date_gmt":"2018-06-28T14:00:12","guid":{"rendered":"https:\/\/www.couchbase.com\/blog\/?p=5359"},"modified":"2025-06-13T18:32:52","modified_gmt":"2025-06-14T01:32:52","slug":"jwt-authentication-with-graphql-node-js-and-couchbase-nosql","status":"publish","type":"post","link":"https:\/\/www.couchbase.com\/blog\/jwt-authentication-with-graphql-node-js-and-couchbase-nosql\/","title":{"rendered":"JWT Authentication with GraphQL, Node.js &amp; Couchbase NoSQL"},"content":{"rendered":"<p>A few months ago when I had first started learning about GraphQL, I had written a <a href=\"https:\/\/www.couchbase.com\/blog\/creating-a-graphql-application-with-node-js-and-a-nosql-database\/\" target=\"_blank\" rel=\"noopener noreferrer\">previous tutorial<\/a> for using it with Couchbase and Node.js. The tutorial focused on the basics which included creating GraphQL objects and querying those objects from the NoSQL database, <a href=\"https:\/\/www.couchbase.com\" target=\"_blank\" rel=\"noopener noreferrer\">Couchbase<\/a>. Fast forward a bit and I wrote a tutorial that offered an <a href=\"https:\/\/www.thepolyglotdeveloper.com\/2018\/05\/getting-started-graphql-development-nodejs\/\" target=\"_blank\" rel=\"noopener noreferrer\">alternative way<\/a> to use GraphQL with Node.js, even though the database layer wasn&#8217;t the emphasis.<\/p>\n<p>When using or creating an API, there are often scenarios where you don&#8217;t want all data to be accessible by everyone. In these scenarios, you&#8217;d want some kind of regulation through authorization and API tokens. Like with a RESTful API, this can easily be accomplished through JSON web tokens (JWT).<\/p>\n<p>We&#8217;re going to see how to use JWT in a <a href=\"https:\/\/graphql.org\/\" target=\"_blank\" rel=\"noopener noreferrer\">GraphQL<\/a> application to protect certain pieces of data rather than all or none.<\/p>\n<p><!--more--><\/p>\n<p>Going forward, it is probably a good idea to have at least a little bit of an understanding of how JSON web tokens (JWT) work. If you&#8217;d like to check out a quick getting started guide, check out my tutorial titled,\u00a0<a href=\"https:\/\/www.thepolyglotdeveloper.com\/2017\/03\/jwt-authentication-in-a-node-js-powered-api\/\" target=\"_blank\" rel=\"noopener noreferrer\">JWT Authentication in a Node.js Powered API<\/a>. The focus of that tutorial is not GraphQL, but it still works as a good starting point.<\/p>\n<p>The goal for this tutorial is to create an API that uses GraphQL. We&#8217;ll be able to create accounts, obtain tokens, and use those tokens to access protected parts of our API. Instructions for installing and configuring Couchbase will not be a part of this tutorial, but nothing special needs to be done for compatibility.<\/p>\n<h2>Creating a New Node.js Application with the Project Dependencies<\/h2>\n<p>Before we jump into the heavier and more complex parts of our project, let&#8217;s create a fresh project with all the dependencies and some boilerplate code. Assuming that you&#8217;ve already got Node.js installed and configured, execute the following from your CLI:<\/p>\n<pre class=\"lang:default decode:true \">npm init -y\r\nnpm install express --save\r\nnpm install express-graphql --save\r\nnpm install graphql --save\r\nnpm install jsonwebtoken --save\r\nnpm install uuid --save\r\nnpm install couchbase --save\r\nnpm install body-parser --save\r\nnpm install bcryptjs --save<\/pre>\n<p>The above commands will create a new\u00a0<strong>package.json<\/strong> file and install each of our necessary packages. These packages include a GraphQL library as well as a GraphQL extension for Express Framework. We&#8217;re also including a way to hash our password data, create JWT, and store everything in Couchbase. Could I have done this with a single line? Yes, but I thought it would be easier to read if I broke it up.<\/p>\n<p>With the project created, go ahead and create an\u00a0<strong>app.js<\/strong> file that includes the following code:<\/p>\n<pre class=\"lang:default decode:true \">const Express = require(\"express\");\r\nconst Couchbase = require(\"couchbase\");\r\nconst BodyParser = require(\"body-parser\");\r\nconst JsonWebToken = require(\"jsonwebtoken\");\r\nconst Bcrypt = require(\"bcryptjs\");\r\nconst ExpressGraphQL = require(\"express-graphql\");\r\nconst GraphQLObjectType = require(\"graphql\").GraphQLObjectType;\r\nconst GraphQLID = require(\"graphql\").GraphQLID;\r\nconst GraphQLString = require(\"graphql\").GraphQLString;\r\nconst GraphQLSchema = require(\"graphql\").GraphQLSchema;\r\nconst GraphQLList = require(\"graphql\").GraphQLList;\r\nconst UUID = require(\"uuid\");\r\n\r\nvar cluster = new Couchbase.Cluster(\"couchbase:\/\/localhost\");\r\ncluster.authenticate(\"example\", \"123456\");\r\nvar bucket = cluster.openBucket(\"example\");\r\n\r\nvar app = Express();\r\n\r\napp.use(BodyParser.json());\r\napp.set(\"jwt-secret\", \"polyglotdeveloper\");\r\n\r\napp.use(\"\/graphql\", ExpressGraphQL({\r\n    graphiql: true\r\n}));\r\n\r\napp.post(\"\/register\", (request, response) =&gt; { });\r\n\r\napp.post(\"\/login\", (request, response) =&gt; { });\r\n\r\napp.listen(3000, () =&gt; {\r\n    console.log(\"Listening at :3000\");\r\n});<\/pre>\n<p>We&#8217;re going to call the above code our boilerplate code. Essentially we&#8217;re just doing some setup and nothing truly relevant to our end goal. We&#8217;re importing our downloaded packages, establishing a connection to Couchbase, configuring Express Framework, defining three endpoints, and serving on port 3000.<\/p>\n<p>Make sure to use your own Couchbase information rather than the information I used. Also, for better security, change the <code>jwt-secret<\/code> so your tokens are hashed in a less predictable fashion than mine.<\/p>\n<h2>Designing Simple Account API endpoints for Login and Registration<\/h2>\n<p>You&#8217;ll notice from our boilerplate code that we have an endpoint for both registration and sign-in. There are many ways to accomplish what we&#8217;re trying to do, probably some better than my solution. However, I found what we&#8217;re about to see logical and easy to implement without getting too far away from our goals.<\/p>\n<p>Starting with the <code>\/register<\/code> endpoint, we have the following:<\/p>\n<pre class=\"lang:default decode:true \">app.post(\"\/register\", (request, response) =&gt; {\r\n    var id = UUID.v4();\r\n    request.body.type = \"account\";\r\n    request.body.password = Bcrypt.hashSync(request.body.password, 10);\r\n    bucket.insert(id, request.body, (error, result) =&gt; {\r\n        if(error) {\r\n            return response.status(500).send({ code: error.code, message: error.message });\r\n        }\r\n        response.send(request.body);\r\n    });\r\n});<\/pre>\n<p>When a user sends a POST request with <code>username<\/code> and <code>password<\/code> in the body, we are first creating a new UUID to be used as our Couchbase document key, then we are hashing the password using Bcrypt, like <a href=\"https:\/\/www.couchbase.com\/blog\/hashing-passwords-stored-in-couchbase-server-with-nodejs\/\" target=\"_blank\" rel=\"noopener noreferrer\">previously demonstrated<\/a> in a tutorial I wrote.<\/p>\n<p>Once a hash is created, we store the profile data in Couchbase and return it. The whole goal behind the <code>\/register<\/code> endpoint is to give us some data to authenticate with. To authenticate, we use the <code>\/login<\/code> endpoint as seen below:<\/p>\n<pre class=\"lang:default decode:true \">app.post(\"\/login\", (request, response) =&gt; {\r\n    var statement = \"SELECT META(account).id, account.username, account.`password` FROM `\" + bucket._name + \"` AS account WHERE account.type = 'account' AND account.username = $username\";\r\n    var query = Couchbase.N1qlQuery.fromString(statement);\r\n    bucket.query(query, { \"username\": request.body.username }, (error, account) =&gt; {\r\n        if(error) {\r\n            return response.status(500).send({ code: error.code, message: error.message });\r\n        }\r\n        Bcrypt.compare(request.body.password, account[0].password, function(error, result) {\r\n            if(error || !result) {\r\n                return response.status(401).send({ \"success\": false, \"message\": \"Invalid username and password\" });\r\n            }\r\n            var token = JsonWebToken.sign(account[0].id, app.get(\"jwt-secret\"), {});\r\n            response.send({\"token\": token});\r\n        });\r\n    });\r\n});<\/pre>\n<p>In the above code, we are creating a N1QL query to find a document that contains a username that matches the username that was passed with the request. We&#8217;re using a parameterized query to prevent any kind of SQL injection attack.<\/p>\n<p>If a document was found, we then compare the stored hashed password with the password that was passed in with the request. If it matches, we can sign the user id using our secret, giving us a JWT to be used in future requests.<\/p>\n<p>A few things to note with our two endpoints:<\/p>\n<ol>\n<li>We&#8217;re not doing any data validation. This is an example and we&#8217;re trying to keep things simple.<\/li>\n<li>We&#8217;re not setting an expiration on our JWT. Typically you&#8217;d want it to expire within an hour, but this is just a simple example.<\/li>\n<\/ol>\n<p>As of now, we&#8217;ve done nothing with GraphQL. We&#8217;ve just laid down the foundation for creating users and getting JSON web tokens. Even though we&#8217;re creating JWT, we are not validating that they are accurate as of now.<\/p>\n<h2>Validating JSON Web Tokens (JWT) with an Express Framework Function<\/h2>\n<p>When it comes to working with protected data, having a JWT is not enough. We want to make sure the token is in fact valid by checking the signature. We also need a solution for passing JWT around.<\/p>\n<p>Express Framework does have middleware for working with JSON web tokens, but I found the documentation to be lacking. Instead, it seemed easier to just create my own method for validation. Take the following:<\/p>\n<pre class=\"lang:default decode:true \">app.use((request, response, next) =&gt; {\r\n    var authHeader = request.headers[\"authorization\"];\r\n    if(authHeader) {\r\n        var bearerToken = authHeader.split(\" \");\r\n        if(bearerToken.length == 2 &amp;&amp; bearerToken[0].toLowerCase() == \"bearer\") {\r\n            JsonWebToken.verify(bearerToken[1], app.get(\"jwt-secret\"), function(error, decodedToken) {\r\n                if(error) {\r\n                    return response.status(401).send(\"Invalid authorization token\");\r\n                }\r\n                request.decodedToken = decodedToken;\r\n                next();\r\n            });\r\n        } else {\r\n            next();\r\n        }\r\n    } else {\r\n        next();\r\n    }\r\n});<\/pre>\n<p>So what are we doing in the above code?<\/p>\n<p>Since we&#8217;re using <code>app.use<\/code>, on every request, this function will be called. When this function is called, we look at the current request headers and look for an authorization header. If an authorization header exists, we make sure it is a bearer token and use the actual token value in our verification. The actual token is our JWT. If the token is valid, we can add the decoded value to the request which then becomes accessible in the next stage of our request. If no token is present, no worries because nothing will happen. Our logic only checks our tokens if they exist because not all data points will be protected.<\/p>\n<p>Are there better ways to obtain our JWT token in a request and validate it? Probably, but the above code worked when I tested it out and it wasn&#8217;t too complicated.<\/p>\n<h2>Developing a partially protected API with GraphQL and JavaScript<\/h2>\n<p>Now that we have the JWT logic in place, we can focus on the development of our API. Technically the <code>\/login<\/code> and <code>\/register<\/code> endpoints are part of our API, but the focus is GraphQL.<\/p>\n<p>Before we worry about the queries, let&#8217;s focus on our GraphQL objects:<\/p>\n<pre class=\"lang:default decode:true \">const AccountType = new GraphQLObjectType({\r\n    name: \"Account\",\r\n    fields: {\r\n        id: { type: GraphQLID },\r\n        username: { type: GraphQLString },\r\n        password: { type: GraphQLString }\r\n    }\r\n});\r\n\r\nconst CourseType = new GraphQLObjectType({\r\n    name: \"Course\",\r\n    fields: {\r\n        id: { type: GraphQLID },\r\n        title: { type: GraphQLString },\r\n        length: { type: GraphQLString },\r\n        author: {\r\n            type: AccountType\r\n        }\r\n    }\r\n});<\/pre>\n<p>Remember, if you saw my <a href=\"https:\/\/www.couchbase.com\/blog\/creating-a-graphql-application-with-node-js-and-a-nosql-database\/\" target=\"_blank\" rel=\"noopener noreferrer\">previous Couchbase with GraphQL tutorial<\/a>, the objects above probably look a little different. This is because I modeled them after my <a href=\"https:\/\/www.thepolyglotdeveloper.com\/2018\/05\/getting-started-graphql-development-nodejs\/\" target=\"_blank\" rel=\"noopener noreferrer\">alternative GraphQL tutorial<\/a>. Essentially, we have two objects where one is for account data and the other is for course data. Maybe not the best example, but we&#8217;ll make it work.<\/p>\n<p>The course data will reference an account for the course author. We&#8217;ll be creating a resolver method for author information, but not yet. Let&#8217;s first create a query for account data separately:<\/p>\n<pre class=\"lang:default decode:true \">const schema = new GraphQLSchema({\r\n    query: new GraphQLObjectType({\r\n        name: 'Query',\r\n        fields: {\r\n            account: {\r\n                type: AccountType,\r\n                resolve: (root, args, context, info) =&gt; {\r\n                    return new Promise((resolve, reject) =&gt; {\r\n                        if(!context.decodedToken) {\r\n                            return reject(\"A valid authorization token is required\");\r\n                        }\r\n                        var statement = \"SELECT META(account).id, account.username, account.`password` FROM `\" + bucket._name + \"` AS account WHERE account.type = 'account' AND META(account).id = $id\";\r\n                        var query = Couchbase.N1qlQuery.fromString(statement);\r\n                        bucket.query(query, { \"id\": context.decodedToken }, (error, result) =&gt; {\r\n                            if(error) {\r\n                                return reject(error.message);\r\n                            }\r\n                            resolve(result[0]);\r\n                        });\r\n                    });\r\n                }\r\n            }\r\n        }\r\n    })\r\n});<\/pre>\n<p>It only makes sense that when we have a query like <code>account<\/code>, we want to get data for a particular account and that should probably be our own account. If we&#8217;re querying our own account, we should probably have a valid JWT.<\/p>\n<p>Notice how we&#8217;re using <code>context.decodeToken<\/code> in the above code. The <code>context<\/code> allows us to get data from the request and in our case, the decoded token data might exist in the request. If it doesn&#8217;t exist, we should probably throw an error because a valid token is a requirement for this query.<\/p>\n<p>If we have a valid token, we can create a N1QL query and use the user id to query for our account and return it.<\/p>\n<p>Not bad right?<\/p>\n<p>Let&#8217;s expand on our queries. Within the <code>fields<\/code> object, we&#8217;re going to add another query, but this time we&#8217;ll be querying for course data and course data won&#8217;t necessarily be protected.<\/p>\n<pre class=\"lang:default decode:true \">courses: {\r\n    type: GraphQLList(CourseType),\r\n    resolve: (root, args, context, info) =&gt; {\r\n        return new Promise((resolve, reject) =&gt; {\r\n            var statement = \"SELECT META(course).id, course.title, course.length, course.author FROM `\" + bucket._name + \"` AS course WHERE course.type = 'course'\";\r\n            var query = Couchbase.N1qlQuery.fromString(statement);\r\n            bucket.query(query, (error, result) =&gt; {\r\n                if(error) {\r\n                    return reject(error.message);\r\n                }\r\n                resolve(result);\r\n            });\r\n        });\r\n    }\r\n}<\/pre>\n<p>In the above code, we are doing a simple N1QL query for all courses stored in the database. The catch here is that for author data, we&#8217;re only obtaining the key, not the fully loaded account data which is protected.<\/p>\n<p>We&#8217;re actually going to do some data manipulations in the GraphQL object for <code>CourseType<\/code> instead:<\/p>\n<pre class=\"lang:default decode:true \">const CourseType = new GraphQLObjectType({\r\n    name: \"Course\",\r\n    fields: {\r\n        id: { type: GraphQLID },\r\n        title: { type: GraphQLString },\r\n        length: { type: GraphQLString },\r\n        author: {\r\n            type: AccountType,\r\n            resolve: (root, args, context, info) =&gt; {\r\n                return new Promise((resolve, reject) =&gt; {\r\n                    if(!context.decodedToken || context.decodedToken != root.author) {\r\n                        return reject(\"A valid authorization token is required\");\r\n                    }\r\n                    var statement = \"SELECT META(account).id, account.username, account.`password` FROM `\" + bucket._name + \"` AS account WHERE account.type = 'account' AND META(account).id = $id\";\r\n                    var query = Couchbase.N1qlQuery.fromString(statement);\r\n                    bucket.query(query, { \"id\": root.author }, (error, result) =&gt; {\r\n                        if(error) {\r\n                            return reject({ code: error.code, message: error.message });\r\n                        }\r\n                        resolve(result[0]);\r\n                    });\r\n                });\r\n            }\r\n        }\r\n    }\r\n});<\/pre>\n<p>Notice that we now have a <code>resolve<\/code> function on the <code>author<\/code> property. In this function, we check for a valid token and if we don&#8217;t find one, we return an error. This check and error only happens if the <code>author<\/code> data is requested. If the query does not request <code>author<\/code> data, we can get the other information without a token since it is not protected.<\/p>\n<p>There is another catch here. Not only are we checking to make sure a valid JWT is present, but we also want the JWT to match the data returned in the N1QL query. This means if we have several authors, only the authors we have permission for will succeed. Again, not the best example, but it proves our point.<\/p>\n<p>To clean up any loose ends, we need to update our <code>\/graphql<\/code> endpoint:<\/p>\n<pre class=\"lang:default decode:true \">app.use(\"\/graphql\", ExpressGraphQL({\r\n    schema: schema,\r\n    graphiql: true\r\n}));<\/pre>\n<p>All we&#8217;ve done is add our <code>schema<\/code> which includes our two possible queries.<\/p>\n<h2>Conclusion<\/h2>\n<p>While our example was simple, it allowed us to demonstrated protected queries and pieces of data with GraphQL, <a href=\"https:\/\/www.couchbase.com\" target=\"_blank\" rel=\"noopener noreferrer\">Couchbase<\/a>, and JSON web tokens (JWT). Some core things to remember:<\/p>\n<ol>\n<li>Request data can be accessed in the GraphQL <code>context<\/code> variable.<\/li>\n<li>JSON web tokens and accounts should probably be created through separate endpoints rather than with GraphQL mutations.<\/li>\n<li>You can restrict queries as well as data properties with JWT. It is not an all or nothing series of events.<\/li>\n<\/ol>\n<p>If you want to learn more about GraphQL, I suggest you check out my <a href=\"https:\/\/www.couchbase.com\/blog\/creating-a-graphql-application-with-node-js-and-a-nosql-database\/\" target=\"_blank\" rel=\"noopener noreferrer\">previous tutorial<\/a> on the subject. To learn more about Couchbase with Node.js, check out the <a href=\"https:\/\/www.couchbase.com\/developers\/\" target=\"_blank\" rel=\"noopener noreferrer\">Couchbase Developer Portal<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>A few months ago when I had first started learning about GraphQL, I had written a previous tutorial for using it with Couchbase and Node.js. The tutorial focused on the basics which included creating GraphQL objects and querying those objects [&hellip;]<\/p>\n","protected":false},"author":63,"featured_media":13873,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"inline_featured_image":false,"footnotes":""},"categories":[1814,1815,1816,1822,1813,1812],"tags":[1393,1261,2251],"ppma_author":[9032],"class_list":["post-5359","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-application-design","category-best-practices-and-tutorials","category-couchbase-server","category-node-js","category-security","category-n1ql-query","tag-api","tag-json","tag-jwt"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v25.9 (Yoast SEO v25.9) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>JWT Authentication with GraphQL, Node.js &amp; Couchbase NoSQL<\/title>\n<meta name=\"description\" content=\"Learn to protect specific data elements of your GraphQL powered API that uses the NoSQL database, Couchbase Server, and Node.js using JSON Web Tokens (JWT).\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.couchbase.com\/blog\/jwt-authentication-with-graphql-node-js-and-couchbase-nosql\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"JWT Authentication with GraphQL, Node.js &amp; Couchbase NoSQL\" \/>\n<meta property=\"og:description\" content=\"Learn to protect specific data elements of your GraphQL powered API that uses the NoSQL database, Couchbase Server, and Node.js using JSON Web Tokens (JWT).\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.couchbase.com\/blog\/jwt-authentication-with-graphql-node-js-and-couchbase-nosql\/\" \/>\n<meta property=\"og:site_name\" content=\"The Couchbase Blog\" \/>\n<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/thepolyglotdeveloper\" \/>\n<meta property=\"article:published_time\" content=\"2018-06-28T14:00:12+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-06-14T01:32:52+00:00\" \/>\n<meta name=\"author\" content=\"Nic Raboy, Developer Advocate, Couchbase\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@nraboy\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Nic Raboy, Developer Advocate, Couchbase\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"8 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/jwt-authentication-with-graphql-node-js-and-couchbase-nosql\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/jwt-authentication-with-graphql-node-js-and-couchbase-nosql\/\"},\"author\":{\"name\":\"Nic Raboy, Developer Advocate, Couchbase\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/bb545ebe83bb2d12f91095811d0a72e1\"},\"headline\":\"JWT Authentication with GraphQL, Node.js &amp; Couchbase NoSQL\",\"datePublished\":\"2018-06-28T14:00:12+00:00\",\"dateModified\":\"2025-06-14T01:32:52+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/jwt-authentication-with-graphql-node-js-and-couchbase-nosql\/\"},\"wordCount\":1696,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/jwt-authentication-with-graphql-node-js-and-couchbase-nosql\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png\",\"keywords\":[\"API\",\"JSON\",\"jwt\"],\"articleSection\":[\"Application Design\",\"Best Practices and Tutorials\",\"Couchbase Server\",\"Node.js\",\"Security\",\"SQL++ \/ N1QL Query\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.couchbase.com\/blog\/jwt-authentication-with-graphql-node-js-and-couchbase-nosql\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/jwt-authentication-with-graphql-node-js-and-couchbase-nosql\/\",\"url\":\"https:\/\/www.couchbase.com\/blog\/jwt-authentication-with-graphql-node-js-and-couchbase-nosql\/\",\"name\":\"JWT Authentication with GraphQL, Node.js &amp; Couchbase NoSQL\",\"isPartOf\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/jwt-authentication-with-graphql-node-js-and-couchbase-nosql\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/jwt-authentication-with-graphql-node-js-and-couchbase-nosql\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png\",\"datePublished\":\"2018-06-28T14:00:12+00:00\",\"dateModified\":\"2025-06-14T01:32:52+00:00\",\"description\":\"Learn to protect specific data elements of your GraphQL powered API that uses the NoSQL database, Couchbase Server, and Node.js using JSON Web Tokens (JWT).\",\"breadcrumb\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/jwt-authentication-with-graphql-node-js-and-couchbase-nosql\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.couchbase.com\/blog\/jwt-authentication-with-graphql-node-js-and-couchbase-nosql\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/jwt-authentication-with-graphql-node-js-and-couchbase-nosql\/#primaryimage\",\"url\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png\",\"contentUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png\",\"width\":1800,\"height\":630},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/jwt-authentication-with-graphql-node-js-and-couchbase-nosql\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.couchbase.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"JWT Authentication with GraphQL, Node.js &amp; Couchbase NoSQL\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#website\",\"url\":\"https:\/\/www.couchbase.com\/blog\/\",\"name\":\"The Couchbase Blog\",\"description\":\"Couchbase, the NoSQL Database\",\"publisher\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.couchbase.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\",\"name\":\"The Couchbase Blog\",\"url\":\"https:\/\/www.couchbase.com\/blog\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png\",\"contentUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png\",\"width\":218,\"height\":34,\"caption\":\"The Couchbase Blog\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/bb545ebe83bb2d12f91095811d0a72e1\",\"name\":\"Nic Raboy, Developer Advocate, Couchbase\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/image\/8863514d8bed0cf6080f23db40e00354\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/bedeb68368d4681aca4c74fe5f697f0c423b80d498ec50fd915ba018b72c101f?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/bedeb68368d4681aca4c74fe5f697f0c423b80d498ec50fd915ba018b72c101f?s=96&d=mm&r=g\",\"caption\":\"Nic Raboy, Developer Advocate, Couchbase\"},\"description\":\"Nic Raboy is an advocate of modern web and mobile development technologies. He has experience in Java, JavaScript, Golang and a variety of frameworks such as Angular, NativeScript, and Apache Cordova. Nic writes about his development experiences related to making web and mobile development easier to understand.\",\"sameAs\":[\"https:\/\/www.thepolyglotdeveloper.com\",\"https:\/\/www.facebook.com\/thepolyglotdeveloper\",\"https:\/\/x.com\/nraboy\"],\"url\":\"https:\/\/www.couchbase.com\/blog\/author\/nic-raboy-2\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"JWT Authentication with GraphQL, Node.js &amp; Couchbase NoSQL","description":"Learn to protect specific data elements of your GraphQL powered API that uses the NoSQL database, Couchbase Server, and Node.js using JSON Web Tokens (JWT).","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:\/\/www.couchbase.com\/blog\/jwt-authentication-with-graphql-node-js-and-couchbase-nosql\/","og_locale":"en_US","og_type":"article","og_title":"JWT Authentication with GraphQL, Node.js &amp; Couchbase NoSQL","og_description":"Learn to protect specific data elements of your GraphQL powered API that uses the NoSQL database, Couchbase Server, and Node.js using JSON Web Tokens (JWT).","og_url":"https:\/\/www.couchbase.com\/blog\/jwt-authentication-with-graphql-node-js-and-couchbase-nosql\/","og_site_name":"The Couchbase Blog","article_author":"https:\/\/www.facebook.com\/thepolyglotdeveloper","article_published_time":"2018-06-28T14:00:12+00:00","article_modified_time":"2025-06-14T01:32:52+00:00","author":"Nic Raboy, Developer Advocate, Couchbase","twitter_card":"summary_large_image","twitter_creator":"@nraboy","twitter_misc":{"Written by":"Nic Raboy, Developer Advocate, Couchbase","Est. reading time":"8 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.couchbase.com\/blog\/jwt-authentication-with-graphql-node-js-and-couchbase-nosql\/#article","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/jwt-authentication-with-graphql-node-js-and-couchbase-nosql\/"},"author":{"name":"Nic Raboy, Developer Advocate, Couchbase","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/bb545ebe83bb2d12f91095811d0a72e1"},"headline":"JWT Authentication with GraphQL, Node.js &amp; Couchbase NoSQL","datePublished":"2018-06-28T14:00:12+00:00","dateModified":"2025-06-14T01:32:52+00:00","mainEntityOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/jwt-authentication-with-graphql-node-js-and-couchbase-nosql\/"},"wordCount":1696,"commentCount":0,"publisher":{"@id":"https:\/\/www.couchbase.com\/blog\/#organization"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/jwt-authentication-with-graphql-node-js-and-couchbase-nosql\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","keywords":["API","JSON","jwt"],"articleSection":["Application Design","Best Practices and Tutorials","Couchbase Server","Node.js","Security","SQL++ \/ N1QL Query"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.couchbase.com\/blog\/jwt-authentication-with-graphql-node-js-and-couchbase-nosql\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.couchbase.com\/blog\/jwt-authentication-with-graphql-node-js-and-couchbase-nosql\/","url":"https:\/\/www.couchbase.com\/blog\/jwt-authentication-with-graphql-node-js-and-couchbase-nosql\/","name":"JWT Authentication with GraphQL, Node.js &amp; Couchbase NoSQL","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/jwt-authentication-with-graphql-node-js-and-couchbase-nosql\/#primaryimage"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/jwt-authentication-with-graphql-node-js-and-couchbase-nosql\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","datePublished":"2018-06-28T14:00:12+00:00","dateModified":"2025-06-14T01:32:52+00:00","description":"Learn to protect specific data elements of your GraphQL powered API that uses the NoSQL database, Couchbase Server, and Node.js using JSON Web Tokens (JWT).","breadcrumb":{"@id":"https:\/\/www.couchbase.com\/blog\/jwt-authentication-with-graphql-node-js-and-couchbase-nosql\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.couchbase.com\/blog\/jwt-authentication-with-graphql-node-js-and-couchbase-nosql\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.couchbase.com\/blog\/jwt-authentication-with-graphql-node-js-and-couchbase-nosql\/#primaryimage","url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","contentUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","width":1800,"height":630},{"@type":"BreadcrumbList","@id":"https:\/\/www.couchbase.com\/blog\/jwt-authentication-with-graphql-node-js-and-couchbase-nosql\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.couchbase.com\/blog\/"},{"@type":"ListItem","position":2,"name":"JWT Authentication with GraphQL, Node.js &amp; Couchbase NoSQL"}]},{"@type":"WebSite","@id":"https:\/\/www.couchbase.com\/blog\/#website","url":"https:\/\/www.couchbase.com\/blog\/","name":"The Couchbase Blog","description":"Couchbase, the NoSQL Database","publisher":{"@id":"https:\/\/www.couchbase.com\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.couchbase.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.couchbase.com\/blog\/#organization","name":"The Couchbase Blog","url":"https:\/\/www.couchbase.com\/blog\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png","contentUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png","width":218,"height":34,"caption":"The Couchbase Blog"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/bb545ebe83bb2d12f91095811d0a72e1","name":"Nic Raboy, Developer Advocate, Couchbase","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/image\/8863514d8bed0cf6080f23db40e00354","url":"https:\/\/secure.gravatar.com\/avatar\/bedeb68368d4681aca4c74fe5f697f0c423b80d498ec50fd915ba018b72c101f?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/bedeb68368d4681aca4c74fe5f697f0c423b80d498ec50fd915ba018b72c101f?s=96&d=mm&r=g","caption":"Nic Raboy, Developer Advocate, Couchbase"},"description":"Nic Raboy is an advocate of modern web and mobile development technologies. He has experience in Java, JavaScript, Golang and a variety of frameworks such as Angular, NativeScript, and Apache Cordova. Nic writes about his development experiences related to making web and mobile development easier to understand.","sameAs":["https:\/\/www.thepolyglotdeveloper.com","https:\/\/www.facebook.com\/thepolyglotdeveloper","https:\/\/x.com\/nraboy"],"url":"https:\/\/www.couchbase.com\/blog\/author\/nic-raboy-2\/"}]}},"authors":[{"term_id":9032,"user_id":63,"is_guest":0,"slug":"nic-raboy-2","display_name":"Nic Raboy, Developer Advocate, Couchbase","avatar_url":"https:\/\/secure.gravatar.com\/avatar\/bedeb68368d4681aca4c74fe5f697f0c423b80d498ec50fd915ba018b72c101f?s=96&d=mm&r=g","author_category":"","last_name":"Raboy","first_name":"Nic","job_title":"","user_url":"https:\/\/www.thepolyglotdeveloper.com","description":"Nic Raboy is an advocate of modern web and mobile development technologies. He has experience in Java, JavaScript, Golang and a variety of frameworks such as Angular, NativeScript, and Apache Cordova. Nic writes about his development experiences related to making web and mobile development easier to understand."}],"_links":{"self":[{"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/posts\/5359","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/users\/63"}],"replies":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/comments?post=5359"}],"version-history":[{"count":0,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/posts\/5359\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/media\/13873"}],"wp:attachment":[{"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/media?parent=5359"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/categories?post=5359"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/tags?post=5359"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/ppma_author?post=5359"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}