{"id":97,"date":"2014-12-16T19:32:04","date_gmt":"2014-12-16T19:32:03","guid":{"rendered":"https:\/\/www.couchbase.com\/blog\/game-servers-and-couchbase-nodejs-part-2\/"},"modified":"2014-12-16T19:32:04","modified_gmt":"2014-12-16T19:32:03","slug":"game-servers-and-couchbase-nodejs-part-2","status":"publish","type":"post","link":"https:\/\/www.couchbase.com\/blog\/pt\/game-servers-and-couchbase-nodejs-part-2\/","title":{"rendered":"Game Servers and Couchbase with Node.js &#8211; Part 2"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">In this part of the series, we will be implementing session management and authenticated endpoints (endpoints that require you to be logged in). Lets get started!<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If you have yet to read <a href=\"https:\/\/www.couchbase.com\/blog\/game-servers-and-couchbase-nodejs-part-1\/\">Part 1<\/a> of this series, I suggest you do as it sets up the basic project layout as well as basic user management and is a prerequisit to Part 2!<\/p>\n\n\n\n<h1 class=\"wp-block-heading\">Session Management &#8211; The Model<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">The first step towards building our session management endpoints is setting up a model to use from these endpoints for manipulating the database. Unlike the account model, this model does not need referential documents or any complicated logic and thus is fairly simple. The first step is importing the various modules we will need, as well as getting a reference to our database connection from our database module.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><span>var<\/span> db <span>=<\/span> require<span>(<\/span><span>&#8216;.\/..\/database&#8217;<\/span><span>)<\/span>.<span>mainBucket<\/span><span>;<\/span><br>\n<span>var<\/span> couchbase <span>=<\/span> require<span>(<\/span><span>&#8216;couchbase&#8217;<\/span><span>)<\/span><span>;<\/span><br>\n<span>var<\/span> uuid <span>=<\/span> require<span>(<\/span><span>&#8216;uuid&#8217;<\/span><span>)<\/span><span>;<\/span><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Next, again similar to our account model, we build a small function for stripping away our database properties. &#8216;type&#8217; is the only one we need to remove in this case as well.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><span>function<\/span> cleanSessionObj<span>(<\/span>obj<span>)<\/span> <span>{<\/span><br>\n<span>delete<\/span> obj.<span>type<\/span><span>;<\/span><br>\n<span>return<\/span> obj<span>;<\/span><br>\n<span>}<\/span><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Now lets start working on the session model class itself. First comes our blank constructor. I&#8217;d like to mention at this point that our model classes are currently entirely static in this example, but a good practice to follow is returning your model classes from the static CRUD operations, we just are not at the point that this would be helpful yet.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><span>function<\/span> SessionModel<span>(<\/span><span>)<\/span> <span>{<\/span><br>\n<span>}<\/span><br>\nmodule.<span>exports<\/span> <span>=<\/span> SessionModel<span>;<\/span><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Now for our first session model function that will actually do any work.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">SessionModel.<span>create<\/span> <span>=<\/span> <span>function<\/span><span>(<\/span>uid<span>,<\/span> callback<span>)<\/span> <span>{<\/span><br>\n<span>}<\/span><span>;<\/span><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">And inside that function we need to create our document we will be inserting and its associated key (we only store the uid, and then access the users remaining information directly from their account document through our account model, which you will see later.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><span>var<\/span> sessDoc <span>=<\/span> <span>{<\/span><br>\ntype<span>:<\/span> <span>&#8216;session&#8217;<\/span><span>,<\/span><br>\nsid<span>:<\/span> uuid.<span>v4<\/span><span>(<\/span><span>)<\/span><span>,<\/span><br>\nuid<span>:<\/span> uid<br>\n<span>}<\/span><span>;<\/span><br>\n<span>var<\/span> sessDocName <span>=<\/span> <span>&#8216;sess-&#8216;<\/span> <span>+<\/span> sessDoc.<span>sid<\/span><span>;<\/span><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Then we store our newly created session document to our cluster. You will also notice that we call our sanitization function from above here, as well as setting an expiry value of 60 minutes. This will cause the cluster to &#8216;expire&#8217; the session by removing it after that amount of time.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">db.<span>add<\/span><span>(<\/span>sessDocName<span>,<\/span> sessDoc<span>,<\/span> <span>{<\/span>expiry<span>:<\/span> <span>3600<\/span><span>}<\/span><span>,<\/span> <span>function<\/span><span>(<\/span>err<span>,<\/span> result<span>)<\/span> <span>{<\/span><br>\ncallback<span>(<\/span>err<span>,<\/span> cleanSessionObj<span>(<\/span>sessDoc<span>)<\/span><span>,<\/span> result.<span>cas<\/span><span>)<\/span><span>;<\/span><br>\n<span>}<\/span><span>)<\/span><span>;<\/span><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Next we need to build a function on our model that allows us to retrieve session information that we have previous stored. To do this, we generate a key matching the one we would have stored, and then execute a get request, returning the users uid from the session to our callback.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">SessionModel.<span>get<\/span> <span>=<\/span> <span>function<\/span><span>(<\/span>sid<span>,<\/span> callback<span>)<\/span> <span>{<\/span><br>\n<span>var<\/span> sessDocName <span>=<\/span> <span>&#8216;sess-&#8216;<\/span> <span>+<\/span> sid<span>;<\/span>db.<span>get<\/span><span>(<\/span>sessDocName<span>,<\/span> <span>function<\/span><span>(<\/span>err<span>,<\/span> result<span>)<\/span> <span>{<\/span><br>\n<span>if<\/span> <span>(<\/span>err<span>)<\/span> <span>{<\/span><br>\n<span>return<\/span> callback<span>(<\/span>err<span>)<\/span><span>;<\/span><br>\n<span>}<\/span>\n<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">callback<span>(<\/span><span>null<\/span><span>,<\/span> result.<span>value<\/span>.<span>uid<\/span><span>)<\/span><span>;<\/span><br>\n<span>}<\/span><span>)<\/span><span>;<\/span><br>\n<span>}<\/span><span>;<\/span><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">And here is the finalized sessionmodel.js:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><span>var<\/span> db <span>=<\/span> require<span>(<\/span><span>&#8216;.\/..\/database&#8217;<\/span><span>)<\/span>.<span>mainBucket<\/span><span>;<\/span><br>\n<span>var<\/span> couchbase <span>=<\/span> require<span>(<\/span><span>&#8216;couchbase&#8217;<\/span><span>)<\/span><span>;<\/span><br>\n<span>var<\/span> uuid <span>=<\/span> require<span>(<\/span><span>&#8216;uuid&#8217;<\/span><span>)<\/span><span>;<\/span><span>function<\/span> cleanSessionObj<span>(<\/span>obj<span>)<\/span> <span>{<\/span><br>\n<span>delete<\/span> obj.<span>type<\/span><span>;<\/span><br>\n<span>return<\/span> obj<span>;<\/span><br>\n<span>}<\/span>\n<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><span>function<\/span> SessionModel<span>(<\/span><span>)<\/span> <span>{<\/span><br>\n<span>}<\/span><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">SessionModel.<span>create<\/span> <span>=<\/span> <span>function<\/span><span>(<\/span>uid<span>,<\/span> callback<span>)<\/span> <span>{<\/span><br>\n<span>var<\/span> sessDoc <span>=<\/span> <span>{<\/span><br>\ntype<span>:<\/span> <span>&#8216;session&#8217;<\/span><span>,<\/span><br>\nsid<span>:<\/span> uuid.<span>v4<\/span><span>(<\/span><span>)<\/span><span>,<\/span><br>\nuid<span>:<\/span> uid<br>\n<span>}<\/span><span>;<\/span><br>\n<span>var<\/span> sessDocName <span>=<\/span> <span>&#8216;sess-&#8216;<\/span> <span>+<\/span> sessDoc.<span>sid<\/span><span>;<\/span><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">db.<span>add<\/span><span>(<\/span>sessDocName<span>,<\/span> sessDoc<span>,<\/span> <span>{<\/span>expiry<span>:<\/span> <span>3600<\/span><span>}<\/span><span>,<\/span> <span>function<\/span><span>(<\/span>err<span>,<\/span> result<span>)<\/span> <span>{<\/span><br>\ncallback<span>(<\/span>err<span>,<\/span> cleanSessionObj<span>(<\/span>sessDoc<span>)<\/span><span>,<\/span> result.<span>cas<\/span><span>)<\/span><span>;<\/span><br>\n<span>}<\/span><span>)<\/span><span>;<\/span><br>\n<span>}<\/span><span>;<\/span><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">SessionModel.<span>get<\/span> <span>=<\/span> <span>function<\/span><span>(<\/span>sid<span>,<\/span> callback<span>)<\/span> <span>{<\/span><br>\n<span>var<\/span> sessDocName <span>=<\/span> <span>&#8216;sess-&#8216;<\/span> <span>+<\/span> sid<span>;<\/span><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">db.<span>get<\/span><span>(<\/span>sessDocName<span>,<\/span> <span>function<\/span><span>(<\/span>err<span>,<\/span> result<span>)<\/span> <span>{<\/span><br>\n<span>if<\/span> <span>(<\/span>err<span>)<\/span> <span>{<\/span><br>\n<span>return<\/span> callback<span>(<\/span>err<span>)<\/span><span>;<\/span><br>\n<span>}<\/span><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">callback<span>(<\/span><span>null<\/span><span>,<\/span> result.<span>value<\/span>.<span>uid<\/span><span>)<\/span><span>;<\/span><br>\n<span>}<\/span><span>)<\/span><span>;<\/span><br>\n<span>}<\/span><span>;<\/span><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">module.<span>exports<\/span> <span>=<\/span> SessionModel<span>;<\/span><\/p>\n\n\n\n<h1 class=\"wp-block-heading\">Session Management &#8211; Account Lookup<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">Before we can start writing our request handler itself, we need to build a method that will allow us to lookup a user based on their username. We don&#8217;t really want users to have to remember their uid&#8217;s! In part 1 we built our account model in accountmodel.js. Lets go back to that file and add a new method.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">AccountModel.<span>getByUsername<\/span> <span>=<\/span> <span>function<\/span><span>(<\/span>username<span>,<\/span> callback<span>)<\/span> <span>{<\/span><br>\n<span>}<\/span><span>;<\/span><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">How we handle this method is that we will build a key using the provided username that will search for one of the referential documents we created in `AccountModel.create`. If we are not able to locate this referential document, we assume that the user does not exist and return an error. If the username is able to be located, and we find the referential document, we then execute a `AccountModel.get` to locate the user document itself, and forward the callback through there. This means that calls to `AccountModel.getByUsername` will return the full user object as if you had directly called `AccountModel.get` with the uid.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Here is the whole function:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">AccountModel.<span>getByUsername<\/span> <span>=<\/span> <span>function<\/span><span>(<\/span>username<span>,<\/span> callback<span>)<\/span> <span>{<\/span><br>\n<span>var<\/span> refdocName <span>=<\/span> <span>&#8216;username-&#8216;<\/span> <span>+<\/span> username<span>;<\/span><br>\ndb.<span>get<\/span><span>(<\/span>refdocName<span>,<\/span> <span>function<\/span><span>(<\/span>err<span>,<\/span> result<span>)<\/span> <span>{<\/span><br>\n<span>if<\/span> <span>(<\/span>err <span>&amp;&amp;<\/span> err.<span>code<\/span> <span>===<\/span> couchbase.<span>errors<\/span>.<span>keyNotFound<\/span><span>)<\/span> <span>{<\/span><br>\n<span>return<\/span> callback<span>(<\/span><span>&#8216;Username not found&#8217;<\/span><span>)<\/span><span>;<\/span><br>\n<span>}<\/span> <span>else<\/span> <span>if<\/span> <span>(<\/span>err<span>)<\/span> <span>{<\/span><br>\n<span>return<\/span> callback<span>(<\/span>err<span>)<\/span><span>;<\/span><br>\n<span>}<\/span><span>\/\/ Extract the UID we found<\/span><br>\n<span>var<\/span> foundUid <span>=<\/span> result.<span>value<\/span>.<span>uid<\/span><span>;<\/span>\n<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><span>\/\/ Forward to a normal get<\/span><br>\nAccountModel.<span>get<\/span><span>(<\/span>foundUid<span>,<\/span> callback<span>)<\/span><span>;<\/span><br>\n<span>}<\/span><span>)<\/span><span>;<\/span><br>\n<span>}<\/span><span>;<\/span><\/p>\n\n\n\n<h1 class=\"wp-block-heading\">Session Management &#8211; Request Handling<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">The last step of enabling session creation is writing the request handler itself. Thankfully, most of the important logic has gone into the sections above, and our request handler simpler forwards information off to each for processing. First we validate our inputs from the user to make sure everything necessary was provided. Next we try to locate the account by the provided username. Next we validate that the password matches what the user provided by hashing the provided password and comparing. And finally we create the session with our newly created session model and return the details to the user. You may notice that the session id is not directly provided to the user, but instead is passed in the header. This is for consistency as the header is also used to authenticate each request later.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">app.<span>post<\/span><span>(<\/span><span>&#8216;\/sessions&#8217;<\/span><span>,<\/span> <span>function<\/span><span>(<\/span>req<span>,<\/span> res<span>,<\/span> next<span>)<\/span> <span>{<\/span><br>\n<span>if<\/span> <span>(<\/span><span>!<\/span>req.<span>body<\/span>.<span>username<\/span><span>)<\/span> <span>{<\/span><br>\n<span>return<\/span> res.<span>send<\/span><span>(<\/span><span>400<\/span><span>,<\/span> <span>&#8216;Must specify a username&#8217;<\/span><span>)<\/span><span>;<\/span><br>\n<span>}<\/span><br>\n<span>if<\/span> <span>(<\/span><span>!<\/span>req.<span>body<\/span>.<span>password<\/span><span>)<\/span> <span>{<\/span><br>\n<span>return<\/span> res.<span>send<\/span><span>(<\/span><span>400<\/span><span>,<\/span> <span>&#8216;Must specify a password&#8217;<\/span><span>)<\/span><span>;<\/span><br>\n<span>}<\/span>accountModel.<span>getByUsername<\/span><span>(<\/span>req.<span>body<\/span>.<span>username<\/span><span>,<\/span> <span>function<\/span><span>(<\/span>err<span>,<\/span> user<span>)<\/span> <span>{<\/span><br>\n<span>if<\/span> <span>(<\/span>err<span>)<\/span> <span>{<\/span><br>\n<span>return<\/span> next<span>(<\/span>err<span>)<\/span><span>;<\/span><br>\n<span>}<\/span>\n<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><span>if<\/span> <span>(<\/span>crypt.<span>sha1<\/span><span>(<\/span>req.<span>body<\/span>.<span>password<\/span><span>)<\/span> <span>!==<\/span> user.<span>password<\/span><span>)<\/span> <span>{<\/span><br>\n<span>return<\/span> res.<span>send<\/span><span>(<\/span><span>400<\/span><span>,<\/span> <span>&#8216;Passwords do not match&#8217;<\/span><span>)<\/span><span>;<\/span><br>\n<span>}<\/span><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">sessionModel.<span>create<\/span><span>(<\/span>user.<span>uid<\/span><span>,<\/span> <span>function<\/span><span>(<\/span>err<span>,<\/span> session<span>)<\/span> <span>{<\/span><br>\n<span>if<\/span> <span>(<\/span>err<span>)<\/span> <span>{<\/span><br>\n<span>return<\/span> next<span>(<\/span>err<span>)<\/span><span>;<\/span><br>\n<span>}<\/span><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">res.<span>setHeader<\/span><span>(<\/span><span>&#8216;Authorization&#8217;<\/span><span>,<\/span> <span>&#8216;Bearer &#8216;<\/span> <span>+<\/span> session.<span>sid<\/span><span>)<\/span><span>;<\/span><\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><span>\/\/ Delete the password for security reasons<\/span><br>\n<span>delete<\/span> user.<span>password<\/span><span>;<\/span><br>\nres.<span>send<\/span><span>(<\/span>user<span>)<\/span><span>;<\/span><br>\n<span>}<\/span><span>)<\/span><span>;<\/span><br>\n<span>}<\/span><span>)<\/span><span>;<\/span><br>\n<span>}<\/span><span>)<\/span><span>;<\/span><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Now that our session creation exists, lets add a method to authenticate the user on a per-request basis. This will check the users session, for now I have placed this in our app.js, however it may be better put in its own separate file later once routes begin being separated into separate files. To authenticate the user, we check the standard HTTP Authorization header, grab the session id from it and then look this up using our session model. If everything goes as plan, we store the newly found user id in the request for later route handlers.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><span>function<\/span> authUser<span>(<\/span>req<span>,<\/span> res<span>,<\/span> next<span>)<\/span> <span>{<\/span><br>\nreq.<span>uid<\/span> <span>=<\/span> <span>null<\/span><span>;<\/span><br>\n<span>if<\/span> <span>(<\/span>req.<span>headers<\/span>.<span>authorization<\/span><span>)<\/span> <span>{<\/span><br>\n<span>var<\/span> authInfo <span>=<\/span> req.<span>headers<\/span>.<span>authorization<\/span>.<span>split<\/span><span>(<\/span><span>&#8216; &#8216;<\/span><span>)<\/span><span>;<\/span><br>\n<span>if<\/span> <span>(<\/span>authInfo<span>[<\/span><span>0<\/span><span>]<\/span> <span>===<\/span> <span>&#8216;Bearer&#8217;<\/span><span>)<\/span> <span>{<\/span><br>\n<span>var<\/span> sid <span>=<\/span> authInfo<span>[<\/span><span>1<\/span><span>]<\/span><span>;<\/span><br>\nsessionModel.<span>get<\/span><span>(<\/span>sid<span>,<\/span> <span>function<\/span><span>(<\/span>err<span>,<\/span> uid<span>)<\/span> <span>{<\/span><br>\n<span>if<\/span> <span>(<\/span>err<span>)<\/span> <span>{<\/span><br>\nnext<span>(<\/span><span>&#8216;Your session id is invalid&#8217;<\/span><span>)<\/span><span>;<\/span><br>\n<span>}<\/span> <span>else<\/span> <span>{<\/span><br>\nreq.<span>uid<\/span> <span>=<\/span> uid<span>;<\/span><br>\nnext<span>(<\/span><span>)<\/span><span>;<\/span><br>\n<span>}<\/span><br>\n<span>}<\/span><span>)<\/span><span>;<\/span><br>\n<span>}<\/span> <span>else<\/span> <span>{<\/span><br>\nnext<span>(<\/span><span>&#8216;Must be authorized to access this endpoint&#8217;<\/span><span>)<\/span><span>;<\/span><br>\n<span>}<\/span><br>\n<span>}<\/span> <span>else<\/span> <span>{<\/span><br>\nnext<span>(<\/span><span>&#8216;Must be authorized to access this endpoint&#8217;<\/span><span>)<\/span><span>;<\/span><br>\n<span>}<\/span><br>\n<span>}<\/span><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Mainly for the purpose of displaying the authUser method in action I implemented a `\/me` endpoint that returns the user document. We simply do a get through the account model based on the uid that was stored into the request by the authInfo handler, and return this to the client, of course stripping away the password first.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">app.<span>get<\/span><span>(<\/span><span>&#8216;\/me&#8217;<\/span><span>,<\/span> authUser<span>,<\/span> <span>function<\/span><span>(<\/span>req<span>,<\/span> res<span>,<\/span> next<span>)<\/span> <span>{<\/span><br>\naccountModel.<span>get<\/span><span>(<\/span>req.<span>uid<\/span><span>,<\/span> <span>function<\/span><span>(<\/span>err<span>,<\/span> user<span>)<\/span> <span>{<\/span><br>\n<span>if<\/span> <span>(<\/span>err<span>)<\/span> <span>{<\/span><br>\n<span>return<\/span> next<span>(<\/span>err<span>)<\/span><span>;<\/span><br>\n<span>}<\/span><span>delete<\/span> user.<span>password<\/span><span>;<\/span><br>\nres.<span>send<\/span><span>(<\/span>user<span>)<\/span><span>;<\/span><br>\n<span>}<\/span><span>)<\/span><span>;<\/span><br>\n<span>}<\/span><span>)<\/span><span>;<\/span>\n<\/p>\n\n\n\n<h1 class=\"wp-block-heading\">Finale<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">At this point you should now be able to create accounts, log into them and request stored information about the user. Here is an example using the user we created in Part 1.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&gt; POST \/sessions<br>\n{<br>\n&#8220;username&#8221;: &#8220;brett19&#8221;,<br>\n&#8220;password&#8221;: &#8220;success!&#8221;<br>\n}<br>\n&lt; 200 OK<br>\nHeader(Authorization): Bearer 0e9dd36c-5e2c-4f0e-9c2c-bffeea72d4f7&gt; GET \/me<br>\nHeader(Authorization): Bearer 0e9dd36c-5e2c-4f0e-9c2c-bffeea72d4f7<br>\n&lt; 200 OK<br>\n{<br>\n&#8220;uid&#8221;: &#8220;b836d211-425c-47de-9faf-5d0adc078edc&#8221;,<br>\n&#8220;name&#8221;: &#8220;Brett Lawson&#8221;,<br>\n&#8220;username&#8221;: &#8220;brett19&#8221;<br>\n}\n<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The full source for this application is available here: <a href=\"https:\/\/github.com\/brett19\/node-gameapi\">https:\/\/github.com\/brett19\/node-gameapi<\/a><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Enjoy! Brett<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In this part of the series, we will be implementing session management and authenticated endpoints (endpoints that require you to be logged in). Lets get started! If you have yet to read Part 1 of this series, I suggest you do as it sets up the basic project layout as well as basic user management [&hellip;]<\/p>\n","protected":false},"author":31,"featured_media":18,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"inline_featured_image":false,"_acf":"","footnotes":""},"categories":[1],"tags":[],"ppma_author":[53],"class_list":["post-97","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorized"],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v27.6 (Yoast SEO v27.6) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>Game Servers and Couchbase with Node.js - Part 2 - The Couchbase Blog<\/title>\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\/pt\/game-servers-and-couchbase-nodejs-part-2\/\" \/>\n<meta property=\"og:locale\" content=\"pt_BR\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Game Servers and Couchbase with Node.js - Part 2\" \/>\n<meta property=\"og:description\" content=\"In this part of the series, we will be implementing session management and authenticated endpoints (endpoints that require you to be logged in). Lets get started! If you have yet to read Part 1 of this series, I suggest you do as it sets up the basic project layout as well as basic user management [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.couchbase.com\/blog\/pt\/game-servers-and-couchbase-nodejs-part-2\/\" \/>\n<meta property=\"og:site_name\" content=\"The Couchbase Blog\" \/>\n<meta property=\"article:published_time\" content=\"2014-12-16T19:32:03+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/5\/2026\/05\/couchbase-nosql-dbaas.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1800\" \/>\n\t<meta property=\"og:image:height\" content=\"630\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Brett Lawson, Principal Software Engineer, Couchbase\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Brett Lawson, Principal Software Engineer, Couchbase\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"7 minutos\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/game-servers-and-couchbase-nodejs-part-2\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/ko\\\/game-servers-and-couchbase-nodejs-part-2\\\/\"},\"author\":{\"name\":\"Brett Lawson, Principal Software Engineer, Couchbase\",\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/#\\\/schema\\\/person\\\/5cfc2fbf25776be2a027a474562be02f\"},\"headline\":\"Game Servers and Couchbase with Node.js &#8211; Part 2\",\"datePublished\":\"2014-12-16T19:32:03+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/ko\\\/game-servers-and-couchbase-nodejs-part-2\\\/\"},\"wordCount\":1386,\"commentCount\":10,\"publisher\":{\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/game-servers-and-couchbase-nodejs-part-2\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/wp-content\\\/uploads\\\/sites\\\/5\\\/2026\\\/05\\\/couchbase-nosql-dbaas.png\",\"articleSection\":[\"Uncategorized\"],\"inLanguage\":\"pt-BR\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/game-servers-and-couchbase-nodejs-part-2\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/ko\\\/game-servers-and-couchbase-nodejs-part-2\\\/\",\"url\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/game-servers-and-couchbase-nodejs-part-2\\\/\",\"name\":\"Game Servers and Couchbase with Node.js - Part 2 - The Couchbase Blog\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/game-servers-and-couchbase-nodejs-part-2\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/game-servers-and-couchbase-nodejs-part-2\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/wp-content\\\/uploads\\\/sites\\\/5\\\/2026\\\/05\\\/couchbase-nosql-dbaas.png\",\"datePublished\":\"2014-12-16T19:32:03+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/game-servers-and-couchbase-nodejs-part-2\\\/#breadcrumb\"},\"inLanguage\":\"pt-BR\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/game-servers-and-couchbase-nodejs-part-2\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"pt-BR\",\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/game-servers-and-couchbase-nodejs-part-2\\\/#primaryimage\",\"url\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/wp-content\\\/uploads\\\/sites\\\/5\\\/2026\\\/05\\\/couchbase-nosql-dbaas.png\",\"contentUrl\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/wp-content\\\/uploads\\\/sites\\\/5\\\/2026\\\/05\\\/couchbase-nosql-dbaas.png\",\"width\":1800,\"height\":630},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/game-servers-and-couchbase-nodejs-part-2\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Game Servers and Couchbase with Node.js &#8211; Part 2\"}]},{\"@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\":\"pt-BR\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/#organization\",\"name\":\"The Couchbase Blog\",\"url\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"pt-BR\",\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/wp-content\\\/uploads\\\/sites\\\/5\\\/2026\\\/06\\\/logo.svg\",\"contentUrl\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/wp-content\\\/uploads\\\/sites\\\/5\\\/2026\\\/06\\\/logo.svg\",\"width\":\"1024\",\"height\":\"1024\",\"caption\":\"The Couchbase Blog\"},\"image\":{\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/#\\\/schema\\\/logo\\\/image\\\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/#\\\/schema\\\/person\\\/5cfc2fbf25776be2a027a474562be02f\",\"name\":\"Brett Lawson, Principal Software Engineer, Couchbase\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"pt-BR\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/6aec1ba24ef7558a248dcde7b7a18b15b06e2885b24b663906a448634066c1c4?s=96&d=mm&r=gee3586f0c112c20e863af447d44dec8f\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/6aec1ba24ef7558a248dcde7b7a18b15b06e2885b24b663906a448634066c1c4?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/6aec1ba24ef7558a248dcde7b7a18b15b06e2885b24b663906a448634066c1c4?s=96&d=mm&r=g\",\"caption\":\"Brett Lawson, Principal Software Engineer, Couchbase\"},\"description\":\"Brett Lawson is a Principal Software Engineer at Couchbase. Brett is responsible for the design and development of the Couchbase Node.js and PHP clients as well as playing a role in the design and development of the C library, libcouchbase.\",\"url\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/pt\\\/author\\\/brett-lawson\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Game Servers and Couchbase with Node.js - Part 2 - The Couchbase Blog","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\/pt\/game-servers-and-couchbase-nodejs-part-2\/","og_locale":"pt_BR","og_type":"article","og_title":"Game Servers and Couchbase with Node.js - Part 2","og_description":"In this part of the series, we will be implementing session management and authenticated endpoints (endpoints that require you to be logged in). Lets get started! If you have yet to read Part 1 of this series, I suggest you do as it sets up the basic project layout as well as basic user management [&hellip;]","og_url":"https:\/\/www.couchbase.com\/blog\/pt\/game-servers-and-couchbase-nodejs-part-2\/","og_site_name":"The Couchbase Blog","article_published_time":"2014-12-16T19:32:03+00:00","og_image":[{"width":1800,"height":630,"url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/5\/2026\/05\/couchbase-nosql-dbaas.png","type":"image\/png"}],"author":"Brett Lawson, Principal Software Engineer, Couchbase","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Brett Lawson, Principal Software Engineer, Couchbase","Est. reading time":"7 minutos"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.couchbase.com\/blog\/game-servers-and-couchbase-nodejs-part-2\/#article","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/ko\/game-servers-and-couchbase-nodejs-part-2\/"},"author":{"name":"Brett Lawson, Principal Software Engineer, Couchbase","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/5cfc2fbf25776be2a027a474562be02f"},"headline":"Game Servers and Couchbase with Node.js &#8211; Part 2","datePublished":"2014-12-16T19:32:03+00:00","mainEntityOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/ko\/game-servers-and-couchbase-nodejs-part-2\/"},"wordCount":1386,"commentCount":10,"publisher":{"@id":"https:\/\/www.couchbase.com\/blog\/#organization"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/game-servers-and-couchbase-nodejs-part-2\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/5\/2026\/05\/couchbase-nosql-dbaas.png","articleSection":["Uncategorized"],"inLanguage":"pt-BR","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.couchbase.com\/blog\/game-servers-and-couchbase-nodejs-part-2\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.couchbase.com\/blog\/ko\/game-servers-and-couchbase-nodejs-part-2\/","url":"https:\/\/www.couchbase.com\/blog\/game-servers-and-couchbase-nodejs-part-2\/","name":"Game Servers and Couchbase with Node.js - Part 2 - The Couchbase Blog","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/game-servers-and-couchbase-nodejs-part-2\/#primaryimage"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/game-servers-and-couchbase-nodejs-part-2\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/5\/2026\/05\/couchbase-nosql-dbaas.png","datePublished":"2014-12-16T19:32:03+00:00","breadcrumb":{"@id":"https:\/\/www.couchbase.com\/blog\/game-servers-and-couchbase-nodejs-part-2\/#breadcrumb"},"inLanguage":"pt-BR","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.couchbase.com\/blog\/game-servers-and-couchbase-nodejs-part-2\/"]}]},{"@type":"ImageObject","inLanguage":"pt-BR","@id":"https:\/\/www.couchbase.com\/blog\/game-servers-and-couchbase-nodejs-part-2\/#primaryimage","url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/5\/2026\/05\/couchbase-nosql-dbaas.png","contentUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/5\/2026\/05\/couchbase-nosql-dbaas.png","width":1800,"height":630},{"@type":"BreadcrumbList","@id":"https:\/\/www.couchbase.com\/blog\/game-servers-and-couchbase-nodejs-part-2\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.couchbase.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Game Servers and Couchbase with Node.js &#8211; Part 2"}]},{"@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":"pt-BR"},{"@type":"Organization","@id":"https:\/\/www.couchbase.com\/blog\/#organization","name":"The Couchbase Blog","url":"https:\/\/www.couchbase.com\/blog\/","logo":{"@type":"ImageObject","inLanguage":"pt-BR","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/5\/2026\/06\/logo.svg","contentUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/5\/2026\/06\/logo.svg","width":"1024","height":"1024","caption":"The Couchbase Blog"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/5cfc2fbf25776be2a027a474562be02f","name":"Brett Lawson, Principal Software Engineer, Couchbase","image":{"@type":"ImageObject","inLanguage":"pt-BR","@id":"https:\/\/secure.gravatar.com\/avatar\/6aec1ba24ef7558a248dcde7b7a18b15b06e2885b24b663906a448634066c1c4?s=96&d=mm&r=gee3586f0c112c20e863af447d44dec8f","url":"https:\/\/secure.gravatar.com\/avatar\/6aec1ba24ef7558a248dcde7b7a18b15b06e2885b24b663906a448634066c1c4?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/6aec1ba24ef7558a248dcde7b7a18b15b06e2885b24b663906a448634066c1c4?s=96&d=mm&r=g","caption":"Brett Lawson, Principal Software Engineer, Couchbase"},"description":"Brett Lawson is a Principal Software Engineer at Couchbase. Brett is responsible for the design and development of the Couchbase Node.js and PHP clients as well as playing a role in the design and development of the C library, libcouchbase.","url":"https:\/\/www.couchbase.com\/blog\/pt\/author\/brett-lawson\/"}]}},"acf":[],"authors":[{"term_id":53,"user_id":31,"is_guest":0,"slug":"brett-lawson","display_name":"Brett Lawson, Principal Software Engineer, Couchbase","avatar_url":"https:\/\/secure.gravatar.com\/avatar\/?s=96&d=mm&r=g","author_category":"","first_name":"Brett","last_name":"Lawson","user_url":"","job_title":"","description":"Brett Lawson is a Principal Software Engineer at Couchbase. Brett is responsible for the design and development of the Couchbase Node.js and PHP clients as well as playing a role in the design and development of the C library, libcouchbase."}],"_links":{"self":[{"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/posts\/97","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/users\/31"}],"replies":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/comments?post=97"}],"version-history":[{"count":0,"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/posts\/97\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/media\/18"}],"wp:attachment":[{"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/media?parent=97"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/categories?post=97"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/tags?post=97"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/ppma_author?post=97"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}