<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:googleplay="http://www.google.com/schemas/play-podcasts/1.0"><channel><title><![CDATA[Identity, Authenticity, and Security]]></title><description><![CDATA[System designs and tutorials of IAM (Identity and Access Management), user authentication and authorization, and web application security.]]></description><link>https://unknwon.substack.com</link><image><url>https://substackcdn.com/image/fetch/$s_!ieJw!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F07936b31-4265-4500-9fb4-b456c4be87fd_1106x1106.png</url><title>Identity, Authenticity, and Security</title><link>https://unknwon.substack.com</link></image><generator>Substack</generator><lastBuildDate>Wed, 15 Jul 2026 05:11:09 GMT</lastBuildDate><atom:link href="https://unknwon.substack.com/feed" rel="self" type="application/rss+xml"/><copyright><![CDATA[Joe Chen]]></copyright><language><![CDATA[en]]></language><webMaster><![CDATA[unknwon@substack.com]]></webMaster><itunes:owner><itunes:email><![CDATA[unknwon@substack.com]]></itunes:email><itunes:name><![CDATA[Joe Chen]]></itunes:name></itunes:owner><itunes:author><![CDATA[Joe Chen]]></itunes:author><googleplay:owner><![CDATA[unknwon@substack.com]]></googleplay:owner><googleplay:email><![CDATA[unknwon@substack.com]]></googleplay:email><googleplay:author><![CDATA[Joe Chen]]></googleplay:author><itunes:block><![CDATA[Yes]]></itunes:block><item><title><![CDATA[Authentication for beginners, part 1: You don’t store the passwords]]></title><description><![CDATA[The best way to protect a secret is not knowing the secret at all.]]></description><link>https://unknwon.substack.com/p/authentication-for-beginners-part-one</link><guid isPermaLink="false">https://unknwon.substack.com/p/authentication-for-beginners-part-one</guid><dc:creator><![CDATA[Joe Chen]]></dc:creator><pubDate>Fri, 25 Oct 2024 19:16:43 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/f8a64dcd-c3c7-4e8a-992b-a4f859bf6ac8_1024x768.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>If you're new to authentication and think 'what's so hard about storing usernames and passwords to make a simple accounts system?' - well then you're already doing it wrong!</p><p>The truth is, you should never store the passwords of your users. But then the question arises, what do you mean &#8220;I should not store&#8221; and how is it possible?</p><p>In this post, I will explain what I mean exactly, and how to implement a secure accounts system without storing any of the user's passwords.</p><h2>TL;DR</h2><p><strong>The best way to protect a secret is not knowing the secret at all.</strong></p><p>The accounts system should only ever store a proxy to the user's password, which we often refer to as password hashes. We use the user&#8217;s password as the secret to <strong>compute its hash via a computationally-expensive algorithm </strong>(by purpose).</p><p>Because a user's password is very often the same or similar across different websites, the system should always generate a random string to mixin with the password to achieve a certain level of unpredictability (of the secret) for computing the signature. This process is referred to as &#8220;adding salt&#8221; and those signatures are then called &#8220;salted hashes&#8221;.</p><p>As of this writing, popular and safe choices of signature algorithms are Argon2, Bcrypt, Scrypt and PBKDF2 with cryptographically-randomly-generated slats and right parameters.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://unknwon.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Identity, Authenticity, and Security is a reader-supported publication. To receive new posts and support my work, consider becoming a free or paid subscriber.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><h2>You wanted to store passwords as plaintext</h2><p>First of all, I want to clarify what &#8220;store&#8221; means in the context of this post. It means keeping something in persistent storage, very often, if you&#8217;re building an accounts system for your website, then your persistent storage is a database.</p><p>Let&#8217;s say, you have the following database table schema for your `users` table, where you have a column for the username and another column for the user&#8217;s password.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Z-v1!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F088e8a71-143b-400e-b403-d68584f19af5_414x338.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Z-v1!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F088e8a71-143b-400e-b403-d68584f19af5_414x338.png 424w, https://substackcdn.com/image/fetch/$s_!Z-v1!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F088e8a71-143b-400e-b403-d68584f19af5_414x338.png 848w, https://substackcdn.com/image/fetch/$s_!Z-v1!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F088e8a71-143b-400e-b403-d68584f19af5_414x338.png 1272w, https://substackcdn.com/image/fetch/$s_!Z-v1!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F088e8a71-143b-400e-b403-d68584f19af5_414x338.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Z-v1!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F088e8a71-143b-400e-b403-d68584f19af5_414x338.png" width="260" height="212.27053140096618" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/088e8a71-143b-400e-b403-d68584f19af5_414x338.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:338,&quot;width&quot;:414,&quot;resizeWidth&quot;:260,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Z-v1!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F088e8a71-143b-400e-b403-d68584f19af5_414x338.png 424w, https://substackcdn.com/image/fetch/$s_!Z-v1!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F088e8a71-143b-400e-b403-d68584f19af5_414x338.png 848w, https://substackcdn.com/image/fetch/$s_!Z-v1!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F088e8a71-143b-400e-b403-d68584f19af5_414x338.png 1272w, https://substackcdn.com/image/fetch/$s_!Z-v1!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F088e8a71-143b-400e-b403-d68584f19af5_414x338.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><p>How would you go about checking a user's credentials when they try to authenticate (aka. log in, sign in)?</p><p>In the Go programming language, you could do it as follows (the code snippet is for illustration purpose only):</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!i0w5!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F291b400e-06c6-463b-b6c7-270ec3c1666d_1296x456.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!i0w5!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F291b400e-06c6-463b-b6c7-270ec3c1666d_1296x456.png 424w, https://substackcdn.com/image/fetch/$s_!i0w5!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F291b400e-06c6-463b-b6c7-270ec3c1666d_1296x456.png 848w, https://substackcdn.com/image/fetch/$s_!i0w5!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F291b400e-06c6-463b-b6c7-270ec3c1666d_1296x456.png 1272w, https://substackcdn.com/image/fetch/$s_!i0w5!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F291b400e-06c6-463b-b6c7-270ec3c1666d_1296x456.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!i0w5!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F291b400e-06c6-463b-b6c7-270ec3c1666d_1296x456.png" width="1296" height="456" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/291b400e-06c6-463b-b6c7-270ec3c1666d_1296x456.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:456,&quot;width&quot;:1296,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!i0w5!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F291b400e-06c6-463b-b6c7-270ec3c1666d_1296x456.png 424w, https://substackcdn.com/image/fetch/$s_!i0w5!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F291b400e-06c6-463b-b6c7-270ec3c1666d_1296x456.png 848w, https://substackcdn.com/image/fetch/$s_!i0w5!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F291b400e-06c6-463b-b6c7-270ec3c1666d_1296x456.png 1272w, https://substackcdn.com/image/fetch/$s_!i0w5!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F291b400e-06c6-463b-b6c7-270ec3c1666d_1296x456.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>You may now ask, &#8220;isn&#8217;t that right? What&#8217;s wrong with it? Can&#8217;t users sign in perfectly to my website and my job is done?&#8221;</p><p>Well, it is functionally correct, but security-wise, it is a nightmare.</p><p>&#8220;How so? Aren&#8217;t users without the correct passwords unable to sign in? Are you selling me shit like NFTs?&#8221; You&#8217;re getting skeptical.</p><p>Systems developed nowadays are well aware of common attack vectors, some even directly baked into the framework you choose. Unfortunately, there is still an unsolved attack vector that accounts for many of the data breaches that you hear about in the news, which is what we call &#8220;social engineering&#8221;. What that means, in simple terms, is that the system itself is robust and secure (like you&#8217;re checking a user's credentials to be able to authenticate), but access to the system infrastructure and persistent storage, on the other hand, is often overlooked. That is saying, if the access to the system infrastructure is compromised (which is often much easier than attacking the system directly), then all of the defenses built in the system are effectively bypassed because of the malicious users (aka. hackers) get the backdoor access.</p><p>Now, think of it again, all of your users&#8217; passwords in what, plaintext, what a pleasant gift to the hackers for them to sell. You&#8217;re literally making them rich by sacrificing your own business brand (tax-free assets transfer, huh?).</p><p>&#8220;Wait a minute&#8221;, you said, &#8220;access control in my company is heavily locked down.&#8221; Sure, you can and you should, but then why are there &#8220;insider trades&#8221; in the stock market even in such a highly regulated and policed industry? What about a malicious application silently installed on your employees devices and monitoring screens and/or network traffic before your IT gets alerted? What about an application bug that accidently logs the credentials and/or sends them to third-party vendors (who have their own set of security problems)? What about taking pictures from a mobile device? What about the database backup storage got compromised? The list can go on for the rest of my life, but I hope you get what&#8217;s the problem here: there are infinite possibilities to leak users&#8217; passwords in this imperfect world.</p><p>&#8220;What do I do now?&#8221; Don&#8217;t sit there with you hands in your hair just yet, remember:</p><p><strong>The best way to protect a secret is not knowing the secret at all.</strong></p><p>If your persistent storage and your employees do not even know what the passwords are, it is impossible to leak through them (by chance or on purpose) just because they have high privilege access to your system infrastructure.</p><p>Taking one step back, the fundamental reason that we want to avoid storing users&#8217; passwords is coming from two basic security principles when doing your system designs:</p><ol><li><p><strong>The least privilege principle:</strong> Access is only granted to those who actually need it, and revoked when no longer needed.</p></li><li><p><strong>The defense in depth principle:</strong> Put security measures in every possible layer, not just the current outermost layer (usually the user-facing layer).</p></li></ol><p>How do these two principles apply to our storyline here?</p><ol><li><p>The least privilege principle for user passwords</p><ol><li><p>Who else besides the users themselves need to know the password? The answer is only the application logic (that lives only in memory) that validates the username and password.</p></li></ol></li><li><p>The defense in depth principle for user passwords</p><ol><li><p>The system should not only check user passwords for authentication, but also store the passwords securely.</p></li></ol></li></ol><p>&#8220;OK OK, I&#8217;m sold, what should I do instead?&#8221;</p><p>Let&#8217;s ask ourselves this question: why do users need to enter their username and password for authentication, in the first place?</p><p>Because we need an approach for users to prove that they are who they claim they are by asking something theoretically only the users themselves know. Therefore, the question becomes, is there a way to prove the user knows the correct password without storing the password itself?</p><p>Yes, in computer science, a common technology that can achieve exactly that, is called hashing. It uses the following attributes that we can take advantage of:</p><ul><li><p>The same output is guaranteed given the same input</p></li><li><p>It is absurdly time-consuming to reverse the input from an output</p><ul><li><p>This is why hashing algorithms are always evolving with the commodity computing powers and mathematical theories. What was considered irreversible before may not hold true today or in the near future.</p></li></ul></li><li><p>Some algorithms are designed to be computationally expensive, making computing all possible variants of the outputs absurdly expensive.</p><ul><li><p>Similarly, what it means to be &#8220;absurdly expensive&#8221; evolves with the commodity computing powers and mathematical theories.</p></li></ul></li></ul><p>To summarize, instead of storing user passwords in plaintext, we should store hashed results (aka. signatures) in the persistent storage.</p><h2>MD5 looks pretty random to me?</h2><p>MD5 was once the popular choice but has been considered insecure because it lost some of the attributes with the current commodity computing powers and mathematical theories:</p><ul><li><p>It is now practically possible to get the same output with different inputs (aka. collisions)</p></li><li><p>It is now computationally inexpensive</p></li></ul><p>Same for many other older hashing algorithms like MD4, NTLM, etc. you may never even heard of (which might be good so you won&#8217;t try to use those insecure algorithms), making them no longer suitable to be used as password hashing algorithms.</p><h2>Then what about the SHA family?</h2><p>SHA1 is in a very close spot as MD5. SHA256 and SHA512 are better choices nowadays, but in terms of protecting user passwords, SHA family isn&#8217;t a great choice because they are not computationally expensive enough to prevent cracking passwords with a brute-force approach.</p><h2>Salted hashes</h2><p>&#8220;I know I don&#8217;t need to store the actual passwords by using a hashing algorithm, but what the heck are salts?&#8221;</p><p>One of the advantages to us, can be the disadvantage to us as well. The attribute that &#8220;the same output is guaranteed given the same input&#8221; of hashing algorithms gives predictability to both us and hackers.</p><p>Let&#8217;s say, when the databases were compromised on other sites through data breaches, or precomputed hashes of common passwords offline (see <a href="https://weakpass.com/">https://weakpass.com</a> as an example), hackers then have a very large dataset of mappings between leaked/known passwords and their corresponding hashes. With that, they are able to compare against leaked data from your database to efficiently reveal the original passwords, authenticate against your system legitimately, and start stealing user&#8217;s data. This attack technique is called <a href="https://en.wikipedia.org/wiki/Dictionary_attack">dictionary attack</a>.</p><p>The defense technique that we call &#8220;adding salts&#8221; comes from the idea that, every time you add salts to your dishes, no two additions will be exactly the same in terms of the amount of salts, nor the shape of every salt. This technique effectively makes any precomputation of hashes useless, and requires hackers to recompute almost everything, which when things done right on our side, becomes absurdly expensive.</p><p>The salts however, must be cryptographically-randomly generated to make this defense technique effective, i.e. do not use pseudo-random generators.</p><p>In the Go programming language, you could do it as follows (the code snippet is good to use as-is):</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!s9W8!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2000d012-c4d0-44aa-a827-70d7d42d2bb7_1526x1228.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!s9W8!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2000d012-c4d0-44aa-a827-70d7d42d2bb7_1526x1228.png 424w, https://substackcdn.com/image/fetch/$s_!s9W8!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2000d012-c4d0-44aa-a827-70d7d42d2bb7_1526x1228.png 848w, https://substackcdn.com/image/fetch/$s_!s9W8!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2000d012-c4d0-44aa-a827-70d7d42d2bb7_1526x1228.png 1272w, https://substackcdn.com/image/fetch/$s_!s9W8!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2000d012-c4d0-44aa-a827-70d7d42d2bb7_1526x1228.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!s9W8!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2000d012-c4d0-44aa-a827-70d7d42d2bb7_1526x1228.png" width="1456" height="1172" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/2000d012-c4d0-44aa-a827-70d7d42d2bb7_1526x1228.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1172,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!s9W8!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2000d012-c4d0-44aa-a827-70d7d42d2bb7_1526x1228.png 424w, https://substackcdn.com/image/fetch/$s_!s9W8!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2000d012-c4d0-44aa-a827-70d7d42d2bb7_1526x1228.png 848w, https://substackcdn.com/image/fetch/$s_!s9W8!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2000d012-c4d0-44aa-a827-70d7d42d2bb7_1526x1228.png 1272w, https://substackcdn.com/image/fetch/$s_!s9W8!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2000d012-c4d0-44aa-a827-70d7d42d2bb7_1526x1228.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h2>Who are the cool kids?</h2><p>As of this writing, popular and safe choices of signature algorithms are <strong>Argon2, Bcrypt, Scrypt and PBKDF2 with cryptographically randomly-generated salts and right parameters</strong>.</p><p>&#8220;Wait wait, not that fast! What are the right parameters?&#8221;</p><p>Unlike hashing algorithms like the SHA family, where you have fixed parameters (e.g. SHA1 computes 20-byte signatures, SHA256 computes 32-byte signatures, SHA512 computes 64-byte signatures), modern hashing algorithms are configurable in terms of the level of computational expensiveness.</p><p>For example,</p><ul><li><p>you may choose the length of entropy, which usually means the length of the salts added. As a contrary, SHA family or any older hashing algorithms have no builtin support for salts.</p></li><li><p>and number of compute iterations, SHA family has exactly one iteration, modern algorithms default to thousands or tens of thousands of iterations. It makes the computation of the final signature both CPU and memory intensive, and ultimately achieving the goal of being computational expensive.</p></li></ul><p>Be careful though, always use well-respected implementations of those hashing algorithms in your programming language, and do not implement any of those algorithms on your own and think you're a genius unless you indeed are (in which case, better contribute to those implementations instead). The reasons being those well-respected implementations are usually battle-tested in production systems who often had to go through extensive penetration tests to ensure there are no exploitable flaws in those systems. Better to enjoy the free rides when it comes to cryptography than pay the cost on your own.</p><h2>Be aware of the performance implications</h2><p>For new accounts systems, it is recommended to start using Argon2 as the strongest password hashing algorithm, but like every design decision in computer science, it&#8217;s all about trade-offs.</p><p>Theoretically, the longer the entropy and the more compute iterations the more secure, it is more costly for your computing infrastructure as well. You definitely do not want to end up in a situation where the old saying goes, &#8220;killing flies with a machine gun&#8221;, that the algorithm and the parameters you choose drags down your system performance to to the point regular user authentication becomes a timing attack to your system (e.g. it takes one minute to complete any authentication because you chose to have ten million compute iterations with 99 as your entropy length). A good balance is that the signature computation is expensive enough to make computing at a massive scale absurdly expensive for unethical hackers, but cheap enough to feel instantaneous at the time of user authentication.</p><p>Speaking of the timing attack, one little detail is that you should always use a constant-time comparison function when possible.</p><p>In the Go programming language, you could do it as follows (the code snippet is for illustration purpose only):</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!O_Kv!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F10d144b6-90dc-45a3-b312-0837556b138e_1360x574.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!O_Kv!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F10d144b6-90dc-45a3-b312-0837556b138e_1360x574.png 424w, https://substackcdn.com/image/fetch/$s_!O_Kv!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F10d144b6-90dc-45a3-b312-0837556b138e_1360x574.png 848w, https://substackcdn.com/image/fetch/$s_!O_Kv!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F10d144b6-90dc-45a3-b312-0837556b138e_1360x574.png 1272w, https://substackcdn.com/image/fetch/$s_!O_Kv!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F10d144b6-90dc-45a3-b312-0837556b138e_1360x574.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!O_Kv!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F10d144b6-90dc-45a3-b312-0837556b138e_1360x574.png" width="1360" height="574" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/10d144b6-90dc-45a3-b312-0837556b138e_1360x574.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:574,&quot;width&quot;:1360,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!O_Kv!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F10d144b6-90dc-45a3-b312-0837556b138e_1360x574.png 424w, https://substackcdn.com/image/fetch/$s_!O_Kv!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F10d144b6-90dc-45a3-b312-0837556b138e_1360x574.png 848w, https://substackcdn.com/image/fetch/$s_!O_Kv!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F10d144b6-90dc-45a3-b312-0837556b138e_1360x574.png 1272w, https://substackcdn.com/image/fetch/$s_!O_Kv!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F10d144b6-90dc-45a3-b312-0837556b138e_1360x574.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>You can find <a href="https://github.com/unknwon/unknwon.substack.com/blob/main/authentication-for-beginners-part-one/hash-benchmark/README.md">a simple benchmark on my GitHub repository</a> to give you a grasp of the performance implications between different password hashing algorithms with recommended parameters.</p><p>Some takeaways:</p><ul><li><p>Since SHA family alone isn&#8217;t a good password hashing algorithm, their results are meaningless compared to other real algorithms, but you can tell between SHA256 and SHA512 that the cost is linear to the hash size they compute.</p></li><li><p>None of the good password hashing algorithms look great on benchmark because that&#8217;s by design, and only Argon2 meaningfully increases the speed from multiple cores starting at 4, but its memory is insane compared to others.</p></li><li><p>Based on the recommended parameters, PBKDF2 with SHA512 seems to strike a good balance between speed and memory usage.</p></li></ul><h2>Why does it have to be hashed? Can&#8217;t encryption do it?</h2><p>Encryption is better than plaintext, but not so much and still goes against the least privilege principle because the persistent storage does not need to know the users&#8217; passwords at all. In the event of the database being compromised, likely your encryption secret is being exposed too, making your encrypted passwords effectively plaintext to the hackers.</p><h2>Welcome to the reality shit show!</h2><p>You should have a good understanding about how to securely handle your users&#8217; passwords, but does this worry you in any way?&nbsp;</p><p>If not, then you should! Because you should always use a different randomly generated password for every website you have an account with, you never know how they handle your password in their persistent storage, and if you share passwords across different services, and when one gets compromised, it would put all your accounts in other services in danger! The best you can do is to get yourself a proper password manager.</p><h2>Further readings</h2><ul><li><p><a href="https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html">OWASP - Password Storage Cheat Sheet</a>&nbsp;</p></li><li><p><a href="https://passlib.readthedocs.io/en/stable/lib/passlib.hash.html">passlib - Password Hashing Schemes</a>&nbsp;</p></li></ul>]]></content:encoded></item><item><title><![CDATA[Identity 101: Authentication and Authorization ]]></title><description><![CDATA[Similarities, differences, and confusion of authentication and authorization]]></description><link>https://unknwon.substack.com/p/identity-101-authentication-and-authorization</link><guid isPermaLink="false">https://unknwon.substack.com/p/identity-101-authentication-and-authorization</guid><dc:creator><![CDATA[Joe Chen]]></dc:creator><pubDate>Wed, 04 Sep 2024 18:13:53 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/c66e12de-e8be-4f6e-90e8-f084075d67fb_612x345.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>If you think authentication and authorization is so confusing that you can't even understand what your PM and peers are talking about.&nbsp;</p><p>Congratulations, you&#8217;ve come to the right place!</p><p>Whether you&#8217;re building a single-user application, an admin dashboard, or a multi-user product, you likely have encountered the terms authentication and authorization and most likely gotten them confused. What&#8217;s worse, developers new to application security oftentimes mistakenly use them interchangeably. What do people mean when they say, &#8220;auth&#8221;, &#8220;authN&#8221;, and &#8220;authZ&#8221;?</p><p>In this post, we will clear up all the common misconceptions and make sure you have a clear understanding of what the terms mean, and when to use them.</p><h2>TL;DR</h2><p>If you&#8217;re in a hurry, here is the takeaway and you may skip the rest of the post:</p><ul><li><p>Authentication refers to the process of <strong>proving who you are</strong>.</p></li><li><p>Authorization refers to the process of <strong>checking what you can do</strong>.</p></li></ul><p>Pretty simple, isn&#8217;t it?</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://unknwon.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Identity, Authenticity, and Security! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><h2>What are they, exactly?</h2><p><strong>Authentication, often referred to as "authN" for short, is the process by which a service verifies a visitor&#8217;s identity by requiring them to prove their legitimate access through specific methods.</strong></p><p>Even if you&#8217;ve never heard of the term &#8220;authentication&#8221;, you have performed the process with almost every service on the internet nowadays (that requires an account). Commonly, visitors use:</p><ul><li><p>Emails with a password, one-time passcode, magic link, etc.</p></li><li><p>Social sign-ins like GitHub, Google, X, or Microsoft, etc.</p></li><li><p>Phone numbers with one-time passcode</p></li><li><p>Biometrics like touch ID, or face ID, etc.</p></li><li><p>Passkeys</p></li></ul><p>In addition, if the visitor&#8217;s account has<a href="https://en.wikipedia.org/wiki/Multi-factor_authentication"> Multi-Factor Authentication (MFA)</a> enabled, an extra verification step is presented and must be completed as part of the same authentication process. Commonly, by:</p><ul><li><p>Receiving one-time passcodes via email, phone, or authenticator (Google Authenticator, 1Password, Duo, etc.)</p></li><li><p>Tapping &#8220;Yes, it&#8217;s me&#8221; on a trusted device</p></li></ul><p>Once the visitors complete the authentication process, we then call them &#8220;authenticated users&#8221; and use some techniques to &#8220;remember&#8221; the authenticated state for a period of time (often known as &#8220;sessions&#8221;), so visitors will not get annoyed by authenticating themselves over and over until they give up using your service.</p><p><strong>Authorization, often referred to as &#8220;authZ&#8221; for short, is the process by which the service backend asserts whether the currently authenticated user has permission to perform the intended action.</strong></p><p>This process isn&#8217;t as visible as authentication to visitors because the entire process is completed within the service backend. Visitors would only get an error like &#8220;access denied&#8221; if the visitor is not authorized to perform the intended action (often known as &#8220;unauthorized access&#8221;).</p><p>How does the service backend determine whether an intended action is authorized or not? It heavily depends on the actual business logic and how the service backend chooses to implement its authorization system, but common examples are:</p><ul><li><p>Whether the authenticated user is an admin for admin actions.</p></li><li><p>Whether other users have shared access with the authenticated user for their protected data.</p></li><li><p>Whether the authenticated user is on the premium plan for paid features.</p></li></ul><p>What about &#8220;auth&#8221;, what does it refer to? When people mention &#8220;auth&#8221; in a conversation, they either mean authentication or both, almost always never solely meaning authorization. Remember, when in doubt, simply ask clarifying questions.</p><h2>What are the gotchas?</h2><p>Although authentication and authorization look similar, and sound similar, the way they are being designed and implemented are very different.</p><p>The implementation of authentication (other than the UI) is fundamentally the same for most services. Therefore, in addition to the typical email/username sign-in, many open standards have been published and adopted as the go-to solutions. Just to name a few:</p><ul><li><p><a href="https://en.wikipedia.org/wiki/OAuth">OAuth 2</a>-based sign-ins (although technically OAuth 2 isn&#8217;t an authentication protocol, it has been widely adopted since the rise of social sign-ins)</p></li><li><p><a href="https://en.wikipedia.org/wiki/OpenID">OIDC</a>, which builds on top of OAuth 2 as a sophisticated authentication protocol</p></li><li><p><a href="https://en.wikipedia.org/wiki/SAML_2.0">SAML 2.0</a>, an XML-based protocol widely adopted in enterprise settings</p></li><li><p><a href="https://en.wikipedia.org/wiki/Lightweight_Directory_Access_Protocol">LDAP</a>, ancient but still widely used, most enterprises use its variant<a href="https://en.wikipedia.org/wiki/Active_Directory"> Active Directory</a> from Microsoft</p></li><li><p>Passkeys from<a href="https://en.wikipedia.org/wiki/WebAuthn"> WebAuthn</a>, the new cool kid in town</p></li></ul><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!X1gP!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a947d71-d83e-4242-ad42-4786f9cfa15a_1600x716.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!X1gP!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a947d71-d83e-4242-ad42-4786f9cfa15a_1600x716.png 424w, https://substackcdn.com/image/fetch/$s_!X1gP!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a947d71-d83e-4242-ad42-4786f9cfa15a_1600x716.png 848w, https://substackcdn.com/image/fetch/$s_!X1gP!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a947d71-d83e-4242-ad42-4786f9cfa15a_1600x716.png 1272w, https://substackcdn.com/image/fetch/$s_!X1gP!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a947d71-d83e-4242-ad42-4786f9cfa15a_1600x716.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!X1gP!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a947d71-d83e-4242-ad42-4786f9cfa15a_1600x716.png" width="1456" height="652" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/1a947d71-d83e-4242-ad42-4786f9cfa15a_1600x716.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:652,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!X1gP!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a947d71-d83e-4242-ad42-4786f9cfa15a_1600x716.png 424w, https://substackcdn.com/image/fetch/$s_!X1gP!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a947d71-d83e-4242-ad42-4786f9cfa15a_1600x716.png 848w, https://substackcdn.com/image/fetch/$s_!X1gP!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a947d71-d83e-4242-ad42-4786f9cfa15a_1600x716.png 1272w, https://substackcdn.com/image/fetch/$s_!X1gP!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a947d71-d83e-4242-ad42-4786f9cfa15a_1600x716.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>On the other hand, the design choice and implementation of authorization in services are almost always heavily dependent on the actual business logic, which makes it harder to adopt any go-to solution. Efforts have been made to provide some standardization around authorization models:</p><ul><li><p><a href="https://en.wikipedia.org/wiki/Role-based_access_control">Role-based access control (RBAC)</a> defines access based on the user&#8217;s roles, e.g. site admin, billing manager, and regular users.</p></li><li><p><a href="https://en.wikipedia.org/wiki/Attribute-based_access_control">Attribute-based access control (ABAC)</a> allows the service to provide fine-grained authorization, e.g. OAuth 2 token scopes is an application of ABAC.</p></li><li><p><a href="https://en.wikipedia.org/wiki/Relationship-based_access_control">Relationship-based access control (ReBAC)</a> was coined by the publication of<a href="https://research.google/pubs/zanzibar-googles-consistent-global-authorization-system/"> Google&#8217;s Zanzibar</a>, it is the most complex, sophisticated yet flexible way to define authorization models.</p></li></ul><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!2529!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb773fb2-4369-4309-a938-44fcfcb35e68_1364x712.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!2529!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb773fb2-4369-4309-a938-44fcfcb35e68_1364x712.png 424w, https://substackcdn.com/image/fetch/$s_!2529!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb773fb2-4369-4309-a938-44fcfcb35e68_1364x712.png 848w, https://substackcdn.com/image/fetch/$s_!2529!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb773fb2-4369-4309-a938-44fcfcb35e68_1364x712.png 1272w, https://substackcdn.com/image/fetch/$s_!2529!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb773fb2-4369-4309-a938-44fcfcb35e68_1364x712.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!2529!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb773fb2-4369-4309-a938-44fcfcb35e68_1364x712.png" width="1364" height="712" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/bb773fb2-4369-4309-a938-44fcfcb35e68_1364x712.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:712,&quot;width&quot;:1364,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!2529!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb773fb2-4369-4309-a938-44fcfcb35e68_1364x712.png 424w, https://substackcdn.com/image/fetch/$s_!2529!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb773fb2-4369-4309-a938-44fcfcb35e68_1364x712.png 848w, https://substackcdn.com/image/fetch/$s_!2529!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb773fb2-4369-4309-a938-44fcfcb35e68_1364x712.png 1272w, https://substackcdn.com/image/fetch/$s_!2529!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb773fb2-4369-4309-a938-44fcfcb35e68_1364x712.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Theoretically, both of them need to happen for every single request that would potentially or explicitly access protected data. Although certain techniques can be applied to improve the user experience (UX) and request latency:</p><ul><li><p>Use sessions or alike to remember the result of authentication for a period of time, typically 7-30 days. Government and financial services are often more stringent, limiting sessions to 15 to 30 minutes.</p></li><li><p>Use caching to save the computation results of an authorization evaluation for a short period of time. Usually not recommended, but useful when it is expensive to compute the authorization evaluations of some operations.</p></li></ul><p>Besides the implementation, there are other things to keep in mind:</p><ul><li><p>Depending on the use case and the nature of the business, not all endpoints of your service have to be put behind authentication. For example:</p><ul><li><p>Anyone can view any public posts on Substack, but only authenticated users can subscribe to newsletters and manage their paid subscriptions.</p></li><li><p>Admin dashboard type of services typically require authentication before any action can be performed.</p></li></ul></li><li><p>Not every service requires complex design and implementation of authentication and authorization:</p><ul><li><p>The more ways to do the same thing, the more attacks surface from the outside, e.g. if your service doesn&#8217;t require LDAP, SAML, or social sign-ins, it is better to leave them out.</p></li><li><p>If all you need is to check whether a user is an admin or not, a simple isAdmin helper (and an extra database column like is_admin on your users table) does the perfect job for implementing your authorization system. Do not over-engineer the solution because the more complex the system is, the easier to write (security) bugs.</p></li></ul></li><li><p>A common mistake for developers new to application security is that they implemented authentication and authorization in a layer that visitors can easily bypass. In other words, putting authentication and authorization purely in browsers, mobile apps, or editor extensions is ineffective, and malicious users can always bypass your checks and send requests directly to your service backend and gain unauthorized access.</p><ul><li><p>With that said, additional authentication and authorization in browsers, mobile apps, or editor extensions can be helpful to enhance the UX, e.g. by not showing certain items if the user has no access to them or only displaying public information when not authenticated.</p></li></ul></li></ul><p>Because both authentication and authorization are so crucial to get right, it is important to take them into consideration early in your system design, as some design decisions may turn out to be infeasible with security constraints.</p><h2>Can you walk me through an example?</h2><p>Sure!</p><p>Using Sourcegraph&#8217;s public code search as an example (since I was personally involved in designing, building, and maintaining many parts of its authentication and authorization systems throughout my tenure).</p><ul><li><p>Not all endpoints are behind authentication:</p><ul><li><p>Anyone on the internet can make code searches across public repositories on Sourcegraph.com, e.g. search for the keyword &#8220;gogs&#8221; (<a href="https://sourcegraph.com/search?q=context:global+gogs&amp;patternType=keyword&amp;sm=0">link</a>).</p></li></ul></li><li><p>Certain features are only available to authenticated users:</p><ul><li><p>Using the Cody Web chat (https://sourcegraph.com/cody/chat) will prompt for authentication, and visitors will be able to authenticate via their email, Google.com, GitHub.com, and GitLab.com accounts.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!FrMe!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4601ee0d-6dbc-4ddd-9de5-4e0d6fdac378_1128x1100.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!FrMe!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4601ee0d-6dbc-4ddd-9de5-4e0d6fdac378_1128x1100.png 424w, https://substackcdn.com/image/fetch/$s_!FrMe!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4601ee0d-6dbc-4ddd-9de5-4e0d6fdac378_1128x1100.png 848w, https://substackcdn.com/image/fetch/$s_!FrMe!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4601ee0d-6dbc-4ddd-9de5-4e0d6fdac378_1128x1100.png 1272w, https://substackcdn.com/image/fetch/$s_!FrMe!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4601ee0d-6dbc-4ddd-9de5-4e0d6fdac378_1128x1100.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!FrMe!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4601ee0d-6dbc-4ddd-9de5-4e0d6fdac378_1128x1100.png" width="358" height="349.11347517730496" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/4601ee0d-6dbc-4ddd-9de5-4e0d6fdac378_1128x1100.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1100,&quot;width&quot;:1128,&quot;resizeWidth&quot;:358,&quot;bytes&quot;:96960,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!FrMe!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4601ee0d-6dbc-4ddd-9de5-4e0d6fdac378_1128x1100.png 424w, https://substackcdn.com/image/fetch/$s_!FrMe!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4601ee0d-6dbc-4ddd-9de5-4e0d6fdac378_1128x1100.png 848w, https://substackcdn.com/image/fetch/$s_!FrMe!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4601ee0d-6dbc-4ddd-9de5-4e0d6fdac378_1128x1100.png 1272w, https://substackcdn.com/image/fetch/$s_!FrMe!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4601ee0d-6dbc-4ddd-9de5-4e0d6fdac378_1128x1100.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div></li><li><p>If you look closely enough, when not authenticated, the &#8220;Tools&#8221; option in the top navbar is not displayed at all.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!qQ-d!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7280132f-e893-4237-ae26-3de775f6a193_490x344.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!qQ-d!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7280132f-e893-4237-ae26-3de775f6a193_490x344.png 424w, https://substackcdn.com/image/fetch/$s_!qQ-d!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7280132f-e893-4237-ae26-3de775f6a193_490x344.png 848w, https://substackcdn.com/image/fetch/$s_!qQ-d!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7280132f-e893-4237-ae26-3de775f6a193_490x344.png 1272w, https://substackcdn.com/image/fetch/$s_!qQ-d!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7280132f-e893-4237-ae26-3de775f6a193_490x344.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!qQ-d!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7280132f-e893-4237-ae26-3de775f6a193_490x344.png" width="278" height="195.16734693877552" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/7280132f-e893-4237-ae26-3de775f6a193_490x344.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:344,&quot;width&quot;:490,&quot;resizeWidth&quot;:278,&quot;bytes&quot;:30284,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!qQ-d!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7280132f-e893-4237-ae26-3de775f6a193_490x344.png 424w, https://substackcdn.com/image/fetch/$s_!qQ-d!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7280132f-e893-4237-ae26-3de775f6a193_490x344.png 848w, https://substackcdn.com/image/fetch/$s_!qQ-d!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7280132f-e893-4237-ae26-3de775f6a193_490x344.png 1272w, https://substackcdn.com/image/fetch/$s_!qQ-d!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7280132f-e893-4237-ae26-3de775f6a193_490x344.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div></li><li><p>Access to site admin features is blocked unless the authenticated user has a site admin role.</p></li></ul><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!AmFd!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F450c86fa-eb7f-4f69-b0ba-4576a78be0d7_780x544.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!AmFd!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F450c86fa-eb7f-4f69-b0ba-4576a78be0d7_780x544.png 424w, https://substackcdn.com/image/fetch/$s_!AmFd!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F450c86fa-eb7f-4f69-b0ba-4576a78be0d7_780x544.png 848w, https://substackcdn.com/image/fetch/$s_!AmFd!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F450c86fa-eb7f-4f69-b0ba-4576a78be0d7_780x544.png 1272w, https://substackcdn.com/image/fetch/$s_!AmFd!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F450c86fa-eb7f-4f69-b0ba-4576a78be0d7_780x544.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!AmFd!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F450c86fa-eb7f-4f69-b0ba-4576a78be0d7_780x544.png" width="334" height="232.94358974358974" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/450c86fa-eb7f-4f69-b0ba-4576a78be0d7_780x544.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:544,&quot;width&quot;:780,&quot;resizeWidth&quot;:334,&quot;bytes&quot;:37822,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!AmFd!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F450c86fa-eb7f-4f69-b0ba-4576a78be0d7_780x544.png 424w, https://substackcdn.com/image/fetch/$s_!AmFd!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F450c86fa-eb7f-4f69-b0ba-4576a78be0d7_780x544.png 848w, https://substackcdn.com/image/fetch/$s_!AmFd!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F450c86fa-eb7f-4f69-b0ba-4576a78be0d7_780x544.png 1272w, https://substackcdn.com/image/fetch/$s_!AmFd!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F450c86fa-eb7f-4f69-b0ba-4576a78be0d7_780x544.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><ul><li><p>Users can only view and manage their own Cody subscriptions, user settings, UI preferences, etc.</p></li></ul></li></ul><h2>Why should I care?</h2><p>Having a strong sense and solid defense in application security are as important as having locks on your doors and windows, monitoring surroundings with security cameras, and verifying ID at bank service counters. Authentication and authorization are the first line of defense in the internet era; every developer should have a reasonable level of understanding so we can write more secure code and stop making it so easy to leak people&#8217;s personal data online (please, please, please &#128591; Identity theft is so annoying OK?).</p><p>Ineffective application security, at the very least, costs your company money and gives away valuable assets; at worst, it will hurt your company's reputation and cause a loss of customer trust and deals.</p><p>Every developer needs to be disciplined about application security because it takes a great effort to build the defense but it only takes a tiny crack to fail.</p><h2>I&#8217;m pumped, how can I learn more?</h2><p>Auth0 provides a rich set of resources on the topics of authentication and authorization (<a href="https://auth0.com/resources">link</a>), while this is not an endorsement nor promotion of their product, you will learn a lot by just playing around.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://unknwon.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Identity, Authenticity, and Security! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[Coming soon]]></title><description><![CDATA[Safeguard your spot in the AI era for "taken for granted" things.]]></description><link>https://unknwon.substack.com/p/coming-soon</link><guid isPermaLink="false">https://unknwon.substack.com/p/coming-soon</guid><dc:creator><![CDATA[Joe Chen]]></dc:creator><pubDate>Sat, 18 May 2024 17:45:53 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F07936b31-4265-4500-9fb4-b456c4be87fd_1106x1106.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Hi there &#128075; It&#8217;s my pleasure to meet you here!</p><p>My name is Joe Chen, I am a software engineer currently working at <a href="https://sourcegraph.com/">Sourcegraph</a> since 2019. I have spent most of my tenancy working on user authentication, user authorization, cross-system roles and permissions synchronization, designing and building IAM systems, both for single-tenant (enterprise on-prem) and multi-tenant (SaaS product) architectures, with a strong emphasis of making them both secure and scalable.</p><p>In this newsletter, you will find all kinds of resources that help you learn and solidify your strength on modern system design knowledge and skills about Identity, Authenticity, and Security. Doesn&#8217;t matter whether you&#8217;re just getting started, grow your career, or just for fun!</p><p>If you&#8217;re pumped by now, please consider &#128071;</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://unknwon.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://unknwon.substack.com/subscribe?"><span>Subscribe now</span></a></p>]]></content:encoded></item></channel></rss>