{"componentChunkName":"component---src-templates-tag-js","path":"/tags/json-web-tokens/","result":{"data":{"site":{"siteMetadata":{"title":"LoginRadius Blog"}},"allMarkdownRemark":{"totalCount":2,"edges":[{"node":{"fields":{"slug":"/engineering/invalidating-jwt/"},"html":"<p>As we all know, JSON Web Tokens are a way of sending information between parties in a way where the sender's authenticity can be verified. It is essentially a JSON object with a signature. Using this signature, services that issue these tokens can verify that they are the ones who issued this token and thus can trust the claims which are contained within. </p>\n<p>The trustworthiness of these tokens make them popular for use in authorization and authentication scenarios:</p>\n<ul>\n<li>In authorization workflows, JSON Web Tokens are distributed to users with claims containing the resources and services that are allowed for that user. The issuing service can perform its database lookups to determine the user's authorization levels when the token is being generated and issued. Since the signature can be used to verify that the token is authentic and issued by a trusted source, for subsequent transactions using the token, the service can safely take the token at its word. This saves the service from needing to check its database for the user's relevant permissions every time a transaction is performed.</li>\n<li>In authentication workflows such as OAuth2, JSON Web Tokens are often used as part of a larger workflow, where they are useful to securely transmit information between parties. Since the resource server and authenticating server are different, these tokens ensure that the information being received by these parties is valid and authentic.</li>\n</ul>\n<p>For this post, we'll be focusing on the former use case. So having a token with trustworthy claims is great; we can take the token at its word, and trust all of the information that it has contained within as gospel. Our server is unburdened from having to potentially make database calls to verify the user's role, their permissions, their existence, or even if they're logged in. Once the server has generated the token, as far as it is concerned, no state has to be maintained regarding the validity of the token. It will expire once its expiration time included in its claim has passed.</p>\n<p>But before we go ahead and use this for all of our authorization needs, we have to remember that while JSON Web Tokens themselves are stateless, to have a robust, feasible, and controllable authorization workflow, we'll have to maintain some state one way or another.</p>\n<p>You can think of an authorization token as an elementary school hall pass. The teacher (resource server) knows that it is a legitimate hall pass because it is green, 6 cm x 12 cm and has a signature from another member of the faculty. Now imagine that you've issued a hall pass, but now you need to take it back (you've changed your mind, or the kid did something bad). Your options are:</p>\n<ul>\n<li>Go to the kid and take the pass back (browser deletes the token from its storage). However, the kid made a photocopy, and can still roam the halls with relative ease.</li>\n<li>Wait till the hall pass expires (wait till the token expiry claim passes). Green hall passes are only valid on Mondays. He can still roam the halls freely for the remainder of Monday (the horror).</li>\n<li>Change the entire format of the hall pass (change the secret used to sign the token). The crisis has been averted, but now you'll need to handicraft another 5 whole hall passes for the class.</li>\n</ul>\n<p>Other than the 3rd option which may or may not be feasible depending on your use case (most likely not), we can see that it is not possible to reliably remove or revoke a token without maintaining state. The solutions that I've looked upon Stack Overflow for invalidating these tokens boil down to relying on some form of state, one way or another. Don't get me wrong however, this is not a bad thing in my opinion. Using JSON Web Tokens can and do allow us to minimize the state that we do have to maintain, with minimal added complexity.</p>\n<p>So let's look at some ways that we can couple state and JSON Web Tokens that allow us to invalidate these tokens effectively.</p>\n<h3 id=\"token-whitelist\" style=\"position:relative;\"><a href=\"#token-whitelist\" aria-label=\"token whitelist permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Token Whitelist</h3>\n<p>We can maintain a database table containing all of the tokens issued by our server that we would like to accept as valid. This would be a 1:1 session store, with every transaction occurring requiring this table to be checked to prevent an invalidated token from being accepted. While we would not be able to reduce the amount of state being maintained on our server, JSON Web Tokens still provide us with the utility of its trusted claims (and the performance benefits of not needing to check those).</p>\n<h3 id=\"token-blacklist\" style=\"position:relative;\"><a href=\"#token-blacklist\" aria-label=\"token blacklist permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Token Blacklist</h3>\n<p>We can maintain a database table containing all of the tokens issued by our server that we do NOT want to accept as valid. Every transaction that occurs will require this table to be checked, to prevent an invalidated token from being accepted. Each record would only have to be maintained until the token itself expires. I can't think of any use case where a table of invalidated tokens would regularly be larger than a table of active tokens, so I'd imagine that the table maintained would almost always be smaller than maintaining a table of active tokens.</p>\n<h3 id=\"using-a-dynamic-secret-to-sign\" style=\"position:relative;\"><a href=\"#using-a-dynamic-secret-to-sign\" aria-label=\"using a dynamic secret to sign permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Using a Dynamic Secret to Sign</h3>\n<p>This solution still needs a database lookup, but interestingly requires no state. For this, we can use the hash of a piece of data to sign the token itself. For example, by using the hash of a user's password, when the user changes their password, subsequent transactions involving an old token will fail, as the signature will fail to be verified. The effectiveness of this, however, would depend on your requirements, as this would be limited to invalidating tokens based on changing data (such as changing roles, passwords, etc.). It would not allow you to invalidate a token whenever you want.</p>\n<h3 id=\"concluding-remarks\" style=\"position:relative;\"><a href=\"#concluding-remarks\" aria-label=\"concluding remarks permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Concluding Remarks</h3>\n<p>I think that JSON Web Tokens coupled with a token blacklist is a fantastic way to manage authorization in web applications. This allows you to leverage the benefits of these tokens in reducing the network calls needed to secure your application, reduce the amount of data you need to store to manage sessions, and do so in a reliable way without introducing too much complexity.</p>\n<style class=\"grvsc-styles\">\n  .grvsc-container {\n    overflow: auto;\n    -webkit-overflow-scrolling: touch;\n    padding-top: 1rem;\n    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));\n    padding-bottom: 1rem;\n    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));\n    border-radius: 8px;\n    border-radius: var(--grvsc-border-radius, 8px);\n    font-feature-settings: normal;\n  }\n  \n  .grvsc-code {\n    display: inline-block;\n    min-width: 100%;\n  }\n  \n  .grvsc-line {\n    display: inline-block;\n    box-sizing: border-box;\n    width: 100%;\n    padding-left: 1.5rem;\n    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));\n    padding-right: 1.5rem;\n    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));\n  }\n  \n  .grvsc-line-highlighted {\n    background-color: var(--grvsc-line-highlighted-background-color, transparent);\n    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);\n  }\n  \n</style>","frontmatter":{"date":"January 18, 2021","updated_date":null,"title":"Invalidating JSON Web Tokens","tags":["JSON Web Tokens","JWT"],"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1.5037593984962405,"src":"/static/0c11b157497c5b54f5a0149f01ce15ac/58556/unsplash.webp","srcSet":"/static/0c11b157497c5b54f5a0149f01ce15ac/61e93/unsplash.webp 200w,\n/static/0c11b157497c5b54f5a0149f01ce15ac/1f5c5/unsplash.webp 400w,\n/static/0c11b157497c5b54f5a0149f01ce15ac/58556/unsplash.webp 800w,\n/static/0c11b157497c5b54f5a0149f01ce15ac/99238/unsplash.webp 1200w","sizes":"(max-width: 800px) 100vw, 800px"}}},"author":{"id":"Nick Chim","github":"nickc95","avatar":null}}}},{"node":{"fields":{"slug":"/engineering/jwt-signing-algorithms/"},"html":"<h1 id=\"jwt-signing-algorithms\" style=\"position:relative;\"><a href=\"#jwt-signing-algorithms\" aria-label=\"jwt signing algorithms permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>JWT Signing Algorithms</h1>\n<p>When JSON Web Tokens are created, they are typically signed by its issuer. This allows the recipient of the token to validate that the token received contains all of the information encoded by the issuer unmodified and as intended.</p>\n<p>A signature is not to be mistaken for encryption! The fact that a JSON token is signed does not mean that the data enclosed is unreadable by third parties. All a signature does is ensure that the message is authentic, which it achieves by allowing the recipient to compare the data they’ve received with a trusted claim included in the data (the signature).</p>\n<p>JWTs are most commonly signed using one of two algorithms: HS256 (HMAC using SHA256), and RS256 (RSA using SHA256).</p>\n<h2 id=\"how-does-a-signature-ensure-authenticity\" style=\"position:relative;\"><a href=\"#how-does-a-signature-ensure-authenticity\" aria-label=\"how does a signature ensure authenticity permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>How does a signature ensure authenticity?</h2>\n<p>A signature can only be created by someone possessing a secret key, and the original payload. Signatures are generally formed by combining the data to be signed with a secret key, either by appending them together and hashing them (HS256), or by encrypting a representation of that data (a hash) using the secret key (RS256).</p>\n<p>In both signing algorithms, the data is formatted into an immutable representation in a way that a recipient can check that the creator of the signature was in possession of that particular secret key.</p>\n<h2 id=\"hs256\" style=\"position:relative;\"><a href=\"#hs256\" aria-label=\"hs256 permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>HS256</h2>\n<p>HS256 is a symmetric signing method. This means that the same secret key is used to both create and verify the signature.</p>\n<p>The issuer appends the JWT header and payload with the secret key, and hashes the result using SHA256, creating a signature. The recipient uses their copies of the secret key, JWT header and payload in the same way to reproduce the signature, checking to see if they match.</p>\n<p>Aside from some incredibly unlikely scenarios, the only way for these signatures to be consistent is if the JWT header, payload and secret shared between the two parties are identical.</p>\n<h2 id=\"rs256\" style=\"position:relative;\"><a href=\"#rs256\" aria-label=\"rs256 permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>RS256</h2>\n<p>RS256 is an asymmetric encryption method. This differs from a symmetric scheme in that rather than using a single secret key, a pair of seperate keys are used to encrypt and decrypt the data.</p>\n<p>The issuer generates a hash of the JWT header and payload using SHA256, and encrypts it using the RSA encryption algorithm, and their private key. The recipient uses their public key to decrypt the signature ciphertext, and then compares it to a hash they’ve reproduced using their copy of the JWT header and payload, checking for consistency.</p>\n<p>The only way that these resulting hashes are consistent is if the JWT header and payload shared between the two parties are identical, and the public key corresponds to the private key used to encrypt the hash.</p>\n<h2 id=\"when-to-use-which\" style=\"position:relative;\"><a href=\"#when-to-use-which\" aria-label=\"when to use which permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>When to use which?</h2>\n<p>Both signing schemes are effectively secure, with HS256 being a little faster. However, given this use case, the difference in speed is not particularly relevant.</p>\n<p>The main consideration on which to use, is in my opinion the symmetric vs asymmetric property of each:</p>\n<ul>\n<li>For HS256, the secret must be shared between the sender and recipient.</li>\n<li>For RS256, the private key can be kept secret, and the public key can be freely issued.</li>\n<li>In both cases, it confirms to the recipient that the message was sent by the expected party, and was received in the form that it was in when the signature was generated.</li>\n</ul>\n<p>Having an unsecured publicly available key is useful in many cases. For example, it can be published openly on the internet as part of a metadata endpoint, allowing JWT configurators to automatically retrieve the key, making for a straightforward and automatic JWT setup. As such, RS256 may be more suitable for situations where data is exchanged between two independent parties.</p>\n<p>Having a shared secret key can however also be useful in some cases. For example, if the issuer and recipient were both managed by a single party, the two applications would be able to share configurations without having to manage two separate keys. As such, HS256 may be more suitable for situations where data is exchanged within a single party</p>\n<style class=\"grvsc-styles\">\n  .grvsc-container {\n    overflow: auto;\n    -webkit-overflow-scrolling: touch;\n    padding-top: 1rem;\n    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));\n    padding-bottom: 1rem;\n    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));\n    border-radius: 8px;\n    border-radius: var(--grvsc-border-radius, 8px);\n    font-feature-settings: normal;\n  }\n  \n  .grvsc-code {\n    display: inline-block;\n    min-width: 100%;\n  }\n  \n  .grvsc-line {\n    display: inline-block;\n    box-sizing: border-box;\n    width: 100%;\n    padding-left: 1.5rem;\n    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));\n    padding-right: 1.5rem;\n    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));\n  }\n  \n  .grvsc-line-highlighted {\n    background-color: var(--grvsc-line-highlighted-background-color, transparent);\n    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);\n  }\n  \n</style>","frontmatter":{"date":"September 24, 2020","updated_date":null,"title":"JWT Signing Algorithms","tags":["JWT","JSON Web Tokens"],"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1.5037593984962405,"src":"/static/2fd4c7f86c996d936d9b217235d6257d/58556/unsplash.webp","srcSet":"/static/2fd4c7f86c996d936d9b217235d6257d/61e93/unsplash.webp 200w,\n/static/2fd4c7f86c996d936d9b217235d6257d/1f5c5/unsplash.webp 400w,\n/static/2fd4c7f86c996d936d9b217235d6257d/58556/unsplash.webp 800w,\n/static/2fd4c7f86c996d936d9b217235d6257d/99238/unsplash.webp 1200w","sizes":"(max-width: 800px) 100vw, 800px"}}},"author":{"id":"Nick Chim","github":"nickc95","avatar":null}}}}]}},"pageContext":{"tag":"JSON Web Tokens"}},"staticQueryHashes":["1171199041","1384082988","2100481360","23180105","528864852"]}