{"_id":"learn-json-web-tokens","_rev":"10-6391e12cff174f2c3f95b3e1b27234f7","name":"learn-json-web-tokens","description":"A JSON Web Tokens Tutorial to secure your node.js apps!","dist-tags":{"latest":"1.0.6"},"versions":{"1.0.3":{"name":"learn-json-web-tokens","version":"1.0.3","description":"A JSON Web Tokens Tutorial to secure your node.js apps!","main":"server.js","scripts":{"functional":"istanbul cover ./node_modules/tape/bin/tape ./example/test/functional.js | node_modules/tap-spec/bin/cmd.js","coverage":"istanbul cover ./node_modules/tape/bin/tape ./example/test/functional.js && ./node_modules/.bin/istanbul check-coverage --statements 100 --functions 100 --lines 100 --branches 100","test":"./node_modules/tape/bin/tape ./example/test/integration.js | node_modules/tap-spec/bin/cmd.js","start":"node ./example/server.js","jshint":"./node_modules/jshint/bin/jshint -c .jshintrc --exclude-path .gitignore .","codeclimate":"CODECLIMATE_REPO_TOKEN=3f3e469b51750023cd2f400e639e3f9197917ba68efe8c63a19ae983895c8149 codeclimate ./node_modules/codeclimate-test-reporter/bin/codeclimate.js < ./coverage/lcov.info"},"repository":{"type":"git","url":"https://github.com/nelsonic/learn-json-web-tokens.git"},"keywords":["JSON","Web","Tokens","JWT","Security"],"author":{"name":"@nelsonic","email":"contact.nelsonic@gmail.com","url":"https://github.com/nelsonic"},"license":"ISC","bugs":{"url":"https://github.com/nelsonic/learn-json-web-tokens/issues"},"homepage":"https://github.com/nelsonic/learn-json-web-tokens","dependencies":{"jsonwebtoken":"^5.0.0","level":"^0.18.0"},"devDependencies":{"codeclimate-test-reporter":"0.0.4","istanbul":"^0.3.13","jshint":"^2.6.0","pre-commit":"^1.0.6","request":"^2.53.0","tap-spec":"^3.0.0","tape":"^4.0.0"},"engines":{"node":">= 0.8"},"pre-commit":["jshint","coverage","codeclimate"],"gitHead":"e17e97b2ccde9af32f058a22ff59b8452b32829d","_id":"learn-json-web-tokens@1.0.3","_shasum":"fc08c6757d9b35b4ca28c865579a899e999c55b3","_from":".","_npmVersion":"2.5.1","_nodeVersion":"0.12.1","_npmUser":{"name":"nelsonic","email":"contact.nelsonic@gmail.com"},"maintainers":[{"name":"nelsonic","email":"contact.nelsonic@gmail.com"}],"dist":{"shasum":"fc08c6757d9b35b4ca28c865579a899e999c55b3","tarball":"https://registry.npmjs.org/learn-json-web-tokens/-/learn-json-web-tokens-1.0.3.tgz","integrity":"sha512-8Yh0lAKSNyu1JztKY/L/oYMRIt/8iUX/MM1+KHCzDHZXs0wSrU8o3v1y9ut/JZyyjUjxPwb4rKZP9aKH7TMSvw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIEQOWFvDgSYW03RFWUHrLZQ9t+cdhOz3lzFx8w06sq0yAiEA5mZjWTN2tXh/k9OKvvPfJ2TR31h7RS6Iwx6Xs0pRL+s="}]},"directories":{}},"1.0.4":{"name":"learn-json-web-tokens","version":"1.0.4","description":"A JSON Web Tokens Tutorial to secure your node.js apps!","main":"server.js","scripts":{"functional":"istanbul cover ./node_modules/tape/bin/tape ./example/test/functional.js | tap-spec","coverage":"istanbul cover ./node_modules/tape/bin/tape ./example/test/functional.js && istanbul check-coverage --statements 100 --functions 100 --lines 100 --branches 100","test":"tape ./example/test/integration.js | tap-spec","start":"node ./example/server.js","jshint":"jshint -c .jshintrc --exclude-path .gitignore .","codeclimate":"CODECLIMATE_REPO_TOKEN=38d95ab0f78e69f0c4e1f6c5c8fde7edfcf85d396684eb658b73662154e7b2cc codeclimate ./node_modules/codeclimate-test-reporter/bin/codeclimate.js < ./coverage/lcov.info"},"repository":{"type":"git","url":"git+https://github.com/nelsonic/learn-json-web-tokens.git"},"keywords":["JSON","Web","Tokens","JWT","Security"],"author":{"name":"@nelsonic","email":"contact.nelsonic@gmail.com","url":"https://github.com/nelsonic"},"license":"ISC","bugs":{"url":"https://github.com/nelsonic/learn-json-web-tokens/issues"},"homepage":"https://github.com/nelsonic/learn-json-web-tokens","dependencies":{"jsonwebtoken":"^5.0.4","level":"^1.3.0"},"devDependencies":{"codeclimate-test-reporter":"0.1.0","istanbul":"^0.3.17","jshint":"^2.8.0","pre-commit":"^1.0.10","request":"^2.60.0","tap-spec":"^4.0.2","tape":"^4.0.1"},"engines":{"node":">= 0.8"},"pre-commit":["jshint","coverage","codeclimate"],"gitHead":"f9010f6d35bec3f283ab4d9caacc729948e04fc0","_id":"learn-json-web-tokens@1.0.4","_shasum":"8b449545ec55602eaad695879fc7da119a2f7bca","_from":".","_npmVersion":"2.10.1","_nodeVersion":"0.12.4","_npmUser":{"name":"nelsonic","email":"contact.nelsonic@gmail.com"},"dist":{"shasum":"8b449545ec55602eaad695879fc7da119a2f7bca","tarball":"https://registry.npmjs.org/learn-json-web-tokens/-/learn-json-web-tokens-1.0.4.tgz","integrity":"sha512-Poesd8RatZ6v+Ppk8HjeZOXxTHUHWbbp9ZUd9X7fzOyR4rE1gS9L9LGcaVe5/1/7HcgE/d9lS2P+ufaW4iQD3w==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFokx2m7YWlLYT/W+ts5tSgklJMZa4v3InvbMs8kHRoeAiBn7TIVRPb5Z109gMsvpsCPUqQ3nB89n9c1/CIuHujyeA=="}]},"maintainers":[{"name":"nelsonic","email":"contact.nelsonic@gmail.com"}],"directories":{}},"1.0.6":{"name":"learn-json-web-tokens","version":"1.0.6","description":"A JSON Web Tokens Tutorial to secure your node.js apps!","main":"server.js","scripts":{"functional":"istanbul cover ./node_modules/tape/bin/tape ./example/test/functional.js | tap-spec","coverage":"istanbul cover ./node_modules/tape/bin/tape ./example/test/functional.js && istanbul check-coverage --statements 100 --functions 100 --lines 100 --branches 100","spec":"tape ./example/test/integration.js | tap-spec","test":"istanbul cover ./node_modules/tape/bin/tape ./example/test/functional.js","start":"node ./example/server.js","jshint":"jshint -c .jshintrc --exclude-path .gitignore ."},"repository":{"type":"git","url":"git+https://github.com/dwyl/learn-json-web-tokens.git"},"keywords":["JSON","Web","Tokens","JWT","Security"],"author":{"name":"@nelsonic","email":"contact.nelsonic@gmail.com","url":"https://github.com/nelsonic"},"license":"ISC","bugs":{"url":"https://github.com/dwyl/learn-json-web-tokens/issues"},"homepage":"https://github.com/dwyl/learn-json-web-tokens","dependencies":{"jsonwebtoken":"^8.5.1","level":"^5.0.1"},"devDependencies":{"istanbul":"^0.4.3","jshint":"^2.8.0","pre-commit":"^1.0.10","request":"^2.60.0","tap-spec":"^5.0.0","tape":"^4.0.1"},"engines":{"node":">= 6"},"pre-commit":["jshint","coverage"],"gitHead":"09341fcda4453c035d93e53b1b0344e50462f960","_id":"learn-json-web-tokens@1.0.6","_npmVersion":"6.5.0","_nodeVersion":"11.6.0","_npmUser":{"name":"nelsonic","email":"contact.nelsonic@gmail.com"},"dist":{"integrity":"sha512-BqVGrsM2xVZZjj8kFWQ4AHgu+o1EaFyAlXefm/3RJBH2uBbASt3q78+ziXHTXrKXOiYMJm/lm0MtSIqe+hsaDg==","shasum":"7013176362c15ea487d8471ad8c2df440e507201","tarball":"https://registry.npmjs.org/learn-json-web-tokens/-/learn-json-web-tokens-1.0.6.tgz","fileCount":17,"unpackedSize":61072,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJctGdMCRA9TVsSAnZWagAAVw8P+wfmKnON+DrujOBBcjsT\nglRNUeebA24nTNwkdjY/NNyXBzR0PnQMZOdFh+/kJlogRQOPaTt3Hx5DTfOf\n9sQ+haX2xSeauIPa+jaHxy8RgHGQ4iUEnWPjDN6dyuuWbssbWeEaaE107cpc\nDe4qWTFEAT99pQg1dRtEs7LPC9l1/3IVdLanIzORbCJLTt+qlPX+yN58R0Lv\nor0KQiZFec3GQreIQPQWCyQ5vU2swLVuhVUTpiKpei9oec6q1cc5rS3ujVzR\nyIzwNziA4FIWGjLc26wMGwryS5cz0Mnn1O93OeNpXy2TIQZVxMaVyp1XIkH8\nVZ0Bo+daBCsTWUvMEDl3lmFSjv3aF682uVhNYtSSzt7TlYurLrVPuFgsGx6W\ngh7JLLdXKHcQfmW0f2Li7GiwRkF027yrDo5HGJHjtaV11c1sanWmz4LaeUlX\no19lQl1VfyuBZcvSxv2raKXC1S2811RYXcx23DnN8bP9XOFnQO8H8xKEuGdp\n8Rt4gci8vz7pjUdeKvXHF9+AhmaE7XOWgtSME6QydGtfpYAdr9TdodujAiUt\n8ez09J9Q5FlspJAKdLlORVUe6abprr62/ABz/NVYVRAKQ6RcLqyFiX9yc3m+\nf4Mm+JOl086ELhH0LLvp+sdfHOvYVD1lM1v093W15LF2QP5OZfks6Z/8AVpU\n7IZ4\r\n=Ejeu\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCZS5mUeZ+Q/HUTQmNrYc1MgRNe6S88Y2A/5tE/28tsfQIhAJ+vaclN731ZJpKFe4cBfIL/1HnflnZl3a04GprYkNLC"}]},"maintainers":[{"name":"nelsonic","email":"contact.nelsonic@gmail.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/learn-json-web-tokens_1.0.6_1555326795224_0.43081326169373035"},"_hasShrinkwrap":false}},"readme":"![JWT logo wider](http://i.imgur.com/qDOOu4o.jpg)\n\n# Learn how to use *JSON Web Tokens* (JWT) for *Authentication*\n\n![dilbert fixed the internet](http://i.imgur.com/cNElVof.jpg)\n\nLearn how to use JSON Web Token (JWT) to *secure* your Web and/or Mobile Application!\n\n[![Build Status](https://img.shields.io/travis/dwyl/learn-json-web-tokens/master.svg?style=flat-square)](https://travis-ci.org/dwyl/learn-json-web-tokens)\n[![codecov.io](https://img.shields.io/codecov/c/github/dwyl/learn-json-web-tokens/master.svg?style=flat-square)](http://codecov.io/github/dwyl/learn-json-web-tokens?branch=master)\n[![codeclimate-maintainability](https://img.shields.io/codeclimate/maintainability/dwyl/learn-json-web-tokens.svg?style=flat-square)](https://codeclimate.com/github/dwyl/learn-json-web-tokens/maintainability)\n[![Dependencies Status](https://david-dm.org/dwyl/learn-json-web-tokens/status.svg?style=flat-square)](https://david-dm.org/dwyl/learn-json-web-tokens)\n[![devDependencies Status](https://david-dm.org/dwyl/learn-json-web-tokens/dev-status.svg?style=flat-square)](https://david-dm.org/dwyl/learn-json-web-tokens?type=dev)\n[![contributions welcome](https://img.shields.io/badge/contributions-welcome-brightgreen.svg?style=flat-square)](https://github.com/dwyl/learn-json-web-tokens/issues)\n[![HitCount](http://hits.dwyl.io/dwyl/learn-json-web-tokens.svg)](http://hits.dwyl.io/dwyl/learn-json-web-tokens)\n\n\n## *Why*?\n\nJSON Web Tokens (JWTs) make it *easy* to _**send read-only signed**_ \"_**claims**_\"\nbetween services (*both internal and external to your app/site*).\nClaims are *any* bits of data that you want someone else to be able to *read*\nand/or *verify* but ***not alter***.\n\n\n> **Note**: *If that sounds buzz-wordy, don't worry, it will all become clear in the next 5 mins of reading!*\n\n## What?\n\n> \"***JSON Web Token*** *(JWT) is a compact* ***URL-safe*** *means of\n> representing claims to be transferred between two parties.\n> The claims in a JWT are* ***encoded*** *as a* ***JSON object*** *that is* ***digitally\n> signed*** *using JSON Web Signature (JWS)*.  ~ IETF\n\n###  In *English*\n\nTo identify/authenticate people in your (web/mobile) app,\nput a ***standards-based token*** in the **header** or **url** of the page\n(or API endpoint) which proves the user has logged in and is allowed to\naccess the desired content.\n\nexample: `https://www.yoursite.com/private-content/?token=eyJ0eXAiOiJKV1Qi.eyJrZXkiOi.eUiabuiKv`\n\n> **Note**: if this does not *look* \"secure\" to you,\nscroll down to the \"[***security***](https://github.com/dwyl/learn-json-web-tokens#q-if-i-put-the-jwt-in-the-url-or-header-is-it-secure)\" section.\n\n### What does a JWT *Look* Like?\n\nTokens are a string of \"url safe\" characters which *encode* information.\nTokens have **three components** (separated by periods)\n(shown here on multiple lines for *readability* but used as a single string of text)\n\n```\neyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9           // header\n.eyJrZXkiOiJ2YWwiLCJpYXQiOjE0MjI2MDU0NDV9      // payload\n.eUiabuiKv-8PYk2AkGY4Fb5KMZeorYBLw261JPQD5lM   // signature\n```\n\n#### 1. Header\n\nThe first part of a JWT is an encoded string representation\nof a simple JavaScript object which describes the token along with the hashing algorithm used.\n\n#### 2. Payload\n\nThe second part of the JWT forms the core of the token.\nPayload length is proportional to the amount of data you store in the JWT.\nGeneral rule of thumb is: store the bare minimum in the JWT.\n\n\n#### 3. Signature\n\nThe third, and final, part of the JWT is a signature generated\nbased on the header (part one) and the body (part two) and will be used\nto *verify* that the JWT is valid.\n\n### What are \"Claims\"?\n\nClaims are the predefined **keys** and their **values**:\n\n+ **iss**: issuer of the token\n+ **exp**: the expiration timestamp (reject tokens which have expired). Note: as defined in the spec, this must be in seconds.\n+ **iat**: The time the JWT was issued. Can be used to determine the age of the JWT\n+ **nbf**: \"not before\" is a future time when the token will become active.\n+ **jti**: unique identifier for the JWT. Used to prevent the JWT from being re-used or replayed.\n+ **sub**: subject of the token (rarely used)\n+ **aud**: audience of the token (also rarely used)\n\nSee: http://self-issued.info/docs/draft-ietf-oauth-json-web-token.html#RegisteredClaimName\n\n# Example [![contributions welcome](https://img.shields.io/badge/contributions-welcome-brightgreen.svg?style=flat)](https://github.com/dwyl/learn-json-web-tokens/issues)\n\nLets get stuck in with a simple example.\n(the *full* source is in the **/example** directory)\n\n> TRY it: https://jwt.herokuapp.com/\n\nTo play around with the example you can open it in Gitpod (requires OAuth with GitHub).\n\n[![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io#https://github.com/dwyl/learn-json-web-tokens/blob/master/example/lib/helpers.js)\n\n## Server\n\nUsing the *core* **node.js http** server we create 4 endpoints in **/example/server.js**:\n\n1. **/home** : home page (not essential but its where our **login** form is.)\n2. **/auth** : *authenticate* the visitor (returns error + login form if failed)\n3. **/private** : our restricted content - ***login required*** (valid session token) to see this page\n4. **/logout** : invalidates the token and logs out the user (prevent from re-using old token)\n\nWe have *deliberately* made **server.js** as _simple as possible_ for:\n\n+ Readability\n+ Maintainability\n+ Testability (all helper/handler methods are tested separately)\n\n> note: if you can make it _simpler_, please submit an [issue](https://github.com/dwyl/learn-json-web-tokens/issues) to discuss!\n\n## Helper Methods\n\nAll the helper methods are kept in **/example/lib/helpers.js**\nThe two most interesting/relevant methods are (simplified versions shown here):\n\n```javascript\n// generate the JWT\nfunction generateToken(req){\n  return jwt.sign({\n    auth:  'magic',\n    agent: req.headers['user-agent'],\n    exp:   Math.floor(new Date().getTime()/1000) + 7*24*60*60; // Note: in seconds!\n  }, secret);  // secret is defined in the environment variable JWT_SECRET\n}\n```\nWhich ***generates*** our JWT token when the user authenticates (this is then sent back to the client in the **Authorization** header for use in subsequent requests),\n\nand\n\n```javascript\n// validate the token supplied in request header\nfunction validate(req, res) {\n  var token = req.headers.authorization;\n  try {\n    var decoded = jwt.verify(token, secret);\n  } catch (e) {\n    return authFail(res);\n  }\n  if(!decoded || decoded.auth !== 'magic') {\n    return authFail(res);\n  } else {\n    return privado(res, token);\n  }\n}\n```\n\nWhich **checks the JWT supplied by the client is valid**,\nshows private (\"privado\") content to the requestor if valid\nand renders the **authFail** ***error*** page if its not.\n\n**Note**: *Yes*, *both* these methods are ***synchronous***.\nBut, given that neither of these methods require *any* **I/O** *or* **Network** requests,\nits pretty safe to compute them synchronously.\n\n> Tip: If you're looking for a ***Full Featured*** **JWT Auth Hapi.js plugin** (which does the verification/validation *asynchronously*) for your Hapi.js-based app please check out: [https://github.com/**dwyl/hapi-auth-jwt2**](https://github.com/dwyl/hapi-auth-jwt2)\n\n## Tests\n\nYou may have noticed the [![Build Status][travis-image]][travis-url] badge at the *start* of this tutorial.\nThis is a sign the author(s) are not just *cobbling* code together.\nThe tests for both the server routes and helper functions are in: **/example/test**\n\n1. /example/test/**functional.js** - *exercises* all the **helper methods** we created in /example/lib/**helpers.js**\n[![Test Coverage](https://codeclimate.com/github/dwyl/learn-json-web-tokens/badges/coverage.svg)](https://codeclimate.com/github/dwyl/learn-json-web-tokens)\n2. /example/test/**integration.js** - simulates the requests a *user* would send to the server and tests the *responses*.\n\nPlease *read* through the tests and *tell us* if anything is unclear!\n**Note**: We wrote a basic \"***mock***\" of the http req/res objects see: /example/test/**mock.js**\nConfused/curious about Mocking? Read [When to Mock (by \"Uncle Bob\")](http://blog.8thlight.com/uncle-bob/2014/05/10/WhenToMock.html)\n\n- - -\n\n## Frequently Asked Questions (*FAQ*)\n\n> ***Got a Question? Ask!*** >> https://github.com/dwyl/learn-json-web-tokens/issues\n\n\n### Q: If I put the JWT in the *URL* or *Header* is it *secure*?\n\nGood question! The *quick* **answer** is: ***No***.\nUnless you are using SSL/TLS (http**s** in your url) to encrypt the connection,\nsending the Token [***in-the-clear***](http://en.wikipedia.org/wiki/Plaintext)\nis *always* going to be insecure (the token can be intercepted and re-used by a bad person...).\nA *naive* \"*mitigation*\" is to add *verifiable* \"claims\" to the token\nsuch as checking that the request came from the ***same browser*** (user-agent),\n**IP address** or more advanced\n\"[**browser fingerprints**](http://stackoverflow.com/a/3287761/1148249)\"\n... http://programmers.stackexchange.com/a/122385\n\nThe solution is to *either*:\n+ use one-time-use (_single use_) tokens (_which expire after the link has been clicked_) ***or***\n+ Don't use url-tokens where high degree of security is required.\n(e.g: don't send someone a link which allows them to perform a transaction)\n\n**Use-cases** for a JWT token in a url are:\n+ account verification - when you email a person a link after they register on your site. `https://yoursite.co/account/verify?token=jwt.goes.here`\n+ password re-set - ensures that the person re-setting the password has access to the email belonging to the account.\n `https://yoursite.co/account/reset-password?token=jwt.goes.here`\n\nBoth of these are good candidates for single-use tokens (_which expire after they have been clicked_).\n\n### Q: How do we *Invalidate* sessions?\n\nThe person using your app has their **device** (phone/tablet/laptop)\n***stolen***. How do you invalidate the token they were using?\n\nThe idea behind JWT is that the tokens are ***stateless***\nthey can be **computed** by any node in a cluster and verified\nwithout a (slow) request to a database.\n\n#### Store the Token in a Database?\n\n##### LevelDB\n\nIf your app is *small* or you don't want to have to run a Redis server,\nyou can get most of the benefits of Redis by using LevelDB: http://leveldb.org/\n\nWe can ***either*** store the ***valid*** Tokens in the DB **or**\nwe can store the ***invalid*** tokens.\nBoth of these require a round-trip to the DB to check if valid/invalid.\nSo we prefer to store ***all*** tokens and update the\n**valid** property of the token from true to false.\n\nExample record stored in LevelDB\n```json\n\"GUID\" : {\n  \"auth\" : \"true\",\n  \"created\" : \"timestamp\",\n  \"uid\" : \"1234\"\n}\n```\nWe would lookup this record by its GUID:\n\n```js\nvar db = require('level');\ndb.get(GUID, function(err, record){\n  // pseudo-code\n  if(record.auth){\n    // display private content\n  } else {\n    // show error message\n  }\n});\n```\nsee: example/lib/helpers.js **validate** method for detail.\n\n##### Redis\n\nRedis is the *scalable* way of storing your tokens.\n\nIf you are *totally* new to Redis read:\n+ Intro: http://redis.io/topics/introduction\n+ Redis in 30 mins:\nhttp://openmymind.net/2011/11/8/Redis-Zero-To-Master-In-30-Minutes-Part-1/\n+ What is Redis? http://www.slideshare.net/dvirsky/introduction-to-redis\n\nRedis ***Scales*** (provided you have the RAM):\nhttp://stackoverflow.com/questions/10478794/more-than-4-billion-key-value-pairs-in-redis\n\n> ***Get Started with Redis today***! [https://github.com/dwyl/**learn-redis**](https://github.com/dwyl/learn-redis)\n\n#### Memcache?\n\n***Quick* answer**: *use **Redis***:\nhttp://stackoverflow.com/questions/10558465/memcache-vs-redis\n\n\n### Q: Returning Visitor (*no State Preservation between sessions*)\n\nCookies are stored on the client and are sent by the browser to the server on every request. If the person *closes* their browser, cookies are preserved, so they can continue where they left off without having to log-in again. However, cookies will be sent on **all** requests that match the path and issuing domain, including those for images and css, where it isn't needed.\n\n[`localStorage`](https://developer.mozilla.org/en-US/docs/Web/API/Window.localStorage) provides a better mechanism for storing tokens during and between browser sessions.\n\n#### Browser-based Applications\n\nThere are two options for storing your JWTs:\n1. Use ***localStorage*** to store your JWTs on the client side (_means you need to remember to send the JWT in your `authorization` header for subsequent http/ajax requests_)\n2. Store your JWT in a cookie (_set and forget_)\n\n> We _obviously_ prefer the cookie-less approach.\nBut if done right, cookies still have their place in modern web apps!\n(_see the Auth0 article on \"10 things you should know\" in the further reading below_)\n\n##### Useful Links\n\n+ Good ***history*** & overview of **Localstorage**:\nhttp://diveintohtml5.info/storage.html\n+ MDN **Window.localStorage**:\nhttps://developer.mozilla.org/en-US/docs/Web/API/Window.localStorage\n+ Brief description + basic *examples*:\nhttp://www.html5rocks.com/en/features/storage\n+ Will it work for *my* visitors?\nhttp://caniuse.com/#search=localstorage\n(**Quick answer**: ***Yes***! IE 8 & above, Android 4.0+, IOS 7.1+, Chrome & Firefox )\n\n\n#### Programmatic (API) Access\n\nOther services accessing your API will have to store the token in a\nretrieval system (e.g: Redis or SQLite for mobile apps) and send the token back on each request.\n\n### How to generate secret key?\n\n> \"*Apologies if this is mentioned elsewhere. The private key used for signing the tokens, is this the same as a private key generated using ssh-keygen?*\" ~ Originally asked by [@skota](https://github.com/skota) see: [dwyl/**hapi-auth-jwt2/issues**/48](https://github.com/dwyl/hapi-auth-jwt2/issues/48)\n\n\nSince JSON Web Tokens (JWT) do not have to be signed using [***asymmetric encryption***](http://en.wikipedia.org/wiki/Public-key_cryptography) you do not *have* to generate your secret key using ***ssh-keygen***. You can just as easily use a ***strong password*** e.g: https://www.grc.com/passwords.htm provided it's ***long and random***. The chance of collision (and thus someone being able to modify the payload, adding or modifying claims, and create a valid signature) is pretty low. And if you join two of those **Strong Passwords** (*strings*) together, you'll have a 128bit ASCII String. So the chances of collision are less than the [number of *atoms* in the universe](http://en.wikipedia.org/wiki/Observable_universe#Matter_content_.E2.80.94_number_of_atoms).\n\nTo quickly and easily create a secret key using Node's crypto library, run this command.\n\n    node -e \"console.log(require('crypto').randomBytes(32).toString('hex'));\"\n\nIn other words, you *can* use an ***RSA key***, but you don't *have to*.\n\nThe main thing you need to remember is: don't share the key with people who are not in your core (\"*DevOps Team*\") or *accidentally* publish it by committing it to GitHub!\n\n\n\n\n## Which Node.js Module?\n\nA search for \"**JSON Web Token**\" on NPM:\nhttps://www.npmjs.com/search?q=json+web+token yields ***many*** results!\n\n![npm search for json web token](http://i.imgur.com/ZLN3LlW.png)\n\n### Building a Web App with Hapi.js?\n\nIn our efforts to simplify using JWTs in Hapi.js apps,\nwe wrote this module: https://github.com/dwyl/hapi-auth-jwt2\n\n\n### General Use in *Other* Node.js Projects\n\nWe *highly* recommend using the **jsonwebtoken** module\nmade by our friends [@auth0](https://twitter.com/auth0)\n([the identity/authentication experts](https://auth0.com/about)):\n- https://github.com/auth0/node-jsonwebtoken\nWhich in turn uses:\nhttps://github.com/brianloveswords/node-jws\n[![NPM][jsonwebtoken-icon] ][jsonwebtoken-url]\n\nAnother great option is: https://github.com/joaquimserafim/json-web-token\nby our friend [@joaquimserafim](https://github.com/joaquimserafim)\n\n## Essential Reading (_Background_)\n\n- Original **Specification** (Draft):\nhttps://tools.ietf.org/html/draft-ietf-oauth-json-web-token-32\n- Great overview from Atlassian:\nhttps://developer.atlassian.com/cloud/jira/platform/understanding-jwt/\n- Good intro (ruby-specific examples):\nhttp://www.intridea.com/blog/2013/11/7/json-web-token-the-useful-little-standard-you-haven-t-heard-about\n+ Friendlier introduction: http://jwt.io/\n+ Getting to know JWT:\nhttps://scotch.io/tutorials/the-anatomy-of-a-json-web-token\n- Discussion: https://ask.auth0.com/c/jwt\n+ ***How to*** do **stateless authentication** (session-less & cookie-less):\nhttp://stackoverflow.com/questions/20588467/how-to-do-stateless-session-less-cookie-less-authentication\n\n\n## Further Reading (_Recommended_) [![contributions welcome](https://img.shields.io/badge/contributions-welcome-brightgreen.svg?style=flat)](https://github.com/dwyl/learn-json-web-tokens/issues)\n\n+ JWT with Passport.js:\nhttp://stackoverflow.com/questions/20228572/passport-local-with-node-jwt-simple\n+ JWT Tokens as API Keys:\nhttps://auth0.com/blog/2014/12/02/using-json-web-tokens-as-api-keys/\n+ **10 Things you should know** about ***Tokens and Cookies***:\nhttps://auth0.com/blog/2014/01/27/ten-things-you-should-know-about-tokens-and-cookies/#xss-xsrf\n+ Information Security discussion:\nhttp://security.stackexchange.com/questions/51294/json-web-tokens-jwt-as-user-identification-and-authentication-tokens\n+ Using JWT with node.js (express + backbone):\nhttp://www.sitepoint.com/using-json-web-tokens-node-js/\n+ Token-based Authentication with Socket.IO\nhttps://auth0.com/blog/2014/01/15/auth-with-socket-io/\n+ JWT Auth *discussion* on Hacker News:\nhttps://news.ycombinator.com/item?id=7084435\n+ The Spec but nicer:\nhttp://self-issued.info/docs/draft-ietf-oauth-json-web-token.html\n+ Extended (Wiki) article on Claims-based authentication:\nhttp://en.wikipedia.org/wiki/Claims-based_identity\n+ Securing Requests with JWT:\nhttp://websec.io/2014/08/04/Securing-Requests-with-JWT.html\n+ Avoid Database in authenticating user for each request (stateless):\nhttp://security.stackexchange.com/questions/49145/avoid-hitting-db-to-authenticate-a-user-on-every-request-in-stateless-web-app-ar\n+ The Twelve-Factor App: http://12factor.net/ + http://12factor.net/processes\n+ Auth in Hapi with JWT: https://medium.com/@thedon/auth-in-hapi-with-jwt-780ce4d072c7#.clgj5lknq\n+ Token based authentication in Node.js with Passport, JWT and bcrypt: https://jonathas.com/token-based-authentication-in-nodejs-with-passport-jwt-and-bcrypt/\n\n# *Thanks* for Learning with Us!\n\nIf you found this quick guide useful, please star it on GitHub!\nand re-tweet to share it with others: https://twitter.com/olizilla/status/626487231860080640\n\n[![olizilla tweet](http://i.imgur.com/rCvNvvk.jpg)](https://twitter.com/olizilla/status/626487231860080640 \"Please Re-Tweet!\")\n","maintainers":[{"name":"nelsonic","email":"contact.nelsonic@gmail.com"}],"time":{"modified":"2022-06-19T11:21:24.658Z","created":"2015-04-11T07:03:45.074Z","1.0.3":"2015-04-11T07:03:45.074Z","1.0.4":"2015-07-30T02:24:21.923Z","1.0.6":"2019-04-15T11:13:15.440Z"},"homepage":"https://github.com/dwyl/learn-json-web-tokens","keywords":["JSON","Web","Tokens","JWT","Security"],"repository":{"type":"git","url":"git+https://github.com/dwyl/learn-json-web-tokens.git"},"author":{"name":"@nelsonic","email":"contact.nelsonic@gmail.com","url":"https://github.com/nelsonic"},"bugs":{"url":"https://github.com/dwyl/learn-json-web-tokens/issues"},"license":"ISC","readmeFilename":"README.md","users":{"isik":true,"mjurincic":true}}