<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: gao-sun</title>
    <description>The latest articles on Forem by gao-sun (@gaosun).</description>
    <link>https://forem.com/gaosun</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F468603%2F797e1bab-203b-40a3-862a-1a83db723ef6.jpeg</url>
      <title>Forem: gao-sun</title>
      <link>https://forem.com/gaosun</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/gaosun"/>
    <language>en</language>
    <item>
      <title>Logto Cloud is officially launched!</title>
      <dc:creator>gao-sun</dc:creator>
      <pubDate>Wed, 26 Jul 2023 11:31:42 +0000</pubDate>
      <link>https://forem.com/logto/logto-cloud-is-officially-launched-506c</link>
      <guid>https://forem.com/logto/logto-cloud-is-officially-launched-506c</guid>
      <description>&lt;p&gt;👋 Today, we are more than happy to announce that Logto Cloud is officially launched!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Logto is an Auth0 alternative for building modern customer identity infrastructure with minimal effort, for both your customers and their organizations.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;🎉 Join our launch on &lt;a href="https://www.producthunt.com/posts/logto-cloud"&gt;Product Hunt&lt;/a&gt; and support us! We'd love for you to leave us a review as well.&lt;/p&gt;

&lt;p&gt;We'd like also invite you to take a look at our &lt;a href="https://logto.io/"&gt;new website&lt;/a&gt; and explore the features of Logto Cloud.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>beginners</category>
      <category>programming</category>
      <category>opensource</category>
    </item>
    <item>
      <title>The evolution of password hashing</title>
      <dc:creator>gao-sun</dc:creator>
      <pubDate>Tue, 18 Jul 2023 10:10:17 +0000</pubDate>
      <link>https://forem.com/logto/the-evolution-of-password-hashing-1g29</link>
      <guid>https://forem.com/logto/the-evolution-of-password-hashing-1g29</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Password hashing, as the name suggests, is the process of calculating a hash value from a password. The hash value is typically stored in a database, and during the login (sign-in) process, the hash value of the password entered by the user is calculated and compared with the hash value stored in the database. If they match, the user is authenticated.&lt;/p&gt;

&lt;p&gt;Before we dive into the evolution of password hashing algorithms, it's important to understand why it's necessary.&lt;/p&gt;

&lt;h3&gt;
  
  
  Plain text passwords: A major security risk
&lt;/h3&gt;

&lt;p&gt;Imagine being a user of a website where you've registered an account. One day, the website gets hacked, and the database is leaked. If the website stores passwords in plaintext, the hacker can directly access your password. Since many people reuse passwords across multiple websites, the hacker can use this password to gain unauthorized access to your other accounts. The situation becomes even worse if you use the same or a similar password for your email account, as the hacker can reset your password and take over all your associated accounts.&lt;/p&gt;

&lt;p&gt;Even without a data breach, in large teams, anyone with database access can see passwords. Compared to other information, passwords are highly sensitive, and you definitely don't want anyone to have access to them.&lt;/p&gt;

&lt;p&gt;Storing passwords without hashing is an amateur mistake. Unfortunately, if you search for "password leak plaintext", you'll find that major corporations like &lt;a href="https://krebsonsecurity.com/2019/03/facebook-stored-hundreds-of-millions-of-user-passwords-in-plain-text-for-years/"&gt;Facebook&lt;/a&gt;, &lt;a href="https://therecord.media/8-3-million-plaintext-passwords-exposed-in-dailyquiz-data-breach"&gt;DailyQuiz&lt;/a&gt;, and &lt;a href="https://www.wordfence.com/blog/2021/11/godaddy-breach-plaintext-passwords/"&gt;GoDaddy&lt;/a&gt; have all experienced password leaks in plaintext. It's likely that many other companies have made the same error.&lt;/p&gt;

&lt;h3&gt;
  
  
  Encoding v.s. encryption v.s. hashing
&lt;/h3&gt;

&lt;p&gt;These three terms are often confused, but they are distinct concepts.&lt;/p&gt;

&lt;h4&gt;
  
  
  Encoding
&lt;/h4&gt;

&lt;p&gt;Encoding is the first thing to exclude for password storage. For example, &lt;a href="https://en.wikipedia.org/wiki/Base64"&gt;Base64&lt;/a&gt; is an encoding algorithm that converts binary data into a string of characters:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello, world!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;encoded&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Buffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;base64&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;encoded&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// SGVsbG8sIHdvcmxkIQ==&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Knowing the encoding algorithm allows anyone to decode the encoded string and retrieve the original data:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;encoded&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;SGVsbG8sIHdvcmxkIQ==&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Buffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;encoded&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;base64&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Hello, world!&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To hackers, most encoding algorithms are equivalent to plaintext.&lt;/p&gt;

&lt;h4&gt;
  
  
  Encryption
&lt;/h4&gt;

&lt;p&gt;Before hashing gained popularity, encryption was used to store passwords, such as with AES. Encryption involves using a key (or a pair of keys) to encrypt and decrypt data.&lt;/p&gt;

&lt;p&gt;The problem with encryption is evident in the term "decrypt". Encryption is reversible, meaning that if a hacker obtains the key, they can decrypt the password and retrieve the plaintext password.&lt;/p&gt;

&lt;h4&gt;
  
  
  Hashing
&lt;/h4&gt;

&lt;p&gt;The primary difference between hashing, encoding, and encryption is that hashing is &lt;strong&gt;irreversible&lt;/strong&gt;. Once a password is hashed, it cannot be decrypted back to its original form.&lt;/p&gt;

&lt;p&gt;As a website owner, you don't actually need to know the password itself, as long as the user can log in with the correct password. The registration process can be simplified as follows:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;User enters the password.&lt;/li&gt;
&lt;li&gt;The service uses a hashing algorithm to calculate the hash value of the password.&lt;/li&gt;
&lt;li&gt;The service stores the hash value in the database.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;When the user logs in, the process is:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;User enters the password.&lt;/li&gt;
&lt;li&gt;The service uses the same hashing algorithm to calculate the hash value of the password.&lt;/li&gt;
&lt;li&gt;The service compares the hash value with the hash value stored in the database.&lt;/li&gt;
&lt;li&gt;If the hash values match, the user is authenticated.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Both processes avoid storing passwords in plaintext, and since hashing is irreversible, even if the database is compromised, the hacker can only obtain hash values that appear as random strings.&lt;/p&gt;

&lt;h2&gt;
  
  
  Hashing algorithms starter pack
&lt;/h2&gt;

&lt;p&gt;Hashing may seem like the perfect solution for password storage, but it's not that simple. To understand why, let's explore the evolution of password hashing algorithms.&lt;/p&gt;

&lt;h3&gt;
  
  
  MD5
&lt;/h3&gt;

&lt;p&gt;In 1992, Ron Rivest designed the &lt;a href="https://www.rfc-editor.org/rfc/rfc1321.html"&gt;MD5 algorithm&lt;/a&gt;, a message-digest algorithm that can calculate a 128-bit hash value from any data. MD5 has been widely used in various fields, including password hashing. For example, the MD5 hash value of "123456" is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;e10adc3949ba59abbe56e057f20f883e
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As mentioned earlier, the hash value appears as a random string and is irreversible. Moreover, MD5 is fast and easy to implement, making it the most popular password hashing algorithm.&lt;/p&gt;

&lt;p&gt;However, MD5's advantages are also its weaknesses in password hashing. Its speed makes it vulnerable to brute-force attacks. If a hacker possesses a list of common passwords and your personal information, they can calculate the MD5 hash value of each combination and compare them with the hash values in the database. For example, they might combine your birthday with your name or your pet's name.&lt;/p&gt;

&lt;p&gt;In the present day, computers are significantly more powerful than before, making it easy to brute force MD5 password hashes.&lt;/p&gt;

&lt;h3&gt;
  
  
  SHA family
&lt;/h3&gt;

&lt;p&gt;So, why not use a different algorithm that generates longer hash values? The &lt;a href="https://en.wikipedia.org/wiki/Secure_Hash_Algorithms"&gt;SHA family&lt;/a&gt; seems like a good choice. SHA-1 is a hashing algorithm that generates 160-bit hash values, and SHA-2 is a family of hashing algorithms that generate hash values of 224-bit, 256-bit, 384-bit, and 512-bit lengths. Let's see the SHA-256 hash value of "123456":&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The SHA-256 hash value is much longer than MD5, and it is also irreversible. However, there's another issue: if you already know the hash value, like the one above, and you see the exact hash value in the database, you know the password is "123456". A hacker can create a list of common passwords and their corresponding hash values, and compare them against the hash values in the database. This list is known as a rainbow table.&lt;/p&gt;

&lt;h3&gt;
  
  
  Salt
&lt;/h3&gt;

&lt;p&gt;To mitigate rainbow table attacks, the concept of salt was introduced. Salt is a random string that is added to the password before hashing. For example, if the salt is "salt", and you want to use SHA-256 to hash the password "123456" with the salt, instead of simply doing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;sha256&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;123456&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You would do:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;sha256&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;salt123456&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 9898410d7f5045bc673db80c1a49b74f088fd7440037d8ce25c7d272a505bce5&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, the result is completely different from hashing without salt. Typically, each user is assigned a random salt during registration, which is stored in the database alongside the hash value. During the login process, the salt is used to calculate the hash value of the entered password, which is then compared to the stored hash value.&lt;/p&gt;

&lt;h3&gt;
  
  
  Iteration
&lt;/h3&gt;

&lt;p&gt;Despite the addition of salt, the hash value is still susceptible to brute-force attacks as hardware becomes more powerful. To make it harder, iteration (i.e., running the hashing algorithm multiple times) can be introduced. For example, instead of using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;sha256&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;salt123456&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You could use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;sha256&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;salt&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;sha256&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;salt123456&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Increasing the number of iterations makes brute-forcing more difficult. However, this also affects the login process, as it becomes slower. Therefore, a balance between security and performance needs to be struck.&lt;/p&gt;

&lt;h2&gt;
  
  
  Halftime break
&lt;/h2&gt;

&lt;p&gt;Let's take a break and summarize the characteristics of a good password hashing algorithm:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Irreversible (preimage resistance)&lt;/li&gt;
&lt;li&gt;Difficult to brute force&lt;/li&gt;
&lt;li&gt;Resistant to rainbow table attacks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As you may have noticed, salt and iteration are necessary to satisfy all these requirements. The issue is that both MD5 and the SHA family were not specifically designed for password hashing; they are widely used for integrity checks (or "message-digest"). As a result, each website may have its own implementation of salt and iteration, making standardization and migration challenging.&lt;/p&gt;

&lt;h2&gt;
  
  
  Password hashing algorithms
&lt;/h2&gt;

&lt;p&gt;To address this problem, several hashing algorithms have been specifically designed for password hashing. Let's take a look at some of them.&lt;/p&gt;

&lt;h3&gt;
  
  
  bcrypt
&lt;/h3&gt;

&lt;p&gt;bcrypt is a password hashing algorithm designed by Niels Provos and David Mazières. It is widely used in many programming languages. Here's an example of bcrypt hash value:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$2y$12$wNt7lt/xf8wRJgPU7kK2juGrirhHK4gdb0NiCRdsSoAxqQoNbiluu
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Although it appears as another random string, it contains additional information. Let's break it down:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[$2y][$12][$wNt7lt/xf8wRJgPU7kK2ju][GrirhHK4gdb0NiCRdsSoAxqQoNbiluu]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;The first section &lt;code&gt;$2y&lt;/code&gt; indicates the algorithm, which is &lt;code&gt;2y&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The second section &lt;code&gt;$12&lt;/code&gt; indicates the number of iterations, which is &lt;code&gt;12&lt;/code&gt;. This means the hashing algorithm will be run 2&lt;sup&gt;12&lt;/sup&gt;=4096 times (iterations).&lt;/li&gt;
&lt;li&gt;The third section &lt;code&gt;wNt7lt/xf8wRJgPU7kK2ju&lt;/code&gt; is the salt.&lt;/li&gt;
&lt;li&gt;The last section &lt;code&gt;GrirhHK4gdb0NiCRdsSoAxqQoNbiluu&lt;/code&gt; is the hash value.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;bcrypt has some limitations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The maximum length of the password is 72 bytes.&lt;/li&gt;
&lt;li&gt;The salt is limited to 16 bytes.&lt;/li&gt;
&lt;li&gt;The hash value is limited to 184 bits.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Argon2
&lt;/h3&gt;

&lt;p&gt;Given the debates and limitations of existing password hashing algorithms, a &lt;a href="https://www.password-hashing.net/"&gt;password hashing competition&lt;/a&gt; was held in 2015. Skipping the details, let's focus on the winner: Argon2.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.rfc-editor.org/rfc/rfc9106.html"&gt;Argon2&lt;/a&gt; is a password hashing algorithm designed by Alex Biryukov, Daniel Dinu, and Dmitry Khovratovich. It introduces several new concepts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Memory-hard: The algorithm is designed to be hard to parallelize, making brute-forcing with GPUs challenging.&lt;/li&gt;
&lt;li&gt;Time-hard: The algorithm is designed to be hard to optimize, making brute-forcing with ASICs (Application-specific integrated circuits) difficult.&lt;/li&gt;
&lt;li&gt;Side-channel resistant: The algorithm is designed to be resistant to side-channel attacks, such as timing attacks.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;There are two main versions of Argon2, Argon2i and Argon2d. Argon2i is the safest against side-channel attacks, while Argon2d provides the highest resistance against GPU cracking attacks.&lt;/p&gt;

&lt;p&gt;-- &lt;a href="https://www.password-hashing.net/#argon2"&gt;Argon2&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Here's an example of an Argon2 hash value:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$argon2i$v=19$m=16,t=2,p=1$YTZ5ZnpXRWN5SlpjMHBDRQ$12oUmJ6xV5bIadzZHkuLTg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's break it down:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[$argon2i][$v=19][$m=16,t=2,p=1][$YTZ5ZnpXRWN5SlpjMHBDRQ][$12oUmJ6xV5bIadzZHkuLTg]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;The first section &lt;code&gt;$argon2i&lt;/code&gt; indicates the algorithm, which is &lt;code&gt;argon2i&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The second section &lt;code&gt;$v=19&lt;/code&gt; indicates the version, which is &lt;code&gt;19&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The third section &lt;code&gt;$m=16,t=2,p=1&lt;/code&gt; indicates the memory cost, time cost, and parallelism degree, where are &lt;code&gt;16&lt;/code&gt;, &lt;code&gt;2&lt;/code&gt;, and &lt;code&gt;1&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The fourth section &lt;code&gt;$YTZ5ZnpXRWN5SlpjMHBDRQ&lt;/code&gt; is the salt.&lt;/li&gt;
&lt;li&gt;The last section &lt;code&gt;$12oUmJ6xV5bIadzZHkuLTg&lt;/code&gt; is the hash value.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In Argon2, the maximum length of the password is 2&lt;sup&gt;32&lt;/sup&gt;-1 bytes, the salt is limited to 2&lt;sup&gt;32&lt;/sup&gt;-1 bytes, and the hash value is limited to 2&lt;sup&gt;32&lt;/sup&gt;-1 bytes. This should suffice for most scenarios.&lt;/p&gt;

&lt;p&gt;Argon2 is now available in many programming languages, such as &lt;a href="https://github.com/ranisalt/node-argon2/"&gt;node-argon2&lt;/a&gt; for Node.js and &lt;a href="https://pypi.org/project/argon2-cffi/"&gt;argon2-cffi&lt;/a&gt; for Python.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Over the years, password hashing algorithms have undergone significant evolution. We owe a debt of gratitude to the security community for their decades of effort in making the internet a safer place. Thanks to their contributions, developers can pay more attention to building better services without worrying about the security of password hashing. While achieving 100% security in a system may be unattainable, we can employ diverse strategies to minimize the associated risks.&lt;/p&gt;

&lt;p&gt;If you'd like to avoid the hassle of implementing authentication and authorization, feel free to try Logto for free. We provide secure (we use Argon2!), reliable, and scalable solutions, enabling you to focus on building your product.&lt;/p&gt;




&lt;center&gt;&lt;b&gt;&lt;a href="https://logto.io/?utm_source=dev&amp;amp;utm_medium=blog&amp;amp;utm_campaign=evolution-of-password-hasing"&gt;Try Logto Cloud today&lt;/a&gt;&lt;/b&gt;&lt;/center&gt;




</description>
      <category>webdev</category>
      <category>beginners</category>
      <category>programming</category>
      <category>security</category>
    </item>
    <item>
      <title>Why it’s so hard: Things learned from a bad customer support experience</title>
      <dc:creator>gao-sun</dc:creator>
      <pubDate>Tue, 04 Jul 2023 04:15:57 +0000</pubDate>
      <link>https://forem.com/logto/why-its-so-hard-things-learned-from-a-bad-customer-support-experience-3f04</link>
      <guid>https://forem.com/logto/why-its-so-hard-things-learned-from-a-bad-customer-support-experience-3f04</guid>
      <description>&lt;p&gt;As a company that offers cloud services with a product-led growth (PLG) approach, we deeply understand the importance of providing a smooth self-serve experience to users, especially in a mature market or area. However, a recent experience with a company worth billions of dollars showed a negative example of how even a common and fundamental user requirement can be mishandled.&lt;/p&gt;

&lt;h2&gt;
  
  
  Background
&lt;/h2&gt;

&lt;p&gt;The requirement was straightforward: we were using an email platform called S and needed to enable HTTPS for our email tracking links.&lt;/p&gt;

&lt;p&gt;In 2023, I assumed that using HTTPS was a basic feature, considering that &lt;a href="https://w3techs.com/technologies/details/ce-httpsdefault#:~:text=Default%20protocol%20https%20is%20used%20by%2083.2%25%20of%20all%20the%20websites."&gt;83.2% of all websites default to the HTTPS protocol&lt;/a&gt;. Thanks to industry leaders like Let's Encrypt, obtaining and maintaining trusted SSL/TLS certificates is usually not a blocker, and many products can automatically manage them for you.&lt;/p&gt;

&lt;p&gt;In the case of email platform S, before enabling HTTPS, the following prerequisites needed to be met:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1.&lt;/strong&gt; Enable Link Tracking.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2.&lt;/strong&gt; Set up a valid branded link in the platform, which involves using a custom domain for link tracking.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3.&lt;/strong&gt; Set up a valid SSL certificate for that domain.&lt;/p&gt;

&lt;p&gt;If you're not familiar with these techniques and terms, don't worry. Just remember that there are three steps involved. According to their documentation, once these steps are completed, you need to contact the support team to enable HTTPS.&lt;/p&gt;

&lt;h2&gt;
  
  
  A frustrating start: Useless chats
&lt;/h2&gt;

&lt;p&gt;In an effort to be a good customer, I came prepared and initiated an online chat session with the support team. Here's how the conversation began (G represents me, and S represents the support team for platform S; content may be edited for brevity):&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;🤔️ &lt;em&gt;G: I've set up the proxies and DNS records for SSL link tracking in Cloudflare. Can you help me enable the SSL feature? My branded links are &lt;code&gt;foo.io&lt;/code&gt; and &lt;code&gt;bar.io&lt;/code&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;🧑‍💻 S: Thank you for reaching S support.&lt;/p&gt;

&lt;p&gt;🧑‍💻 S: Please refer to the steps to enable Link Tracking:&lt;br&gt;
…&lt;/p&gt;

&lt;p&gt;🤔️ &lt;em&gt;G: I've already done that. I can confirm it works.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;🧑‍💻 S: Please refer to the steps to set up the branded link via Cloudflare:&lt;br&gt;
…&lt;/p&gt;

&lt;p&gt;🤔️ &lt;em&gt;G: I've already done that, too. I can confirm it works. The only issue is that the links are not using HTTPS. The documentation instructs me to contact support.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;🤔️ &lt;em&gt;G: Here's the link I referred to. There's another documentation suggesting the same thing.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;🧑‍💻 S: Please refer to the steps to enable Link Tracking and HTTP&lt;/p&gt;

&lt;p&gt;🧑‍💻 S: …&lt;/p&gt;

&lt;p&gt;🤔️ &lt;em&gt;G: I couldn't find the settings you provided. Here's a screenshot.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;🧑‍💻 S: To make sure that it is not a browser issue, can you please use Google Chrome, clear the cache and cookies on Chrome and also try incognito?&lt;/p&gt;

&lt;p&gt;🤔️ &lt;em&gt;G: I'm using the latest version of Chrome. Let me try clearing the cache and cookies.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;🤔️ &lt;em&gt;G: (After trying) Still no luck.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;🧑‍💻 S: Will it be okay with you if I transform this chat session into a ticket?&lt;/p&gt;

&lt;p&gt;🤔️ &lt;em&gt;G: Sure.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Several things immediately struck me:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;During the live chat, the support engineer didn't understand the real context. The process felt more like "keyword extraction”.&lt;/li&gt;
&lt;li&gt;The online support engineer didn't seem trained to handle this particular case.&lt;/li&gt;
&lt;li&gt;The online support engineer was referring to an outdated manual that applied to a non-existing (or removed) user interface.&lt;/li&gt;
&lt;li&gt;They didn't know which browser I was using (which should be easy to determine from the &lt;code&gt;User-Agent&lt;/code&gt;, although not 100% accurate, it would still save time).&lt;/li&gt;
&lt;li&gt;Resources were wasted.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  “They are not communicating”
&lt;/h2&gt;

&lt;p&gt;The next day, the conversation continued via emails:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;🧑‍💻 S: I apologize for the confusion created in our chat session. The UI may have been updated, here’s the steps for enabling HTTPS link tracking:&lt;/p&gt;

&lt;p&gt;🧑‍💻 S: (Steps about enabling click tracking only)&lt;/p&gt;

&lt;p&gt;🧑‍💻 S: (Three different documentation links to the same topic, which I had already read and followed)&lt;/p&gt;

&lt;p&gt;🤔️ &lt;em&gt;G: I've followed all the steps above, and I'm now at the step that says, "Once you have followed the configuration guide for either of these services, please contact S Support to enable SSL click and open tracking for you.”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And after another day:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;🧑‍💻 S: I could not confirm your CNAME has been configured as it’s a requirement to complete &lt;strong&gt;Step 2&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;🤔️ &lt;em&gt;G: The CNAME records were working; otherwise, the Link Branding wouldn't have been verified. The issue is that I followed your documentation, completed both &lt;strong&gt;Step 2&lt;/strong&gt; and &lt;strong&gt;Step 3&lt;/strong&gt;, but &lt;strong&gt;Step 3&lt;/strong&gt; removes the CNAME record added in &lt;strong&gt;Step 2&lt;/strong&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;🧑‍💻 S: Please refer to this blog post, I think it might help.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Thankfully, this time a new link appeared. However, to my surprise, the blog post described almost the same steps, and once again, I was stuck at "Contact S Support.”&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;At this point, despite my intention to be a good customer, I started considering switching to another modern service that valued HTTPS.&lt;/strong&gt;&lt;/p&gt;




&lt;p&gt;So, in an almost desperate mood, I sent an email:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;🤔️ &lt;em&gt;G: I’m pretty sure I’ve completed all the steps. In every link you sent me, I got stuck at the last step.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Within an hour, I received a response:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;🧑‍💻 S: Thank you for your request to enable HTTPS link branding.&lt;/p&gt;

&lt;p&gt;🧑‍💻 S: Please be reminded that you need to…&lt;/p&gt;

&lt;p&gt;🧑‍💻 S: This case is being given to senior support agents…&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And within another hour:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;🧑‍💻 S (senior engineer): I confirm that SSL has been enabled for the requested account as it passed our testing as well. All the links moving further send trough that account will be overwritten in https instead of http.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;As I received the response, the ticket has been directly closed. Fin. From this exchange, I learned a few things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The documentation was chaotic, with several guidelines discussing the same topic in different ways. This chaos also extended to the customer support training, causing confusion and inconsistencies.&lt;/li&gt;
&lt;li&gt;The support engineer from the S platform treated the customer as if they were unprepared and didn't bother reading the documentation at the start of the session.&lt;/li&gt;
&lt;li&gt;While the senior engineer had the ability to quickly enable HTTPS link branding, the junior engineer did not. There was also a significant gap in how to handle this specific situation between them.&lt;/li&gt;
&lt;li&gt;More resources were wasted.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Closing notes
&lt;/h2&gt;

&lt;p&gt;This case alerted us to how a bad user experience can waste resources and lead to customer churn. To summarize:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Enable self-service options as much as possible. This is crucial for freeing up resources to build a better product.&lt;/li&gt;
&lt;li&gt;Human customer support is inevitable, but relying solely on "keyword extraction" for support engineers is not an efficient approach. Language models like LLMs are proving to be more effective in this regard.&lt;/li&gt;
&lt;li&gt;Maintain a single source of truth for documentation. Don't mix things up, as it will confuse both your customers and teams.&lt;/li&gt;
&lt;li&gt;Keep all staff members updated on product changes. Treat it as a necessary step in product development.&lt;/li&gt;
&lt;li&gt;Identify users who submit support tickets because they didn't read the documentation or have exhausted all other options.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;While it took nearly three days to enable HTTPS link tracking on the S platform, I would like to express my gratitude to our team at Logto. The team made it possible that users can set up their custom domains with Logto-managed TLS certificates within just five minutes.&lt;/p&gt;

&lt;p&gt;I hope this article has provided some valuable insights. &lt;a href="https://logto.io/subscribe"&gt;Subscribe to us&lt;/a&gt; if you're interested in more topics about product, security, or identity!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>discuss</category>
      <category>beginners</category>
      <category>programming</category>
    </item>
    <item>
      <title>The essential security checklist for user identity</title>
      <dc:creator>gao-sun</dc:creator>
      <pubDate>Mon, 03 Jul 2023 13:43:14 +0000</pubDate>
      <link>https://forem.com/logto/the-essential-security-checklist-for-user-identity-1f1</link>
      <guid>https://forem.com/logto/the-essential-security-checklist-for-user-identity-1f1</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Building user identity is a critical component of any application. It enables you to provide personalized experiences, enhance data quality, and improve user retention.&lt;/p&gt;

&lt;p&gt;Validating usernames and passwords may seem like the simplest approach, but there are many other aspects to consider. Let's get started!&lt;/p&gt;

&lt;h2&gt;
  
  
  Infrastructure
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Enforce HTTPS
&lt;/h3&gt;

&lt;p&gt;Let's start with the basics. Always enforce the use of &lt;a href="https://en.wikipedia.org/wiki/HTTPS"&gt;HTTPS&lt;/a&gt; (Hypertext Transfer Protocol Secure) to encrypt data transmission over the internet. HTTPS ensures that the data exchanged between the user's device and your server remains confidential and tamper-proof.&lt;/p&gt;

&lt;p&gt;Setting up HTTPS may seem challenging, but there are many tools and services available to help you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If you are self-hosting, &lt;a href="https://letsencrypt.org/"&gt;Let's Encrypt&lt;/a&gt; provides free SSL/TLS certificates that can be used to enable HTTPS on your website.&lt;/li&gt;
&lt;li&gt;If you are using a cloud provider, such as AWS, Azure, or Google Cloud, you can use their managed services to set up HTTPS.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Don't allow public database access, limited to trusted sources only
&lt;/h3&gt;

&lt;p&gt;Although it may seem basic as well, there have been numerous security breaches due to allowing public access to databases. So it's worth mentioning here.&lt;/p&gt;

&lt;p&gt;Always remember to never allow public access to your database. Put your database in a private network and only allow access from trusted sources.&lt;/p&gt;

&lt;h3&gt;
  
  
  Securely manage private tokens
&lt;/h3&gt;

&lt;p&gt;Private tokens, such as access tokens or API keys, are often used for programmatic authentication and authorization purposes. To manage these tokens securely:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use short-lived tokens and refresh tokens to minimize the risk of unauthorized access.&lt;/li&gt;
&lt;li&gt;Use a secure token storage mechanism, such as a key vault, to protect tokens from unauthorized access.&lt;/li&gt;
&lt;li&gt;Regularly rotate tokens to prevent them from being compromised. Some protocols, such as OAuth 2.0, provide a mechanism for token rotation.&lt;/li&gt;
&lt;li&gt;Retain control over token revocation in case of a security breach.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Choose a password hash algorithm wisely
&lt;/h3&gt;

&lt;p&gt;If you have experience with password hashing, you may be aware that there are many algorithms available, some of which are no longer considered secure, such as MD5, SHA-1, and SHA-2.&lt;/p&gt;

&lt;p&gt;Some common reasons for their insecurity are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;They were not specifically designed for password hashing, and their computational speed is too fast, making brute force attacks easier.&lt;/li&gt;
&lt;li&gt;They lack the use of salt, which makes it easier to create &lt;a href="https://en.wikipedia.org/wiki/Rainbow_table"&gt;rainbow tables&lt;/a&gt; for them.&lt;/li&gt;
&lt;li&gt;They are susceptible to collision attacks, allowing attackers to generate different passwords with the same hash value.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Industry-standard password hashing algorithms, such as &lt;a href="https://en.wikipedia.org/wiki/Bcrypt"&gt;bcrypt&lt;/a&gt; and &lt;a href="https://www.password-hashing.net/argon2-specs.pdf"&gt;Argon2&lt;/a&gt;, have been designed to address these issues. Due to the limited scope of this article, we won't go into detail about them. You can choose a mature library for one of these algorithms in your programming language.&lt;/p&gt;

&lt;h3&gt;
  
  
  Learn and strictly adhere to open standards
&lt;/h3&gt;

&lt;p&gt;Open standards like &lt;a href="https://www.rfc-editor.org/rfc/rfc6749"&gt;OAuth 2.0&lt;/a&gt; and &lt;a href="https://openid.net/specs/openid-connect-core-1_0.html"&gt;OpenID Connect&lt;/a&gt; (OIDC) provide secure and standardized approaches for user authentication and authorization. They have been battle-tested and widely adopted by the industry.&lt;/p&gt;

&lt;p&gt;However, implementing them incorrectly can lead to security vulnerabilities, even for large teams with experienced developers. A recent example is &lt;a href="https://blog.logto.io/oauth-security-recap/"&gt;the OAuth vulnerability discovered in Expo&lt;/a&gt;, a popular framework for building mobile apps. It serves as a good example of how a small mistake can result in a security breach.&lt;/p&gt;

&lt;h3&gt;
  
  
  Encrypt data at rest
&lt;/h3&gt;

&lt;p&gt;Data at rest, such as stored user information or database backups, should be encrypted using a strong encryption algorithm. This ensures that even if the data is compromised, it cannot be read without the decryption key. Double-check if your cloud provider supports this feature, as it is commonly required for compliance purposes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Set up firewalls
&lt;/h3&gt;

&lt;p&gt;DDoS (Distributed Denial of Service) attacks, though ancient, remain a significant threat. According to the &lt;a href="https://blog.cloudflare.com/ddos-threat-report-2022-q4/"&gt;Cloudflare DDoS threat report for 2022 Q4&lt;/a&gt;, the amount of HTTP DDoS attack traffic increased by 79% YoY. Instead of building your own solution, it's a good idea to set up managed firewalls and utilize notifiers to mitigate this risk.&lt;/p&gt;

&lt;h2&gt;
  
  
  Apps and clients
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Improve security level for public clients
&lt;/h3&gt;

&lt;p&gt;Public clients, such as mobile apps or single-page applications, are more susceptible to security vulnerabilities. Even if you provide them, you should treat them as untrusted sources in your security model. For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If you are using OAuth 2.0, use &lt;a href="https://www.rfc-editor.org/rfc/rfc7636"&gt;Proof Key for Code Exchange&lt;/a&gt; (PKCE) to protect against authorization code interception attacks.&lt;/li&gt;
&lt;li&gt;Enforce &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP"&gt;Content Security Policy&lt;/a&gt; (CSP) to mitigate certain types of attacks, including &lt;a href="https://developer.mozilla.org/en-US/docs/Glossary/Cross-site_scripting"&gt;Cross-Site Scripting&lt;/a&gt; (XSS) and data injection attacks.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Never trust public input data
&lt;/h3&gt;

&lt;p&gt;User input can be a significant source of security vulnerabilities, often overlooked. Some common types of overlooked vulnerabilities are &lt;a href="https://developer.mozilla.org/en-US/docs/Glossary/Cross-site_scripting"&gt;Cross-Site Scripting&lt;/a&gt; (XSS) and &lt;a href="https://owasp.org/www-community/attacks/SQL_Injection"&gt;SQL Injection&lt;/a&gt;. Make sure to validate and sanitize all user input data before using it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Keep track of activities
&lt;/h3&gt;

&lt;p&gt;Maintaining an audit trail of user activities helps in detecting and investigating security incidents. Log and monitor user actions, such as login attempts, password changes, or sensitive operations. Analyzing these logs can provide valuable insights into potential security breaches or suspicious activities.&lt;/p&gt;

&lt;h3&gt;
  
  
  Implement solid authentication
&lt;/h3&gt;

&lt;p&gt;Implement a strong authentication mechanism to verify the identity of users. As mentioned earlier, consider using secure protocols like OAuth 2.0 or OpenID Connect for authentication. For more information, you can refer to &lt;a href="https://blog.logto.io/ciam-101-intro-authn-sso/"&gt;CIAM 101: Authentication, Identity, SSO&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Build solid authorization (e.g., Implement Role-Based Access Control)
&lt;/h3&gt;

&lt;p&gt;In addition to authentication, proper authorization mechanisms should be in place. Implement Role-Based Access Control (RBAC) to ensure that users only have access to the resources and actions they are authorized to perform. For more information, you can refer to &lt;a href="https://blog.logto.io/ciam-102-authz-and-rbac/"&gt;CIAM 102: Authorization &amp;amp; Role-based Access Control&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Implement Multi-Factor Authentication (MFA)
&lt;/h3&gt;

&lt;p&gt;Multi-Factor Authentication (MFA) adds an extra layer of security by requiring users to provide one or multiple forms of identification, such as a password and a one-time code sent to their mobile device. Another good example of MFA is when GitHub asks users to enter a one-time code from their mobile app, which is displayed on the webpage, for performing sensitive operations like deleting a repository.&lt;/p&gt;

&lt;h2&gt;
  
  
  Culture
&lt;/h2&gt;

&lt;p&gt;The advice provided above mostly covers "passive" security measures, which are known before a security incident occurs. However, there are also "active" security measures you can take to improve your overall security posture, which are more effective in the long run.&lt;/p&gt;

&lt;h3&gt;
  
  
  Educate your team and users about phishing and social engineering
&lt;/h3&gt;

&lt;p&gt;Phishing attacks and social engineering are critical because they can render many of the security measures mentioned above useless. For example, if a user is tricked into giving away their password or clicking on a seemingly innocent cat picture that contains malware, the strength of your password hashing algorithm or firewall rules becomes irrelevant.&lt;/p&gt;

&lt;p&gt;Most people find security training boring, and it often is. So, change the way you educate your team and users. For example, you can simulate a phishing email before an actual attacker does and demonstrate how to identify it. You can even offer rewards for reporting the email to the security team.&lt;/p&gt;

&lt;h3&gt;
  
  
  Set up DevSecOps
&lt;/h3&gt;

&lt;p&gt;In addition to manual security reviews, you can also implement DevSecOps practices to automate security checks. For example, you can set up a CI/CD pipeline to run static code analysis tools like &lt;a href="https://securitylab.github.com/tools/codeql"&gt;CodeQL&lt;/a&gt; and automatically run penetration tests using tools like &lt;a href="https://www.zaproxy.org/"&gt;OWASP ZAP&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Embrace the most strict configuration without impacting user experience
&lt;/h3&gt;

&lt;p&gt;When it comes to security, always opt for the most secure configuration that doesn't negatively impact the user experience. Avoid taking shortcuts or compromising security for convenience. Security should always be a top priority.&lt;/p&gt;

&lt;p&gt;As a startup or indie developer, you may feel that you lack the necessary resources to implement these measures. Nevertheless, there are professional security services available that offer free or startup-friendly options. Take the time to review and consider utilizing them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Security is a complex topic, and it is impossible to cover everything in a single article. We hope that this article has helped you build a stronger sense of security for yourself or your team. If you are building a new app, you may also want to check out &lt;a href="https://logto.io/"&gt;Logto&lt;/a&gt;, a platform that helps you develop, manage, and secure your product's user identities with minimal effort.&lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>security</category>
      <category>webdev</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Tackle social login experience: Unlocking the power of convenience</title>
      <dc:creator>gao-sun</dc:creator>
      <pubDate>Tue, 27 Jun 2023 12:02:53 +0000</pubDate>
      <link>https://forem.com/logto/tackle-social-login-experience-unlocking-the-power-of-convenience-2ncl</link>
      <guid>https://forem.com/logto/tackle-social-login-experience-unlocking-the-power-of-convenience-2ncl</guid>
      <description>&lt;p&gt;Author: Ran, Product &amp;amp; Design&lt;/p&gt;

&lt;p&gt;Most users are big fans of &lt;a href="https://en.wikipedia.org/wiki/Social_login"&gt;social login&lt;/a&gt; (social sign-in) due to its simplicity, convenience, enhanced security, and elimination of password headaches. If you're one of them, you'll be interested to know that there are several factors to consider when implementing social login to ensure an optimal user experience.&lt;/p&gt;

&lt;p&gt;In this blog post, we will explore why product authentication chooses social login and discuss ways to enhance its advantages through thoughtful design choices. Additionally, you can experience the seamless social login flow firsthand within Logto's web console.&lt;/p&gt;




&lt;center&gt;
&lt;a href="https://logto.io/?utm_source=dev&amp;amp;utm_campaign=tackle-social-login-experience"&gt;
Unlock Social Login with Logto
&lt;/a&gt;
&lt;/center&gt;




&lt;h2&gt;
  
  
  Increase conversion: Make 'em say yes
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Research shows that social login can significantly boost conversion rates, with an average improvement of 20%-40%.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Less is more, but choose wisely
&lt;/h3&gt;

&lt;p&gt;Facebook, Google, Apple, Twitter, LinkedIn, Microsoft, GitHub... they're the cool kids in town. Adding too many login options can overwhelm users during registration; or make it difficult for them to recall which provider they used during login. It's best to offer a minimum but relevant selection of providers. Typically, two providers are sufficient for most products.&lt;/p&gt;

&lt;h3&gt;
  
  
  Branding is key, for trust and usability
&lt;/h3&gt;

&lt;p&gt;Adhere to the branding guidelines of social providers to build trust and maintain a polished UI. For instance, Apple Store strictly reviews the usage of the Apple sign-in button. Facebook or Google sign-in buttons should display the user's avatar, username, or email. Google leverages its browser platform to offer a one-tap sign-in pop-up. You can quickly refer to the platform guidelines for &lt;a href="https://developers.facebook.com/docs/facebook-login"&gt;Facebook&lt;/a&gt;, &lt;a href="https://developers.google.com/identity/gsi/web/guides/overview"&gt;Google&lt;/a&gt;, &lt;a href="https://developer.apple.com/design/human-interface-guidelines/sign-in-with-apple"&gt;Apple&lt;/a&gt;, &lt;a href="https://api.slack.com/authentication/sign-in-with-slack#implementation"&gt;Slack&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Get quality data: Personalize like a pro
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Social login provides valuable user profile and social relationship data, allowing products to personalize user experiences quickly.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Ask nicely for the info you need
&lt;/h3&gt;

&lt;p&gt;While social providers offer access to users' public profiles (email, username, avatar), be cautious when requesting additional user information during registration for personalizing product experience. Requesting excessive or non-essential private details without a clear purpose may trigger user skepticism. Instead, prioritize a seamless registration process, gradually seeking additional information as users become engaged with your product.&lt;/p&gt;

&lt;h3&gt;
  
  
  Sync once or forever, you decide
&lt;/h3&gt;

&lt;p&gt;Typically, user information is synced from social platforms during the first login, allowing users to make changes within the app's profile afterward. But if you prefer the product to always utilize the latest profile information from the social provider, you can choose to sync user information during each login.&lt;/p&gt;

&lt;h2&gt;
  
  
  Retain users: Don't let them slip away
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Did you know that 92% of users will ditch a website if they forget their username or password? Social login comes to the rescue, but it might not be enough on its own.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Email and phone options: a backup plan
&lt;/h3&gt;

&lt;p&gt;Not all users prefer social login, as they may have concerns about privacy or desire anonymity. Therefore, it's essential to offer email or phone number-based login methods alongside social login. Even for users who choose social login, acquiring their email or phone number is necessary. This helps prevent any disruptions caused by social providers discontinuing services or being affected by regional policies. It also enables your marketing team to maintain communication with users through emails or SMS for promotions or re-engagement campaigns.&lt;/p&gt;

&lt;h3&gt;
  
  
  One account, no more confusion
&lt;/h3&gt;

&lt;p&gt;Recently, while attempting to sign in to ChatGPT, I occasionally found myself unsure whether I had used email sign-in or Google sign-in. This confusion resulted in encountering the following interface and necessitated logging out and back in. I have also experienced a similar issue with Pinterest.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--VjKXpzod--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zvoks5d2ej934v1lwd7z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--VjKXpzod--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zvoks5d2ej934v1lwd7z.png" alt="ChatGPT authentication error page" width="800" height="301"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Many users prefer to have a single account, except for those seeking multiple free trial periods. However, after accessing the product, users generally don't navigate to the account management page to link accounts since it's too cumbersome.&lt;/p&gt;

&lt;p&gt;Therefore, during registration, an automated and seamless account linking process, with the user's consent, can yield the best results. Here's an optimized design approach when requesting a user's email:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;If the social provider gives us a trustworthy email that isn't already registered, we automatically link it during registration. Easy peasy!&lt;/li&gt;
&lt;li&gt;If the social provider gives us a trustworthy email, but it's already associated with an account, we ask the user if they want to link their existing account or link another one.&lt;/li&gt;
&lt;li&gt;If the social provider doesn't provide a reliable email, we kindly request the user to provide one during registration.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--t2f6EiKr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rmqxmu954xs12aoa8hyz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--t2f6EiKr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rmqxmu954xs12aoa8hyz.png" alt="The social login flowchart for a seamless user experience" width="800" height="633"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Efficiently configure social login
&lt;/h2&gt;

&lt;p&gt;If you're loving this seamless experience and don't want the hassle of developing it yourself, give Logto a try! It's a quick and easy way to integrate social connectors and level up your social login game. We offer preconfigured options for popular social connectors, and you can also create your own social connectors using standard protocols like OAuth 2.0, OIDC, and SAML.&lt;/p&gt;

&lt;p&gt;The figure below shows the Logto console for configuring end users' sign-in experience social login. You can easily add or remove social connectors, customize the branding, and set up different sign-in methods.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--rZRQchp7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jo5t5r6l7h66893jlsuy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rZRQchp7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jo5t5r6l7h66893jlsuy.png" alt="Logto web console for sign-in experience" width="800" height="376"&gt;&lt;/a&gt;&lt;/p&gt;





&lt;center&gt;
&lt;a href="https://logto.io/?utm_source=dev&amp;amp;utm_campaign=tackle-social-login-experience"&gt;
Configure your social login in minutes
&lt;/a&gt;
&lt;/center&gt;




&lt;p&gt;We value your insights and welcome open communication if you have any better suggestions.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>design</category>
      <category>beginners</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Password isn't dying</title>
      <dc:creator>gao-sun</dc:creator>
      <pubDate>Fri, 16 Jun 2023 02:43:15 +0000</pubDate>
      <link>https://forem.com/logto/password-isnt-dying-2hh1</link>
      <guid>https://forem.com/logto/password-isnt-dying-2hh1</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Last year, there were news articles circulating on the internet claiming that big tech companies like &lt;a href="https://www.techradar.com/news/the-worlds-biggest-tech-companies-want-to-kill-passwords-on-password-day"&gt;Apple, Google, and Microsoft were joining forces to eliminate passwords&lt;/a&gt;. Some startups even declared that passwords were obsolete and outdated. After delving into the realm of identity management for months, I began to question the validity and practicality of these claims.&lt;/p&gt;

&lt;h2&gt;
  
  
  What does a password do?
&lt;/h2&gt;

&lt;p&gt;At first glance, the answer seems obvious: passwords are used for signing in and verifying identities. However, I hold a different viewpoint if you consider the fact that passwords cannot truly verify who you are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When a user signs in to a website with an email and password, the website has no way of confirming the actual person behind those credentials. It could be a human or even a cat.&lt;/li&gt;
&lt;li&gt;Anyone can unlock an iPhone with the correct PIN.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In reality, the purpose of a password is to anonymously prove ownership of something: a user account, a device, or access to a door.&lt;/p&gt;

&lt;h2&gt;
  
  
  The current “password killers”
&lt;/h2&gt;

&lt;p&gt;The companies mentioned earlier have proposed various "password killers." Many claim to be safer alternatives that eliminate the need for users to remember complex, static passwords during authentication. However, most of these alternatives are not entirely practical for completely removing passwords.&lt;/p&gt;

&lt;h3&gt;
  
  
  FIDO authentication
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://fidoalliance.org/"&gt;FIDO&lt;/a&gt; (Fast Identity Online) authentication, as explained in the &lt;a href="https://fidoalliance.org/how-fido-works/"&gt;official documentation&lt;/a&gt;, utilizes public key cryptography techniques for registration and sign-in (it's worth noting that &lt;a href="https://www.w3.org/TR/webauthn-2/"&gt;WebAuthn&lt;/a&gt; is a core component of FIDO2 specifications). On the surface, the process appears appealing:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3RoP735T--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a9gbpd6ncsprlteuk4v3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3RoP735T--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a9gbpd6ncsprlteuk4v3.png" alt="FIDO flow" width="800" height="94"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Simple, right? Unfortunately, there's a significant hurdle in the way: compatibility. When compared to the traditional combination of "identifier and password," FIDO authentication requires:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Websites or apps to support FIDO.&lt;/li&gt;
&lt;li&gt;Browsers and/or operating systems to support FIDO.&lt;/li&gt;
&lt;li&gt;User devices to have a user-friendly verification mechanism.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Failure to meet any of these requirements renders FIDO authentication unavailable, forcing a fallback to other methods.&lt;/p&gt;

&lt;p&gt;Moreover, even if all the conditions are met, what qualifies as a "user-friendly verification mechanism" on a device? Currently, it may involve biometric methods like fingerprint or face recognition, accompanied by a fallback option such as a PIN code, a.k.a. password. In the end, we're brought back to square one.&lt;/p&gt;

&lt;p&gt;Technically, it's not a "password killer" but rather a more secure and user-friendly authentication or verification process protected by passwords.&lt;/p&gt;

&lt;h3&gt;
  
  
  One-time password
&lt;/h3&gt;

&lt;p&gt;Even though the name includes the term “password”, &lt;a href="https://en.wikipedia.org/wiki/One-time_password"&gt;one-time passwords&lt;/a&gt; (OTPs) are not traditional passwords because they are dynamic. There are two popular types of OTPs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Time-based One-Time Password (TOTP): Generated algorithmically using the current time as a source of uniqueness. It's commonly used in &lt;a href="https://en.wikipedia.org/wiki/Multi-factor_authentication"&gt;Multi-factor Authentication&lt;/a&gt; (MFA) or 2FA.&lt;/li&gt;
&lt;li&gt;SMS/Email One-Time Password: Generated on the server using random algorithms. In some countries, it has been widely adopted as a primary sign-in method.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;TOTPs may not be as widely recognized by name. For example, when a website prompts you to set up MFA and use an app like Google Authenticator or Duo to scan a QR code, you're most likely using TOTP. You may have also noticed that the website often displays a long "recovery code" and advises you to save it as it will only be shown once. Some websites even encourage users to print it on paper. In essence, this recovery code functions like a long password.&lt;/p&gt;

&lt;p&gt;As for SMS/Email OTPs, they can be expensive and unreliable:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Building an SMS or email sender from scratch requires setup.&lt;/li&gt;
&lt;li&gt;Email senders need to establish a positive "&lt;a href="https://messagebird.com/guides/o/email-sender-reputation"&gt;reputation&lt;/a&gt;" to improve deliverability, otherwise, the sender may be flagged as spam.&lt;/li&gt;
&lt;li&gt;Each country has its own mobile network operators, leading to unpredictable delivery times and notable costs for sending SMS, especially for startups.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Biometrics
&lt;/h3&gt;

&lt;p&gt;The term "biometric" refers to using only biometric methods for online authentication. In fact, there's a fundamental difference when compared to other methods: biometric authentication shifts the original task of "proving ownership of something" to "proving who you are." Due to privacy concerns, biometric methods are primarily employed for local authentication.&lt;/p&gt;

&lt;h2&gt;
  
  
  Password isn’t perfect, though
&lt;/h2&gt;

&lt;p&gt;As we can see, "password killers" are essentially hiding passwords or using passwords as fallback options. Here's a summary of the advantages of passwords based on our discussion:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Accessibility and compatibility: Passwords can be used in various systems and are accessible to a wide range of users.&lt;/li&gt;
&lt;li&gt;Cost-effectiveness and versatility: Password-based authentication are generally cost-effective than other methods and adaptable to different scenarios.&lt;/li&gt;
&lt;li&gt;Anonymity and privacy: Passwords allow for anonymous usage and protect user privacy.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But every coin has two sides. While passwords have their advantages, relying solely on them for authentication poses significant vulnerabilities. They can be challenging for end-users to manage, and if website owners fail to follow proper security practices, passwords become easy to compromise. Dangerous security practices include, but are not limited to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Allowing for weak or leaked passwords.&lt;/li&gt;
&lt;li&gt;Lack of enforcing HTTPS for connections.&lt;/li&gt;
&lt;li&gt;Use of insecure hashing algorithms.&lt;/li&gt;
&lt;li&gt;Failure to adhere strictly to battle-tested standards like &lt;a href="https://oauth.net/"&gt;OAuth&lt;/a&gt; or &lt;a href="https://openid.net/specs/openid-connect-core-1_0.html"&gt;OpenID Connect&lt;/a&gt; (OIDC).&lt;/li&gt;
&lt;li&gt;Exposing the database to the public.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;I do not intend to undermine any of the authentication methods mentioned above. On the contrary, as I work on building Logto, I have developed a deep respect for these remarkable authentication methods and the individuals behind them.&lt;/p&gt;

&lt;p&gt;Nevertheless, achieving 100% security is an unattainable goal. What we can strive for is to reduce the possibility of attacks. One effective approach is to combine password-based authentication with one-time passwords based on the current device or environment, which adds an extra layer of verification and has been widely adopted. By leveraging the strengths of different authentication techniques, we can create a layered approach that provides stronger protection.&lt;/p&gt;

&lt;p&gt;In closing, rather than focusing on buzzwords like "password killer" when passwords are not truly being eliminated, it would be more valuable to concentrate on striking a balance between security and user experience. This entails understanding the strengths and limitations of various authentication methods and implementing them in a way that ensures both the security of user data and a seamless user experience.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>security</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Simplify Outline authentication with Logto</title>
      <dc:creator>gao-sun</dc:creator>
      <pubDate>Wed, 24 May 2023 19:27:51 +0000</pubDate>
      <link>https://forem.com/logto/simplify-outline-authentication-with-logto-1077</link>
      <guid>https://forem.com/logto/simplify-outline-authentication-with-logto-1077</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://logto.io/"&gt;Logto&lt;/a&gt; is an effortless identity solution with all the features you need. It supports various sign-in methods, including username, email, phone number, and popular social sign-ins like Google and GitHub.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/outline/outline"&gt;Outline&lt;/a&gt; serves as a knowledge base for growing teams.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The best part is that both Logto and Outline are open-source. In this article, we will demonstrate how to use Logto as an &lt;a href="https://openid.net/specs/openid-connect-core-1_0.html"&gt;OpenID Connect&lt;/a&gt; (OIDC) identity provider for Outline.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;To get started, make sure you have the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A running Logto instance or access to a Logto Cloud account.&lt;/li&gt;
&lt;li&gt;An Outline hosting environment with access to environment variables.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Configure Logto
&lt;/h2&gt;

&lt;p&gt;If you are self-hosting Logto, refer to the Logto "&lt;a href="https://docs.logto.io/docs/tutorials/get-started/"&gt;Get started&lt;/a&gt;" documentation to set up your Logto instance.&lt;/p&gt;

&lt;p&gt;Open Logto Console by entering the URL &lt;code&gt;https://cloud.logto.io/&lt;/code&gt; if you are using Logto Cloud, or the endpoint you have set up for self-hosting.&lt;/p&gt;




&lt;center&gt;
&lt;a href="http://cloud.logto.io?sign_up=true&amp;amp;utm_source=dev&amp;amp;utm_medium=outline_auth"&gt;Open Logto Cloud and effortlessly complete the configuration&lt;/a&gt;
&lt;/center&gt;




&lt;p&gt;Next, navigate to the "Applications" tab and click on "Create Application".&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--aQlK6gmM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vzyvd6iq3la1lz6f2zya.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--aQlK6gmM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vzyvd6iq3la1lz6f2zya.png" alt="Applications tab" width="800" height="205"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the modal that appears, choose "Traditional Web" and provide an application name, such as "Outline". Then click on "Create Application”.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_pO6xNv---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bv35e7ai1vuta8zlxzzp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_pO6xNv---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bv35e7ai1vuta8zlxzzp.png" alt="Create application" width="800" height="634"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You will be directed to a tutorial page in Logto. Click on "Skip" at the top-right corner to proceed to the Application details page.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5tnjKoGd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qbba83j22i259u0fyalf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5tnjKoGd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qbba83j22i259u0fyalf.png" alt="Applications details" width="800" height="459"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the "Redirect URIs" section, enter the following value:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[your-outline-origin]/auth/oidc.callback
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For example, if you are hosting Outline on &lt;strong&gt;&lt;code&gt;http://localhost:3000&lt;/code&gt;&lt;/strong&gt;, the value should be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://localhost:3000/auth/oidc.callback
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7sYYeBet--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9xbx7aokyyo0h0hzn2af.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7sYYeBet--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9xbx7aokyyo0h0hzn2af.png" alt="Save changes" width="800" height="289"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click on the "Save Changes" button at the bottom. Once successful, keep this page open as it will be useful for the Outline configuration.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configure Outline
&lt;/h2&gt;

&lt;p&gt;Follow the steps outlined in the &lt;a href="https://docs.getoutline.com/s/hosting/"&gt;Outline hosting guide&lt;/a&gt; until you reach the authentication configuration step. Since Outline supports OIDC-compatible authentication providers by default, you can easily find most of the required configuration values on the Logto application details page.&lt;/p&gt;

&lt;p&gt;Refer to the following table for the necessary configuration details:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Outline Environment Variable&lt;/th&gt;
&lt;th&gt;Logto Display Name&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;OIDC_CLIENT_ID&lt;/td&gt;
&lt;td&gt;App ID&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;OIDC_CLIENT_SECRET&lt;/td&gt;
&lt;td&gt;App Secret&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;OIDC_AUTH_URI&lt;/td&gt;
&lt;td&gt;Authorization Endpoint&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;OIDC_TOKEN_URI&lt;/td&gt;
&lt;td&gt;Token Endpoint&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;OIDC_USERINFO_URI&lt;/td&gt;
&lt;td&gt;Userinfo Endpoint&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Here's another table containing additional variables:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Outline Environment Variable&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;OIDC_USERNAME_CLAIM&lt;/td&gt;
&lt;td&gt;Set to username&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;OIDC_DISPLAY_NAME&lt;/td&gt;
&lt;td&gt;Optional - customize as needed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;OIDC_SCOPES&lt;/td&gt;
&lt;td&gt;Keep default; no need to set&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Self-hosted only: Configure email sign-in in Logto
&lt;/h2&gt;

&lt;p&gt;Since Outline requires user email to be provided, you need to configure email sign-in or a social sign-in that provides trustworthy email address, such as Google sign-in.&lt;/p&gt;

&lt;p&gt;See &lt;a href="https://docs.logto.io/docs/tutorials/get-started/passwordless-sign-in-by-adding-connectors/"&gt;Passwordless sign-in by adding connectors&lt;/a&gt; to learn more about configuring passwordless sign-in in Logto.&lt;/p&gt;

&lt;h2&gt;
  
  
  Checkpoint: Test Logto and Outline integration
&lt;/h2&gt;

&lt;p&gt;Start the Outline instance and access its endpoint. You should see a button in the center labeled "Continue with OpenID Connect"; it can be customized by setting the &lt;code&gt;OIDC_DISPLAY_NAME&lt;/code&gt; environment variable.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vxvTM7gj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j9jllqpeitjli98iychk.png" class="article-body-image-wrapper"&gt;&lt;img alt="Outline sign-in page" src="https://res.cloudinary.com/practicaldev/image/fetch/s--vxvTM7gj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j9jllqpeitjli98iychk.png" width="800" height="470"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click on the button, and you will be directed to the Logto sign-in experience.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Pabvk15G--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2idj1837d4oyngrhib5g.png" class="article-body-image-wrapper"&gt;&lt;img alt="Logto sign-in experience" src="https://res.cloudinary.com/practicaldev/image/fetch/s--Pabvk15G--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2idj1837d4oyngrhib5g.png" width="800" height="831"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If everything has been configured correctly, once you complete the sign-in or registration process in Logto, you will be redirected back to Outline. You can then see your personal information displayed in the bottom left corner of the page.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--zgzxUYu7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tfne3r7trc38lwu3ctew.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zgzxUYu7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tfne3r7trc38lwu3ctew.png" alt="Outline home" width="800" height="440"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you encounter any issues during the integration, please don't hesitate to contact us via email at &lt;a href="mailto:contact@logto.io"&gt;contact@logto.io&lt;/a&gt; or &lt;a href="https://discord.gg/UEPaF3j5e6"&gt;join our Discord server&lt;/a&gt;!&lt;/p&gt;




&lt;center&gt;&lt;a href="http://cloud.logto.io?sign_up=true&amp;amp;utm_source=dev&amp;amp;utm_medium=outline_auth"&gt;Try Logto today&lt;/a&gt;&lt;/center&gt;

</description>
      <category>tutorial</category>
      <category>beginners</category>
      <category>javascript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Implement ChatGPT plugins user authentication with Logto</title>
      <dc:creator>gao-sun</dc:creator>
      <pubDate>Wed, 24 May 2023 19:18:07 +0000</pubDate>
      <link>https://forem.com/logto/implement-chatgpt-plugins-user-authentication-with-logto-18bo</link>
      <guid>https://forem.com/logto/implement-chatgpt-plugins-user-authentication-with-logto-18bo</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://logto.io/"&gt;Logto&lt;/a&gt; is an effortless identity solution with all the features you need. It supports various sign-in methods, including username, email, phone number, and popular social sign-ins like Google and GitHub.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://openai.com/blog/chatgpt-plugins"&gt;ChatGPT plugins&lt;/a&gt; are tools designed specifically for language models, and help ChatGPT access up-to-date information, run computations, or use third-party services.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In this article, we will demonstrate how to use Logto as an OAuth identity provider for ChatGPT plugins. If you're curious about the importance of authentication for your plugins, check out this post: &lt;a href="https://blog.logto.io/authentication-the-differentiator-for-chatgpt-plugins/?utm_source=dev&amp;amp;utm_medium=chatgpt_plugins_auth"&gt;Authentication: The differentiator for ChatGPT plugins&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;We want to give a big shoutout to our community member, kAd, for their invaluable help in validating this integration. We are extremely grateful for their efforts, as this tutorial wouldn't have been possible without their assistance. Tc001 also provided meaningful input during the process.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;To get started, make sure you have the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A running Logto instance or access to a Logto Cloud account.&lt;/li&gt;
&lt;li&gt;A ChatGPT account with developer access for plugins. While ChatGPT plugins are available to all Plus members, you'll still need to join the waitlist to get developer access.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Configure Logto
&lt;/h2&gt;

&lt;p&gt;If you are self-hosting Logto, refer to the Logto "&lt;a href="https://docs.logto.io/docs/tutorials/get-started/"&gt;Get started&lt;/a&gt;" documentation to set up your Logto instance.&lt;/p&gt;

&lt;p&gt;Open Logto Console by entering the URL &lt;code&gt;https://cloud.logto.io/&lt;/code&gt; if you are using Logto Cloud, or the endpoint you have set up for self-hosting.&lt;/p&gt;




&lt;center&gt;
&lt;a href="http://cloud.logto.io?sign_up=true&amp;amp;utm_source=dev&amp;amp;utm_medium=chatgpt_plugins_auth"&gt;Open Logto Cloud and effortlessly complete the configuration&lt;/a&gt;
&lt;/center&gt;




&lt;p&gt;Next, navigate to the "Applications" tab and click on "Create Application".&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KRzU6AoF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j7d5wf4b09hjgpgjjxx1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KRzU6AoF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j7d5wf4b09hjgpgjjxx1.png" alt="Applications tab" width="800" height="205"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the modal that appears, choose "Traditional Web" and provide an application name, such as "My ChatGPT plugin." Click on "Create Application.”&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--iUO2c4vd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7kf5rl93usfyec93bvuy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--iUO2c4vd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7kf5rl93usfyec93bvuy.png" alt="Create application" width="800" height="638"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You will be directed to a tutorial page in Logto. Click on "Skip" at the top-right corner to proceed to the Application details page.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--QCWwL-f1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zpnrsm9peddiwem5qlse.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--QCWwL-f1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zpnrsm9peddiwem5qlse.png" alt="Applications details" width="800" height="387"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the "Redirect URIs" section, enter the following value:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://chat.openai.com/aip/[your-plugin-id]/oauth/callback
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For example, if your plugin ID is &lt;code&gt;foo123&lt;/code&gt;, the value should be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://chat.openai.com/aip/foo123/oauth/callback
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--rwBGieRd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/irueutrnjvdr69xtfsg5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rwBGieRd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/irueutrnjvdr69xtfsg5.png" alt="Redirect URIs" width="800" height="71"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Scroll down to the "Advanced settings" section and enable "Always issue Refresh Token" (this helps ChatGPT maintain the authentication state).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--CTThN4Vd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v29aof9vtotg5opr8h44.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--CTThN4Vd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v29aof9vtotg5opr8h44.png" alt="Always issue Refresh Token toggle" width="800" height="145"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click on the "Save Changes" button at the bottom. Keep this page open as it will be useful for configuring plugin later.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--OVHSpamK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gsmthqck97rc33i2svqe.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--OVHSpamK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gsmthqck97rc33i2svqe.png" alt="Save changes" width="800" height="46"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Configure ChatGPT plugin
&lt;/h2&gt;

&lt;p&gt;Follow the steps outlined in the &lt;a href="https://platform.openai.com/docs/plugins/introduction"&gt;ChatGPT Plugins documentation&lt;/a&gt; until you reach the authentication configuration step. Since ChatGPT plugin supports OAuth authentication providers, you can easily find most of the required configuration values on the Logto application details page.&lt;/p&gt;

&lt;p&gt;When setting up your plugin with ChatGPT, you will need to provide your OAuth Client ID and Client Secret. These correspond to the “App ID” and “App Secret” on the Logto page.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1zayhYXc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hnfsiwjdgv3w8l6bg6xf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1zayhYXc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hnfsiwjdgv3w8l6bg6xf.png" alt="ChatGPT plugin OAuth credentials" width="800" height="178"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For the auth section in the &lt;code&gt;ai-plugin.json&lt;/code&gt;, use the following template:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"auth"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"oauth"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"client_url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"[Authorization Endpoint in Logto]"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"scope"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"openid profile email"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"authorization_url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"[Token Endpoint in Logto]"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"authorization_content_type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"application/json"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"verification_tokens"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"openai"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Replace_this_string_with_the_verification_token_generated_in_the_ChatGPT_UI"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Remember to replace the &lt;code&gt;client_url&lt;/code&gt; and &lt;code&gt;authorization_url&lt;/code&gt; values with the respective values from Logto. You can find and copy them from the "Advanced settings" section on the Logto application details page.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7P2QrP1Q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w2nknkkcxm1bj3y9nq9q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7P2QrP1Q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w2nknkkcxm1bj3y9nq9q.png" alt="Advanced settings" width="800" height="135"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Checkpoint: Test Logto and ChatGPT plugin integration
&lt;/h2&gt;

&lt;p&gt;The ChatGPT UI will automatically prompt you to install the plugin. Once successful, you will see a dialog with a button that says "Log in with [your plugin name]."&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--0pMWG0XA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tcoyk6gisuh9x7tygnua.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0pMWG0XA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tcoyk6gisuh9x7tygnua.png" alt="ChatGPT plugin login" width="800" height="144"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click on the button, and you will be directed to the Logto sign-in experience.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KHHJyDRd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o8y0k9wp7kv81dk5n6fb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KHHJyDRd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o8y0k9wp7kv81dk5n6fb.png" alt="Logto sign-in experience" width="800" height="831"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If everything is configured correctly, once you complete the sign-in or registration process in Logto, you will be redirected back to ChatGPT. From now on, every request sent by ChatGPT to your plugin server will carry the Authorization header, allowing you to decode and verify the token in your API.&lt;/p&gt;

&lt;p&gt;And that wraps up our guide on implementing ChatGPT plugins user authentication with Logto. If you encounter any issues during the integration, please don't hesitate to contact us via email at &lt;a href="mailto:contact@logto.io"&gt;contact@logto.io&lt;/a&gt; or &lt;a href="https://discord.gg/UEPaF3j5e6"&gt;join our Discord server&lt;/a&gt;!&lt;/p&gt;




&lt;center&gt;&lt;a href="http://cloud.logto.io?sign_up=true&amp;amp;utm_source=dev&amp;amp;utm_medium=chatgpt_plugins_auth"&gt;Try Logto today&lt;/a&gt;&lt;/center&gt;

</description>
      <category>chatgpt</category>
      <category>webdev</category>
      <category>tutorial</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Announcing Logto Cloud (Preview) and OSS General Availability</title>
      <dc:creator>gao-sun</dc:creator>
      <pubDate>Mon, 20 Mar 2023 10:05:02 +0000</pubDate>
      <link>https://forem.com/logto/announcing-logto-cloud-preview-and-oss-general-availability-52mo</link>
      <guid>https://forem.com/logto/announcing-logto-cloud-preview-and-oss-general-availability-52mo</guid>
      <description>&lt;p&gt;🚀 Logto Cloud (Preview) has launched on &lt;a href="https://www.producthunt.com/posts/logto-cloud-preview"&gt;Product Hunt&lt;/a&gt;. Come and support us!&lt;/p&gt;




&lt;p&gt;Hi there,&lt;/p&gt;

&lt;p&gt;I’m Gao, one of the creators of &lt;a href="https://logto.io/"&gt;Logto&lt;/a&gt;. I remember feeling nervous last July - that’s the date we launched the first beta version of Logto OSS.&lt;/p&gt;

&lt;p&gt;To our surprise, we had some deep conversations with the community from the outset. We talked about the terrible developer experience of building authentication, even with existing products, and the dramatic costs of current industry leaders. As developers ourselves, we feel you and that's why we started building Logto.&lt;/p&gt;

&lt;p&gt;These conversations drove us towards a brighter future. I want to say a big thank you to everyone we connected with during our beta! Only with your help, we can shape the future of identity development together.&lt;/p&gt;

&lt;p&gt;Today, we're excited to announce that we've made a significant step forward with Logto: we're officially launching Logto Cloud (Preview) to the public!&lt;/p&gt;

&lt;p&gt;I know that most of you got started with Logto through the online demo (huge credit to GitPod) or the docker-compose file. With Logto Cloud (Preview), you can even forget all the operational overheads when developing with Logto. Simply sign in and a new Logto instance will be ready for you. If you're developing locally, the only thing you need to change in your code is the Logto endpoint.&lt;/p&gt;

&lt;p&gt;Assuming you are familiar with cloud products, here are some quick answers to frequently asked questions:&lt;/p&gt;

&lt;h3&gt;
  
  
  What is the pricing model?
&lt;/h3&gt;

&lt;p&gt;We are still finalizing our pricing model, but rest assured that we are working hard to make our product much more affordable than similar offerings currently on the market. We believe it should be more usage-based, rather than charging per seat for a customer-facing scenario.&lt;/p&gt;

&lt;p&gt;Logto Cloud will remain free while in preview. We would love to explore the appropriate and sustainable pricing model with you. Feel free to send us an email or schedule a meeting with us.&lt;/p&gt;

&lt;h3&gt;
  
  
  How will you process data?
&lt;/h3&gt;

&lt;p&gt;We have a strong belief in building trust and maintaining transparency. During the preview period, all Logto data will stay in the Azure West Europe region. See our Privacy Policy for more details if you are interested.&lt;/p&gt;

&lt;h3&gt;
  
  
  Will you keep data when the preview ends?
&lt;/h3&gt;

&lt;p&gt;Yes. Your tenant will seamlessly transition to Logto Cloud once the preview period ends. You can also request to have your data physically removed at any time if needed. See our Terms of Use for more details.&lt;/p&gt;

&lt;h3&gt;
  
  
  Will you stop open-source?
&lt;/h3&gt;

&lt;p&gt;No! Open-source is the core of our product and we believe it always will be. We will try our best to align between OSS and Cloud, and make sure you have full confidence that Logto OSS is backing you up.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Invitation&lt;/strong&gt;&lt;br&gt;
With gratitude, we invite you to enter Logto Cloud via &lt;a href="https://cloud.logto.io/"&gt;this link&lt;/a&gt;. You can find more details about Logto Cloud (Preview) &lt;a href="https://docs.logto.io/about/cloud-preview/"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The other role today is the General Availability version of &lt;a href="https://github.com/logto-io/logto/"&gt;Logto OSS&lt;/a&gt;. After multiple rounds of beta versions and release candidates, we are happy to announce the first release version of Logto OSS. Let’s quickly go through the major updates since last July:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A brand new end-user Sign-In Experience with superior customizability on sign-in and sign-up flows.&lt;/li&gt;
&lt;li&gt;10+ new connectors, including multiple open-standard connectors, such as OAuth 2.0 and SAML.&lt;/li&gt;
&lt;li&gt;Role-Based Access Control that conforms to the NIST model.&lt;/li&gt;
&lt;li&gt;Fully customizable translations with 8 languages built-in.&lt;/li&gt;
&lt;li&gt;Machine-to-Machine apps and Web Hooks for building programmatic connections between Logto and your services.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We received valuable feedback from our community and have incorporated it into our recent priorities:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add Single Sign-On (SSO) support to solidly bridge your product with your customers' identities.&lt;/li&gt;
&lt;li&gt;Implement Multi-Factor Authentication (MFA) for enhanced security requirements.&lt;/li&gt;
&lt;li&gt;Introduce Dynamic Organizations, which unlocks much more business potential for your product while keeping all your customers' identities in a single source of truth.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you notice anything missing, please do not hesitate to reach out to us by sending an email or joining our Discord server.&lt;/p&gt;

&lt;p&gt;We could not have made it this far without the support of our community. Although this is a meaningful milestone for Logto, we believe our journey is just beginning.&lt;/p&gt;

&lt;p&gt;Building an identity product is a serious task, so leave the headache to us. We hope you enjoy using Logto, and let's meet on the cloud!&lt;/p&gt;

&lt;p&gt;Gao&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>beginners</category>
      <category>opensource</category>
    </item>
    <item>
      <title>How to build GitHub sign-in with React and Logto</title>
      <dc:creator>gao-sun</dc:creator>
      <pubDate>Wed, 08 Mar 2023 11:53:44 +0000</pubDate>
      <link>https://forem.com/logto/how-to-build-github-sign-in-with-react-and-logto-2hha</link>
      <guid>https://forem.com/logto/how-to-build-github-sign-in-with-react-and-logto-2hha</guid>
      <description>&lt;p&gt;&lt;strong&gt;For our new friends&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://logto.io" rel="noopener noreferrer"&gt;Logto&lt;/a&gt; is a cost-effective open-source alternative to Auth0. It offers OpenId Connect (OIDC) based authentication and authorization, with modern features like passwordless sign-in and role-based access control.&lt;/p&gt;




&lt;p&gt;
  In this article, we will go through the steps to quickly build the GitHub sign-in
  experience (user authentication) with
  &lt;a href="https://reactjs.org/" rel="noopener noreferrer"&gt;
    React
  &lt;/a&gt;
  &lt;span&gt; and &lt;/span&gt;
  &lt;a href="https://logto.io" rel="noopener noreferrer"&gt;
    Logto
  &lt;/a&gt;
  .
&lt;/p&gt;

&lt;h2&gt;
  
  
  Create an application in Logto
&lt;/h2&gt;

&lt;p&gt;In you browser, open a new tab and enter the link of Logto Admin Console.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjuuthfjg232g1ad6cyxq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjuuthfjg232g1ad6cyxq.png" alt="Create application"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once the page is loaded, in the "Get Started" tab, click the "Create" button on the right, and the browser will redirect to the Application tab.&lt;/p&gt;

&lt;h3&gt;
  
  
  Choose your application type
&lt;/h3&gt;

&lt;p&gt;In the opening modal, select the "Single Page App" option as the application type.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fre5612ukhgy92fxbsk8q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fre5612ukhgy92fxbsk8q.png" alt="Create Application modal"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Enter application name
&lt;/h3&gt;

&lt;p&gt;Enter the application name, e.g., "Bookstore," and click "Create Application."&lt;/p&gt;

&lt;p&gt;🎉 Ta-da! You just created your first application in Logto. You'll see a congrats page which includes a detailed integration guide. Follow the guide to see what the experience will be in your application.&lt;/p&gt;

&lt;h2&gt;
  
  
  Integrate Logto SDK
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Add Logto SDK as a dependency
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm i @logto/react &lt;span class="c"&gt;# or yarn add / pnpm add&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Init LogtoClient
&lt;/h3&gt;

&lt;p&gt;Import and use &lt;code&gt;LogtoProvider&lt;/code&gt; to provide a Logto context:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;LogtoProvider&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;LogtoConfig&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@logto/react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;LogtoConfig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;endpoint&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;your-logto-endpoint&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// E.g. http://localhost:3001&lt;/span&gt;
  &lt;span class="na"&gt;appId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;your-application-id&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;LogtoProvider&lt;/span&gt; &lt;span class="na"&gt;config&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;YourAppContent&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;LogtoProvider&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In the following code snippets, we assume your app is running on &lt;code&gt;http://localhost:3000&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Sign-in flow
&lt;/h3&gt;

&lt;p&gt;The sign-in flow can be simplified as:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp3kxyjt9b1hjrffrv3lw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp3kxyjt9b1hjrffrv3lw.png" alt="Web sign-in flow"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Configure Redirect URI
&lt;/h3&gt;

&lt;p&gt;
  Let's switch to the Application details page of Admin Console in this section. Add a Redirect
  URI &lt;code&gt;http://localhost:3000/callback&lt;/code&gt; and click "Save Changes".
&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4i834c98mhdg1x46xuc8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4i834c98mhdg1x46xuc8.png" alt="Redirect URI in Admin Console"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.oauth.com/oauth2-servers/redirect-uris/" rel="noopener noreferrer"&gt;Redirect URI&lt;/a&gt; is an OAuth 2.0 concept which implies the location should redirect after authentication.&lt;/p&gt;

&lt;h3&gt;
  
  
  Implement a sign-in button
&lt;/h3&gt;

&lt;p&gt;We provide two hooks &lt;code&gt;useHandleSignInCallback()&lt;/code&gt; and &lt;code&gt;useLogto()&lt;/code&gt; which can help you easily manage the authentication flow.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Before calling &lt;code&gt;.signIn()&lt;/code&gt;, make sure you have correctly configured Redirect URI in Admin Console.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Go back to your IDE/editor, use the following code to implement the sign-in button:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useLogto&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@logto/react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;SignIn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;signIn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;isAuthenticated&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useLogto&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isAuthenticated&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Signed in&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;signIn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http://localhost:3000/callback&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Sign In&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Handle redirect
&lt;/h3&gt;

&lt;p&gt;We're almost there! In the last step, we use &lt;code&gt;http://localhost:3000/callback&lt;/code&gt; as the Redirect URI, and now we need to handle it properly.&lt;/p&gt;

&lt;p&gt;First let's create a callback component:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useHandleSignInCallback&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@logto/react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Callback&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;isLoading&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useHandleSignInCallback&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Navigate to root path when finished&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="c1"&gt;// When it's working in progress&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isLoading&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Redirecting...&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally insert the code below to create a &lt;code&gt;/callback&lt;/code&gt; route which does NOT require authentication:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Assuming react-router&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Route&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/callback"&lt;/span&gt; &lt;span class="na"&gt;element&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Callback&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Test your integration&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Open your React app to test if the integration works. When you click the "Sign In" button, the page should be redirected to a Logto sign-in page, and you should be able to create a new account by entering username and password and complete the sign-in process.&lt;/p&gt;

&lt;h2&gt;
  
  
  Add GitHub connector
&lt;/h2&gt;

&lt;p&gt;To add a social connector, go to the "Connector" tab in the Admin Console, then click on "Social Connectors". From there, click "Add Social Connector".&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4rbkjq4vfjmqxnhrvpx3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4rbkjq4vfjmqxnhrvpx3.png" alt="Connector tab"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the openning modal, select "GitHub" and click "Next".&lt;/p&gt;

&lt;p&gt;On the next page, you will see a two-column layout with the README content on the left and configuration on the right.&lt;/p&gt;

&lt;p&gt;Feel free to follow the README file in place or read the following section to complete the configuration process. If you follow the in-place guide, you can skip the next section.&lt;/p&gt;

&lt;h2&gt;
  
  
  Set up GitHub OAuth app
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Sign in with GitHub account
&lt;/h3&gt;

&lt;p&gt;Go to the &lt;a href="https://github.com/" rel="noopener noreferrer"&gt;GitHub website&lt;/a&gt; and sign in with your GitHub account. You may register a new account if you don't have one.&lt;/p&gt;

&lt;h3&gt;
  
  
  Create and configure OAuth app
&lt;/h3&gt;

&lt;p&gt;Follow the &lt;a href="https://docs.github.com/en/developers/apps/building-oauth-apps/creating-an-oauth-app" rel="noopener noreferrer"&gt;creating an OAuth App&lt;/a&gt; guide, and register a new application.&lt;/p&gt;

&lt;p&gt;Name your new OAuth application in &lt;strong&gt;Application name&lt;/strong&gt; and fill up &lt;strong&gt;Homepage URL&lt;/strong&gt; of the app.&lt;br&gt;
You can leave &lt;strong&gt;Application description&lt;/strong&gt; field blank and customize &lt;strong&gt;Authorization callback URL&lt;/strong&gt; as &lt;code&gt;${your_logto_origin}/callback/${connector_id}&lt;/code&gt;. The &lt;code&gt;connector_id&lt;/code&gt; can be found on the top bar of the Logto Admin Console connector details page.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you encounter the error message "The redirect_uri MUST match the registered callback URL for this application." when logging in, try aligning the Authorization Callback URL of your GitHub OAuth App and your Logto App's redirect URL (of course, including the protocol) to resolve the issue.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We suggest not to check the box before &lt;strong&gt;Enable Device Flow&lt;/strong&gt;, or users who sign in with GitHub on mobile devices must confirm the initial sign-in action in the GitHub app. Many GitHub users do not install the GitHub mobile app on their phones, which could block the sign-in flow. Please ignore our suggestion if you are expecting end-users to confirm their sign-in flow. See details of &lt;a href="https://docs.github.com/en/developers/apps/building-oauth-apps/authorizing-oauth-apps#device-flow" rel="noopener noreferrer"&gt;device flow&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  Managing OAuth apps
&lt;/h3&gt;

&lt;p&gt;Go to the &lt;a href="https://github.com/settings/developers" rel="noopener noreferrer"&gt;OAuth Apps page&lt;/a&gt; and you can add, edit or delete existing OAuth apps.&lt;br&gt;
You can also find &lt;code&gt;Client ID&lt;/code&gt; and generate &lt;code&gt;Client secrets&lt;/code&gt; in OAuth app detail pages.&lt;/p&gt;
&lt;h3&gt;
  
  
  Compose the connector JSON
&lt;/h3&gt;

&lt;p&gt;Let's go back to Logto. Fill out the &lt;code&gt;clientId&lt;/code&gt; and &lt;code&gt;clientSecret&lt;/code&gt; field with &lt;em&gt;Client ID&lt;/em&gt; and &lt;em&gt;Client Secret&lt;/em&gt; you've got from OAuth app detail pages mentioned in the previous section.&lt;/p&gt;

&lt;p&gt;Here is an example of GitHub connector config JSON.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"clientID"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;your-client-id&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"clientSecret"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;your-client-secret&amp;gt;"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Config types
&lt;/h4&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Name&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;clientId&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;clientSecret&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Save your configuration
&lt;/h2&gt;

&lt;p&gt;
  Double check you have filled out necessary values in the Logto connector configuration area. Click
  "Save and Done" (or "Save Changes") and the GitHub connector should be available now.
&lt;/p&gt;

&lt;h2&gt;
  
  
  Enable GitHub connector in Sign-in Experience
&lt;/h2&gt;

&lt;p&gt;Switch to the "Sign-in Experience" tab, then click the "Sign-up and Sign-in" tab.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If it's the first time you enter the tab, you will see a quick introduction about Sign-in Experience and its basic configuration.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Febl3m1iyx4kh8hj5qz2x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Febl3m1iyx4kh8hj5qz2x.png" alt="Sign-in Experience tab"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;
Select "None" for the "Sign-up identifier" to provide minimum sign-up effort for GitHub sign-in, which may increase your conversion rate.
&lt;/p&gt;

&lt;p&gt;
  In the "Social sign-in" section, add "Add Social Connector" and choose "GitHub". Then
  you should be able to see a button with text "Continue with GitHub" in the preview
  section.
&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F30tugi3l3bxvmknjofnm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F30tugi3l3bxvmknjofnm.png" alt="Save changes"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Finally, click "Save Changes" on the bottom right corner.&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing and Validation
&lt;/h2&gt;

&lt;p&gt;Return to your React app. You should now be able to sign in with GitHub. Enjoy!&lt;/p&gt;

&lt;h2&gt;
  
  
  Further readings
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://docs.logto.io/docs/recipes/protect-your-api/" rel="noopener noreferrer"&gt;⚔️ Protect your API&lt;/a&gt; For native and single page apps, you'll need to call one or more API endpoints to retrieve and update data.&lt;br&gt;&lt;br&gt;
Learn more about identifying who's who and keeping your API secure.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.logto.io/docs/recipes/manage-users/" rel="noopener noreferrer"&gt;🧑‍🚀 Manage users&lt;/a&gt; We know you care about user management and activities, as we also do.&lt;br&gt;&lt;br&gt;
Learn more about how to know your users and see the figures like DAU and MAU graphically.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.logto.io/docs/recipes/localization/" rel="noopener noreferrer"&gt;🌐 Localization&lt;/a&gt; From one regional business to a global corporate, the willingness to offer the best user experience won't change.&lt;br&gt;&lt;br&gt;
You can change current language phrases or add a new language without friction.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.logto.io/blog/tags/ciam" rel="noopener noreferrer"&gt;🧑‍🎓 Customer IAM series&lt;/a&gt; Our serial blog posts about Customer (or Consumer) Identity and Access Management, from 101 to advanced topics and beyond.&lt;/p&gt;

</description>
      <category>react</category>
      <category>webdev</category>
      <category>beginners</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>CIAM 101: Authentication, Identity, SSO</title>
      <dc:creator>gao-sun</dc:creator>
      <pubDate>Tue, 07 Feb 2023 07:51:55 +0000</pubDate>
      <link>https://forem.com/logto/ciam-101-authentication-identity-sso-nb1</link>
      <guid>https://forem.com/logto/ciam-101-authentication-identity-sso-nb1</guid>
      <description>&lt;h2&gt;
  
  
  Background
&lt;/h2&gt;

&lt;p&gt;I began the build &lt;a href="https://logto.io"&gt;Logto&lt;/a&gt; because I noticed that Identity and Access Management (IAM) had become increasingly complex and expansive over time. The concept of IAM is even large enough to give rise to new concepts, such as WIAM (Workforce IAM) and CIAM (Customer IAM).&lt;/p&gt;

&lt;p&gt;While WIAM and CIAM share the same foundation, they have distinct use cases: WIAM is typically used for internal users, while CIAM is used for external customers. Some examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;WIAM&lt;/strong&gt; Your company has a unified identity system for employees, thus every one can use the same account to access company resources, such as software subscriptions, cloud computing services, etc.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CIAM&lt;/strong&gt; Your online bookstore requires a user identity system for customers and sellers. The sign-in experience is a critical part of onboarding, as it is located at the top of the conversion funnel.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://logto.io"&gt;Logto&lt;/a&gt; started with the CIAM for various reasons (we’ll have another article talking about this). During development, we realized that building a unified understanding across the team would be beneficial before taking our product to the next level. We hope this will also help you gain a better grasp of the IAM landscape.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The original post is on &lt;a href="https://docs.logto.io/blog/ciam-101-intro-authn-sso"&gt;Logto blog&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Let’s get started!&lt;/p&gt;

&lt;h2&gt;
  
  
  The basics of CIAM
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;ℹ️ Regardless of their differences, WIAM and CIAM both have the same foundation: authentication and authorization. These two concepts are at the core of their features.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In this article, we'll focus on the fundamental concepts of CIAM and problems we may meet during or after the authentication flow. We’ll also discuss Single Sign-On (SSO) and its related scenarios.&lt;/p&gt;

&lt;h3&gt;
  
  
  Authentication and authorization
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Definition&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Authentication (AuthN) answers the question “Who are you?”&lt;/li&gt;
&lt;li&gt;Authorization (AuthZ) answers the question “What can you do?”&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you discover something that does not fit into either of these two categories, it is likely not essential to the identity business.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Examples for authentication&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Password sign-in, passwordless sign-in, social sign-in, etc.&lt;/li&gt;
&lt;li&gt;Machine-to-Machine authentication&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Examples for authorization&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Role-based Access Control&lt;/li&gt;
&lt;li&gt;Attribute-based Access Control&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Examples for exceptions&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Non-identity data&lt;/li&gt;
&lt;li&gt;Web hooks&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Identity and Tenant
&lt;/h3&gt;

&lt;p&gt;Identity typically represents either a user or a machine. Upon successful authentication, an ID Token is issued as an Identity.&lt;/p&gt;

&lt;p&gt;In other words, the main purpose of authentication is to obtain an Identity.&lt;/p&gt;

&lt;p&gt;A Tenant is a group of identities:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_td5fgaM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ale4716z60zdlcgqp0mj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_td5fgaM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ale4716z60zdlcgqp0mj.png" alt="Image" width="800" height="253"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When we discuss "Multi-tenant", we are referring to multiple Logto instances that are identity-isolated from one another. In other words, multiple Logto instances.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--HiDnwkgD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c0i0wo46q8e6w3kczgx3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--HiDnwkgD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c0i0wo46q8e6w3kczgx3.png" alt="Image" width="800" height="254"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Note it has two &lt;strong&gt;isolated&lt;/strong&gt; identity systems, i.e. you cannot use the Identity of Tenant 1 in Tenant 2, even for the same identifier (email,  phone, etc.). It's like your Costco membership not being valid at Whole Foods.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;🧱 In short, there are “physical walls” between Tenants.&lt;/p&gt;

&lt;p&gt;ℹ️ The definition of "Tenant" varies across CIAM products. Some refer to the term "Organization" in Logto, which will be introduced later.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  App and Tenant
&lt;/h3&gt;

&lt;p&gt;Just like Identity, an App also belongs to a Tenant. Several things to remember:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;There is typically no direct relationship between an App and an Identity.

&lt;ul&gt;
&lt;li&gt;An Identity can represent an App, but there is no direct connection between them.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Like users, apps are also Tenant-level.&lt;/li&gt;
&lt;li&gt;Apps are code, while users are human.&lt;/li&gt;
&lt;li&gt;The sole purpose of Apps are to complete authentication, i.e. to obtain an Identity.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Identity Provider (IdP) and Service Provider (SP)
&lt;/h3&gt;

&lt;p&gt;The difference between these two providers is tricky but important.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Identity Provider&lt;/strong&gt; is a service that provides authentication (AuthN) and issues identities.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can find various explanations about Service Provider from Google, though they may not be satisfactory. In my mind, Service Provider is a relative concept:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Service Provider (or Relying Party in &lt;a href="https://openid.net/specs/openid-connect-core-1_0.html"&gt;OIDC&lt;/a&gt;)&lt;/strong&gt; is a service or client that initiates authentication (AuthN) and requests the result from Identity Providers.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Quiz
&lt;/h4&gt;

&lt;p&gt;Consider a typical social sign-in scenario:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--flzID5Tk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ao0qodnfuvmj7ckijdmn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--flzID5Tk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ao0qodnfuvmj7ckijdmn.png" alt="Image" width="800" height="160"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;❓ How many Service Providers and Identity Providers in this graph?&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Answer&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Both have two.&lt;/p&gt;

&lt;p&gt;iOS App is a service provider to Logto, while Logto is an identity provider.&lt;/p&gt;

&lt;p&gt;Logto is also a service provider to GitHub, while GitHub is an identity provider.&lt;/p&gt;

&lt;p&gt;Thus, Logto is a Service Provider also a Identity Provider.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Case study: A tech solution company
&lt;/h2&gt;

&lt;p&gt;You are a CTO of a tech solution company, you have over 100 business partners and you have delivered over 300 projects.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Each project is either a web app or a mobile app with a backend service.&lt;/li&gt;
&lt;li&gt;For each business partner, you want to refactor the user system to provide SSO across its projects.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;❓ How can Logto (or a CIAM product) help?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Answer&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Create a Logto instance for each business partner. Each partner holds a Tenant. Projects are mapped to "Apps" in Logto.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--DeH8_mat--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/incf7vi96k49zjekz5u4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--DeH8_mat--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/incf7vi96k49zjekz5u4.png" alt="Image" width="800" height="136"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Logto offers a universal sign-in experience (i.e. SSO) within a Tenant, so users don’t need to sign in again when accessing another app in the same Tenant if they already signed in.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  What we talk about when we talk about SSO
&lt;/h2&gt;

&lt;p&gt;We found the term “SSO” often causes confusion. We consider Single Sign-On(In) to be a behavior, not a business concept. Therefore, SSO does not equate to “SSO in WIAM”.&lt;/p&gt;

&lt;p&gt;When we say “it needs SSO”, it can refer to one of the following cases:&lt;/p&gt;

&lt;h3&gt;
  
  
  SSO Case 1
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;👉🏽 In a big corp, employees use the same credentials to sign in to all company-licensed resources (e.g. email, IM, cloud services).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It is the typical WIAM scenario. In this case, only one Identity Provider is involved. We don’t care for now.&lt;/p&gt;

&lt;h3&gt;
  
  
  SSO Case 2
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;👉🏽 End-users use the same credentials to sign in to all services developed by the same company (e.g. GSuite).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://logto.io"&gt;Logto&lt;/a&gt; is currently focusing on the approach outlined above. Multiple external identity providers, such as a third-party social sign-in provider, may exist independently and without connection.&lt;/p&gt;

&lt;p&gt;Despite this, Logto remains the single source of truth for Identities, simply "borrowing" them from other providers. In this case, Logto acts as both an Identity Provider (to GSuite apps) and a Service Provider (to external Identity Providers).&lt;/p&gt;

&lt;h3&gt;
  
  
  SSO Case 3
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;👉🏽 End-users can only use the specific Identity Provider within the corresponding email domain to complete authentication. For example, signing in to Figma with Google Workspace.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is the most common use case for SSO in CIAM. Let’s take a closer look.&lt;/p&gt;

&lt;p&gt;If we want to sign in to Figma using our @silverhand.io email, we can use either Social sign-in or SSO. The figures below illustrate the difference between the two:&lt;/p&gt;

&lt;center&gt;

![Image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k1iyu55jaxzp9a7ljsen.png)

&lt;/center&gt;

&lt;p&gt;In words:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;After social sign-in, users are free to set a password or change the email address in Figma&lt;/li&gt;
&lt;li&gt;After SSO, users cannot set password or change any personal info including email address, since their Identities are managed by Google Workspace&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In this case, Logto is both an Identity Provider and a Service Provider. It appears that SSO is more complex than a normal sign-in process. What are the benefits for the identity owner?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Centralized control:&lt;/strong&gt; Keep identity information and authentication processes in one place, and ensure user information is always up-to-date. There is no need to add and remove licenses across different applications for changes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Improved user experience:&lt;/strong&gt; Identity owners who require SSO are usually corporations. Their employees can use the same credentials and shared session for cross-company applications, such as Figma, Zoom, Slack, etc.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enhanced security:&lt;/strong&gt; You may have noticed that some corporations require specific sign-in methods, such as dynamic verification codes. Using SSO can ensure that every employee uses the same sign-in method combination for accessing all resources.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;🤔 Smart like you must have noticed that this is actually &lt;strong&gt;SSO Case 1&lt;/strong&gt; from the SaaS perspective.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It’s time to discuss the "X" in the SSO graph. This represents the process of Figma connecting the email domain to a specific Identity Provider. But, how does it work?&lt;/p&gt;

&lt;h2&gt;
  
  
  SSO mapping
&lt;/h2&gt;

&lt;p&gt;Since the request often comes from enterprise clients, we refer to the process of "SSO Case 3" from the previous section as "Enterprise SSO" for clarity.&lt;/p&gt;

&lt;p&gt;We can easily devise a naive solution: create a mapping between email domains and SSO methods, then manually update it.&lt;/p&gt;

&lt;p&gt;The action of process “X” is now clear:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;🔍 &lt;strong&gt;Find the mapped Enterprise SSO method of the given email domain&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Thus, if you configure &lt;code&gt;silverhand.io&lt;/code&gt; as a valid email domain that connects with a Google Workspace SSO URL, users who try to sign in with an &lt;code&gt;@silverhand.io&lt;/code&gt; email will be redirected to the corresponding Google Workspace sign-in page, instead of being processed in-place.&lt;/p&gt;

&lt;p&gt;When you only have a few dozen clients that need Enterprise SSO, manually managing the mapping is okay. However, there are more considerations to take into account:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;em&gt;What if there are hundreds or thousands Enterprise SSO clients?&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;What’s the relationship between “normal users” and “Enterprise SSO users”?&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Should data be isolated between different Enterprise SSO clients?&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Is there a need to provide a dashboard for the Enterprise SSO admins to view active users, audit logs, etc.?&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;How can accounts be automatically deactivated when a user is removed from the Enterprise SSO Identity Provider?&lt;/em&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;And a lot more. Since almost all Enterprise SSO are email-domain-based, we can quickly figure out a better solution:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If the user can prove ownership of that domain, they can set up the enterprise SSO of that domain in a self-serve manner.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This solution addresses the first two questions:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;1. What if there are hundreds or thousands Enterprise SSO clients?&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;They can configure Enterprise SSO in a self-serve way.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;2. What’s the relationship between “normal users” and “Enterprise SSO users”?&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;We open all possible sign-in methods to normal users except Enterprise SSO; While we limit the sign-in method to Enterprise SSO only to the users who are trying to sign in with the configured domains.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As for the third question:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;3. Should I isolate data between different Enterprise SSO clients?&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;Yes and no. It‘s time to introduce organization.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Organization
&lt;/h2&gt;

&lt;p&gt;We mentioned using email domains to recognize the specific Enterprise SSO method to use; in other words, applying a specific treatment for a specific batch of users.&lt;/p&gt;

&lt;p&gt;However, the client requirements are often more than just Enterprise SSO; for example, questions 4 and 5 in the previous section. Over the years, a mature model have been developed by outstanding SaaS companies to address these kinds of problems: Organizations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Organizations rules&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;An organization is a group of identities, typically smaller than a Tenant.&lt;/li&gt;
&lt;li&gt;All organizations are associated with a Tenant.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You may see other terms, such as "Workspace", “Team”, or even "Tenant" in the software. To identify if it is the concept we are discussing, just check if it represents “a group of Identities”.&lt;/p&gt;

&lt;p&gt;In this article, we will use the term "Organization" for consistency.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;🤹🏽‍♀️ In most cases, "a group of Identities" is equivalent to "a group of users". However, &lt;strong&gt;the same Identity can exist in multiple Organizations&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In Notion, you can create and join multiple workspaces (i.e. Organizations) with the same email address and switch between them easily.&lt;/p&gt;

&lt;p&gt;For Slack, it appears to be the same, but we suspect it uses different Identities behind the scenes since we need to create a new account for each workspace.&lt;/p&gt;

&lt;center&gt;

![Image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tl8dpac8pwnim6muwcor.png)

&lt;/center&gt;

&lt;p&gt;Notion has a “Personal Plan” available, which is normally an Organization under the hood, with the sole user (you) inside. We don't know the exact implementation of Notion, but this explanation is reasonable and archivable for our model.&lt;/p&gt;

&lt;p&gt;Each Organization also has an identifier, usually referred to as the “Organization domain”.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;ℹ️ An "Organization domain" is an internal identifier used to distinguish Organizations. It may differ from the "email domain", as the former is managed by the Service Provider, while the latter is usually provided by an external Identity Provider.&lt;/p&gt;

&lt;p&gt;For example, you can use &lt;code&gt;foo&lt;/code&gt; as the Organization domain in Slack, but use &lt;code&gt;@bar.io&lt;/code&gt; as the email domain for this Organization.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Quiz
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;❓ Can an app be associated with an Organization?&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Answer&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Yes yes. As we discussed in the beginning, an app can have an Identity. Can you elaborate a business scenario of this?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Questions remain
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;3. Should data be isolated between different Enterprise SSO clients?&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Yes:&lt;/strong&gt; Isolate business data, such as messages and documents, at the Organization level.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No:&lt;/strong&gt; Keep Identities independent, since they do not need to be associated with an Organization.&lt;/li&gt;
&lt;li&gt;Note there are three distinct entities involved here: Identities, Organizations, and Enterprise SSO configurations; which notably increased the complexity. The question itself is not specific enough.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;4. Is there a need to provide a dashboard for the Enterprise SSO admins to view active users, audit logs, etc.?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;5. How to automatically deactivate account when user is removed for the Enterprise SSO Identity Provider?&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;These demands are more business-oriented and can be implemented at Organization level. We'll leave them open here.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Closing notes
&lt;/h2&gt;

&lt;p&gt;We've introduced several concepts: Authentication (AuthN), Authorization (AuthZ), Identity, Tenant, Application, Identity Provider (IdP), Service Provider (SP), Single Sign-On (SSO), and Enterprise SSO (Organization). It may take some time to understand them all.&lt;/p&gt;

&lt;p&gt;As I wrote this article, I noticed that interestingly, the most expensive plans of online services often include exclusive features related to authorization, which is totally unmentioned in this article. You may already have some questions about authorization, such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How can we assign permissions to a user and verify them?&lt;/li&gt;
&lt;li&gt;What authorization model should I use?&lt;/li&gt;
&lt;li&gt;What is the best practice for applying an authorization model?&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;🔥 Take a break, and see you in CIAM 102!&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>webdev</category>
      <category>beginners</category>
      <category>programming</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Logto v1.0.0-rc.0: User auth with RBAC</title>
      <dc:creator>gao-sun</dc:creator>
      <pubDate>Fri, 03 Feb 2023 10:08:26 +0000</pubDate>
      <link>https://forem.com/logto/logto-v100-rc0-user-auth-with-rbac-4l2d</link>
      <guid>https://forem.com/logto/logto-v100-rc0-user-auth-with-rbac-4l2d</guid>
      <description>&lt;p&gt;&lt;a href="https://logto.io/" rel="noopener noreferrer"&gt;Logto&lt;/a&gt; is an open-source auth solution with comprehensive features and modern dev experience.&lt;/p&gt;




&lt;p&gt;Please welcome our first release candidate! Logto is just a few steps away from general availability.&lt;/p&gt;

&lt;h2&gt;
  
  
  🔒 Role-Based Access Control
&lt;/h2&gt;

&lt;p&gt;We are excited to introduce our latest addition to our product, Role-Based Access Control (RBAC). This powerful feature gives administrators the ability to assign specific roles and permissions to users, ensuring they only have access to the resources and functions they need to do their job.&lt;/p&gt;

&lt;p&gt;With RBAC, administrators can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Define permissions across APIs&lt;/li&gt;
&lt;li&gt;Create custom roles with specific permissions&lt;/li&gt;
&lt;li&gt;Assign roles to users and manage their roles&lt;/li&gt;
&lt;li&gt;Easily manage and update permissions&lt;/li&gt;
&lt;li&gt;Securely validate permissions to protect APIs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Logto takes a major step forward in security and control with easy access management and authorization of sensitive info, ensuring only authorized users have the right to access. This aligns with our vision to provide an open-source identity solution with features for authentication and authorization, and packed with all the features you need.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;&lt;br&gt;
If you are using Logto SDKs, please upgrade to the latest version to take advantage of RBAC.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Check out our &lt;a href="https://docs.logto.io/docs/recipes/rbac/" rel="noopener noreferrer"&gt;RBAC recipe&lt;/a&gt; for a step-by-step guide. Give it a try and let us know what you think!&lt;/p&gt;

&lt;h2&gt;
  
  
  🏄 Streamlined social sign-in flow
&lt;/h2&gt;

&lt;p&gt;💡 Logto now detects a trusted email (or phone number) from the social account during social sign-in.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If the email (or phone number) has been registered: Automatically connect the social identity to the existing user account with a single click.&lt;/li&gt;
&lt;li&gt;If the email (or phone number) is not registered: Automatically sync the user profile with the social-provided email (or phone number) if and only if it is marked as a required user profile.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🔢 Send and verify verification codes via Management API
&lt;/h2&gt;

&lt;p&gt;The new Management APIs allow you to reuse connectors to dynamically send and verify verification codes for various purposes, such as validating identity before a user updates their profile or performs a dangerous action.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Call &lt;code&gt;/api/verification-code&lt;/code&gt; to send verification code to a given email or phone&lt;/li&gt;
&lt;li&gt;Call &lt;code&gt;/api/verification-code/verify&lt;/code&gt; to verify the code against a given email or phone&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  ↩️ Rollback database alteration state
&lt;/h2&gt;

&lt;p&gt;In case of any issues with the database, you can now use the &lt;code&gt;logto db alteration rollback [target]&lt;/code&gt; command to roll back all database schemas to a previous version, for example &lt;code&gt;logto db alteration rollback v1.0.0-beta.19&lt;/code&gt;.&lt;/p&gt;

</description>
      <category>web3</category>
      <category>ethereum</category>
      <category>blockchain</category>
      <category>crypto</category>
    </item>
  </channel>
</rss>
