<?xml version="1.0" encoding="utf-8" standalone="yes"?><feed xmlns="http://www.w3.org/2005/Atom">
  <title></title>
  <subtitle></subtitle>
  <id>https://www.endpointdev.com/blog/tags/authentication/</id>
  <link href="https://www.endpointdev.com/blog/tags/authentication/"/>
  <link href="https://www.endpointdev.com/blog/tags/authentication/" rel="self"/>
  <updated>2023-04-13T00:00:00+00:00</updated>
  <author>
    <name>End Point Dev</name>
  </author>
  
    <entry>
      <title>SSH host key verification: a few useful tips</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2023/04/ssh-host-key/"/>
      <id>https://www.endpointdev.com/blog/2023/04/ssh-host-key/</id>
      <published>2023-04-13T00:00:00+00:00</published>
      <author>
        <name>Selvakumar Arumugam</name>
      </author>
      <content type="html">
        &lt;p&gt;&lt;img src=&#34;/blog/2023/04/ssh-host-key/key.webp&#34; alt=&#34;A close shot of a large golden key sitting on top of a wooden fence. There is green grass visible behind the fence, on the left and right upper sides of the image.&#34;&gt;&lt;/p&gt;
&lt;p&gt;The SSH connections between a client and a remote server begin with a host key verification as an initial handshake. If the default key algorithm is not supported between the client and server, the SSH connection attempt is closed with no matching host key type response.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ sftp username@domain
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Unable to negotiate with xx.xx.xx.xx port 22: no matching host key type found. Their offer: ssh-rsa
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Connection closed.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Connection closed&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this article, we will explore the host key verification process and discuss ways to handle the non-matching host key issue to establish the connection.&lt;/p&gt;
&lt;h3 id=&#34;host-keys&#34;&gt;Host keys&lt;/h3&gt;
&lt;p&gt;By default, OpenSSH automatically generates a public-private key pair on the server and stores it in &lt;code&gt;/etc/ssh&lt;/code&gt;. These keys, known as host keys, are created using several encryption algorithms including RSA, DSA, ECDSA, and ed25519.&lt;/p&gt;
&lt;p&gt;The pair of private and public keys is available on the host server at the path &lt;code&gt;/etc/ssh&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ ls /etc/ssh | grep key
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ssh_host_dsa_key
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ssh_host_dsa_key.pub
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ssh_host_ecdsa_key
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ssh_host_ecdsa_key.pub
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ssh_host_ed25519_key
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ssh_host_ed25519_key.pub
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ssh_host_rsa_key
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ssh_host_rsa_key.pub&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id=&#34;how-does-openssh-decide-which-host-key-to-use&#34;&gt;How does OpenSSH decide which host key to use?&lt;/h3&gt;
&lt;p&gt;During SSH connection establishment, the OpenSSH server presents a default host key signature algorithm to the SSH client. To check the list of key signature algorithms and their order, you can perform a query with &lt;code&gt;ssh -Q sig&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ ssh -Q sig
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ssh-ed25519
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sk-ssh-ed25519@openssh.com
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ssh-rsa
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;rsa-sha2-256
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;rsa-sha2-512
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ssh-dss
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ecdsa-sha2-nistp256
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ecdsa-sha2-nistp384
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ecdsa-sha2-nistp521
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sk-ecdsa-sha2-nistp256@openssh.com
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;webauthn-sk-ecdsa-sha2-nistp256@openssh.com&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id=&#34;hostkeyalgorithms&#34;&gt;HostKeyAlgorithms&lt;/h3&gt;
&lt;p&gt;You can also get a list of key types and signature algorithms with &lt;code&gt;ssh -Q HostKeyAlgorithms&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ ssh -Q HostKeyAlgorithms
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ssh-ed25519
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ssh-ed25519-cert-v01@openssh.com
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sk-ssh-ed25519@openssh.com
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sk-ssh-ed25519-cert-v01@openssh.com
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ssh-rsa
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;rsa-sha2-256
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;rsa-sha2-512
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ssh-dss
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ecdsa-sha2-nistp256
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ecdsa-sha2-nistp384
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ecdsa-sha2-nistp521
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sk-ecdsa-sha2-nistp256@openssh.com
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;webauthn-sk-ecdsa-sha2-nistp256@openssh.com
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ssh-rsa-cert-v01@openssh.com
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;rsa-sha2-256-cert-v01@openssh.com
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;rsa-sha2-512-cert-v01@openssh.com
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ssh-dss-cert-v01@openssh.com
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ecdsa-sha2-nistp256-cert-v01@openssh.com
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ecdsa-sha2-nistp384-cert-v01@openssh.com
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ecdsa-sha2-nistp521-cert-v01@openssh.com
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sk-ecdsa-sha2-nistp256-cert-v01@openssh.com&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The default list of host keys can be modified on the OpenSSH server by configuring the &lt;code&gt;/etc/ssh/sshd_config&lt;/code&gt; file, as described below.&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;Symbol&lt;/th&gt;
          &lt;th&gt;Description&lt;/th&gt;
          &lt;th&gt;Example&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;+&amp;lt;algorithm_name&amp;gt;&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;Algorithm will be appended to default set of list&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;+rsa-sha&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;-&amp;lt;algorithm_name&amp;gt;&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;Algorithm will be removed&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;-rsa-sha&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;^&amp;lt;algorithm_name&amp;gt;&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;Algorithm will be default value on top of list&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;^rsa-sha&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;blockquote&gt;
&lt;p&gt;You can see more in-depth info about SSH configuration with &lt;code&gt;man 5 ssh_config&lt;/code&gt;.&lt;/p&gt;&lt;/blockquote&gt;
&lt;h3 id=&#34;identify-host-key-type&#34;&gt;Identify host key type&lt;/h3&gt;
&lt;p&gt;SSH client and server logs provide valuable information about the host key algorithm types that are offered during SSH connections. In case of a mismatch between the client and server, the logs will record the offered key information from the other end. This information will be useful for troubleshooting and identifying the root cause of the issue.&lt;/p&gt;
&lt;p&gt;SSH client output:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ sftp -o HostKeyAlgorithms=ssh-rsa  username@domain
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Unable to negotiate with &amp;lt;server_id&amp;gt; port 22: no matching host key type found.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Their offer: rsa-sha2-512,rsa-sha2-256&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;SSH Server log (&lt;code&gt;/var/log/auth.log&lt;/code&gt;):&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;2022-06-28T22:26:46.692753-07:00 localhost sshd[445086]:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Unable to negotiate with &amp;lt;client_id&amp;gt; port 55872: no matching host key type found.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Their offer: ssh-rsa [preauth]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h4 id=&#34;third-party-application-logs&#34;&gt;Third-party application logs&lt;/h4&gt;
&lt;p&gt;Some third-party applications return the MD5 hash code in the event of a failed SSH connection attempt. This code can be useful in identifying the exact matching key algorithm that needs to be included in the server.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Limiting the SSH algorithms for the SFTP connection to
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;the following: none, zlib, zlib@openssh.com, aes256-chc, aes192-che,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;aes128-cbe, diffie-hellman-group14-sha256, ecdh-sha2-nistp256,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ecdh-sha2-nistp384, ecdh-sha2-nistp521, ssh-dss, ssh-rsa, hmac-sha2-
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;256, hmac-sha2-512, hmac-shal.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Configuring server validation for the SSH connection using
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;public keys: 3072: 8b 7e de 33 d8 f4 f5 82 d6 86 68 41 17 ba 72 4c.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The MD5 value of a key found in a third-party application log can be used to identify the matching key on the server with the help of the ssh-keygen utility.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ ssh-keygen -lf ssh_host_rsa_key.pub
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;3072 SHA256:kkcdlhNcj8DndHvyLBXGfhI/oZkrTRIAbwuqqd58uY0
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ ssh-keygen -E md5 -lf ssh_host_rsa_key.pub
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;3072 MD5:8b:7e:de:33:d8:f4:f5:82:d6:86:68:41:17:ba:72:4c root@ndpbh-test-epitrax-app01 (RSA)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id=&#34;ssh-rsa-disabled-by-default&#34;&gt;ssh-rsa disabled by default&lt;/h3&gt;
&lt;p&gt;Since the release of OpenSSH version 8.8, the ssh-rsa key algorithm has been disabled. As a result, accessing the latest version of the OpenSSH server from an older client version may lead to non-matching host key failures.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ ssh -V
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;OpenSSH_8.9p1 Ubuntu-3, OpenSSL 3.0.2 15 Mar 2022&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Notice: &lt;a href=&#34;http://www.openssh.com/txt/release-8.7&#34;&gt;http://www.openssh.com/txt/release-8.7&lt;/a&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Imminent deprecation notice
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;===========================
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;OpenSSH will disable the ssh-rsa signature scheme by default in the
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;next release.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Legacy Support: &lt;a href=&#34;https://www.openssh.com/txt/release-8.8&#34;&gt;https://www.openssh.com/txt/release-8.8&lt;/a&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Potentially-incompatible changes
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;================================
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;This release disables RSA signatures using the SHA-1 hash algorithm
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;by default. This change has been made as the SHA-1 hash algorithm is
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;cryptographically broken, and it is possible to create chosen-prefix
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;hash collisions for &amp;lt;USD$50K [1]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;For most users, this change should be invisible and there is
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;no need to replace ssh-rsa keys. OpenSSH has supported RFC8332
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;RSA/SHA-256/512 signatures since release 7.2 and existing ssh-rsa keys
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;will automatically use the stronger algorithm where possible.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Incompatibility is more likely when connecting to older SSH
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;implementations that have not been upgraded or have not closely tracked
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;improvements in the SSH protocol. For these cases, it may be necessary
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;to selectively re-enable RSA/SHA1 to allow connection and/or user
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;authentication via the HostkeyAlgorithms and PubkeyAcceptedAlgorithms
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;options. For example, the following stanza in ~/.ssh/config will enable
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;RSA/SHA1 for host and user authentication for a single destination host:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Host old-host
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        HostkeyAlgorithms +ssh-rsa
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	PubkeyAcceptedAlgorithms +ssh-rsa
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;We recommend enabling RSA/SHA1 only as a stopgap measure until legacy
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;implementations can be upgraded or reconfigured with another key type
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(such as ECDSA or Ed25519).
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;[1] &amp;#34;SHA-1 is a Shambles: First Chosen-Prefix Collision on SHA-1 and
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Application to the PGP Web of Trust&amp;#34; Leurent, G and Peyrin, T
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (2020) https://eprint.iacr.org/2020/014.pdf&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id=&#34;solution&#34;&gt;Solution&lt;/h3&gt;
&lt;p&gt;The SSH client and server offer options to specify the host key algorithm to use during SSH connections. Therefore, you can modify the client or server configuration to establish a connection based on the restrictions of one of the systems involved.&lt;/p&gt;
&lt;p&gt;Establishing an SSH connection using the most secure host key algorithm is highly recommended for optimal security. However, in situations where there are limitations on upgrading or changing the algorithm, users must make decisions based on the security policies of their application environment.&lt;/p&gt;
&lt;p&gt;In such cases, a suggested solution is to carefully evaluate the security requirements of the application environment and choose the host key algorithm that best aligns with those requirements. This may involve a trade-off between security and compatibility, so it is important to weigh the potential risks and benefits of each option.&lt;/p&gt;
&lt;h4 id=&#34;ssh-client&#34;&gt;SSH Client&lt;/h4&gt;
&lt;p&gt;When the privilege to configure the SSH server is restricted, the SSH client can be configured to use a specific algorithm. To do this, you can use the &lt;code&gt;-o HostKeyAlgorithms=&amp;lt;host_key&amp;gt;&lt;/code&gt; option with the SSH client to specify a particular host key algorithm type.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ sftp username@server
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Unable to negotiate with &amp;lt;server&amp;gt; port 22: no matching host key type found. Their offer: ssh-rsa
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Connection closed.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Connection closed&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In the above case, the SSH server uses ssh-rsa as the host key algorithm to establish connections. To use ssh-rsa as the key algorithm for the SSH client, you can configure it as follows.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ sftp -o HostKeyAlgorithms=ssh-rsa username@server
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;username@server~:$&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h4 id=&#34;ssh-server&#34;&gt;SSH Server&lt;/h4&gt;
&lt;p&gt;In some cases, it may not be possible to configure the SSH client to use a specific key when a third-party proprietary application is used to establish the connection. In such scenarios, the SSH server can be configured to include the required key.&lt;/p&gt;
&lt;p&gt;In our scenario, the third-party application expects the ssh-rsa key type, but the latest version of OpenSSH server does not provide ssh-rsa as it has been deprecated.&lt;/p&gt;
&lt;p&gt;To support old client attempts with ssh-rsa, the key should be added to the bottom of the list with a &amp;ldquo;+&amp;rdquo; symbol. This will allow the server to present the deprecated ssh-rsa key to old clients, while still offering more secure key algorithms to newer clients. The new lines in &lt;code&gt;/etc/ssh/sshd_config&lt;/code&gt; should look like the following:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;HostKeyAlgorithms +ssh-rsa
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;PubkeyAcceptedAlgorithms +ssh-rsa&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Before restarting the SSH service, it is advisable to test the configuration for syntax errors to prevent potential issues, like the following which occurs if you add an extra space to &lt;code&gt;Host KeyAlgorithms +ssh-rsa&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;# sshd -t
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;/etc/ssh/sshd_config: line 32: Bad configuration option: Host
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;/etc/ssh/sshd_config: terminating, 1 bad configuration options&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Once you&amp;rsquo;ve verified the configuration and &lt;code&gt;sshd -t&lt;/code&gt; gives no output, go ahead and restart the service to apply the changes.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;# sshd -t
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;# systemctl reload sshd.service&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;With this configuration, SSH clients can connect to the server using ssh-rsa. To verify the host key type used in an SSH connection, you can use the verbose (&lt;code&gt;-v&lt;/code&gt;) option with the &lt;code&gt;ssh&lt;/code&gt; command. This will display additional information about the SSH connection, including the host key algorithm being used. Here we increase the verbosity by adding the maximum of 3 &lt;code&gt;-v&lt;/code&gt; options.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ ssh -vvv -oHostKeyAlgorithms=ssh-rsa username@domain
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;…
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;debug2: host key algorithms: ssh-rsa
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;debug1: Will attempt key: .ssh/id_rsa RSA
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;SHA256:CmARXi+/8UwrvzwS7RkJNqD/rhroYTnfB285OnovVFs agent
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;…&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h4 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h4&gt;
&lt;p&gt;SSH is an incredible tool, but errors like the ones described here can make it a bit harder to work with if you&amp;rsquo;re not aware of what&amp;rsquo;s going on behind the scenes. Let us know in the comments if you&amp;rsquo;ve had any similar experiences!&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>Implementing Basic HTTP Authentication in Rails</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2023/01/implementing-basic-http-authentication-in-rails/"/>
      <id>https://www.endpointdev.com/blog/2023/01/implementing-basic-http-authentication-in-rails/</id>
      <published>2023-01-26T00:00:00+00:00</published>
      <author>
        <name>Kevin Campusano</name>
      </author>
      <content type="html">
        &lt;p&gt;&lt;img src=&#34;/blog/2023/01/implementing-basic-http-authentication-in-rails/deer-on-hill.webp&#34; alt=&#34;Two deer stand on a steep mountain slope. The mountain is reddened by the sunset, and cuts the image in half diagonally, with the other half being dominated by a pale blue sky. In the bottom, behind the front slope, lies a tall, snow-covered peak.&#34;&gt;&lt;/p&gt;
&lt;!-- Photo by Seth Jensen, 2022 --&gt;
&lt;p&gt;Nowadays it&amp;rsquo;s rather unusual to deploy &lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication&#34;&gt;HTTP Basic Authentication&lt;/a&gt; in a production web application. However, the need came up recently from a client. In a nutshell, due to integration requirements with a third party system, we had to provide a web app which expected credentials supplied via Basic HTTP Auth and validated against an external web service.&lt;/p&gt;
&lt;p&gt;Luckily for us, like a great many other things, this is very easy to implement with &lt;a href=&#34;https://rubyonrails.org/&#34;&gt;Ruby on Rails&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&#34;setting-up-a-new-rails-project&#34;&gt;Setting up a new Rails project&lt;/h3&gt;
&lt;p&gt;If you want to work along with me, and you like &lt;a href=&#34;https://www.docker.com/&#34;&gt;Docker&lt;/a&gt; and &lt;a href=&#34;https://code.visualstudio.com/&#34;&gt;VS Code&lt;/a&gt;, take a look at &lt;a href=&#34;/blog/2023/01/developing-rails-apps-in-a-dev-container-with-vs-code/&#34;&gt;this blog post&lt;/a&gt; to learn about the easiest way to set up an environment for development with Ruby on Rails in a container.&lt;/p&gt;
&lt;p&gt;If not, you can follow &lt;a href=&#34;https://www.ruby-lang.org/en/documentation/installation/&#34;&gt;the official docs&lt;/a&gt; for installing Ruby.&lt;/p&gt;
&lt;p&gt;Once you have your environment with Ruby ready, we can go ahead and create a new Rails project to demonstrate how to set up Basic HTTP Auth.&lt;/p&gt;
&lt;h4 id=&#34;creating-the-new-project&#34;&gt;Creating the new project&lt;/h4&gt;
&lt;p&gt;First, install the rails gem:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ gem install rails&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Then, make sure you are located in the directory where you want to create the new project and do:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ rails new . --minimal -O&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;--minimal&lt;/code&gt; is a new option to &lt;code&gt;rails new&lt;/code&gt; added in version 6.1 that disables a lot of default features and gems. You can learn more about it &lt;a href=&#34;https://github.com/rails/rails/pull/39282&#34;&gt;here&lt;/a&gt;. &lt;code&gt;-O&lt;/code&gt; excludes ActiveRecord from the project. We will not be using databases for this quick app so we don&amp;rsquo;t need it.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;And finally, run the app:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ bin/rails server&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Open a browser and navigate to &lt;a href=&#34;http://127.0.0.1:3000/&#34;&gt;http://127.0.0.1:3000/&lt;/a&gt; to see the classic Rails hello world screen:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2023/01/implementing-basic-http-authentication-in-rails/hello-rails.png&#34; alt=&#34;Hello Rails. A browser navigated to http://127.0.0.1:3000/, with the webpage displaying the Rails logo, and underneath reading &amp;ldquo;Rails version: 7.0.4&amp;rdquo;; &amp;ldquo;Ruby version: ruby 3.1.3p185 (2022-11-24 revision 1a6b16756e)[x86_64-linux]&#34;&gt;&lt;/p&gt;
&lt;h3 id=&#34;implementing-basic-http-auth&#34;&gt;Implementing Basic HTTP Auth&lt;/h3&gt;
&lt;p&gt;Now that we have a Rails app up and running, let&amp;rsquo;s actually add Basic HTTP auth to it.&lt;/p&gt;
&lt;p&gt;First of all we need a page that we will secure:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ bin/rails generate controller Pages home --no-helper&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;That&amp;rsquo;ll give us a &amp;ldquo;Pages&amp;rdquo; controller with a &amp;ldquo;home&amp;rdquo; action and its corresponding view.&lt;/p&gt;
&lt;p&gt;Next, we replace the &lt;code&gt;get &#39;pages/home&#39;&lt;/code&gt; line in &lt;code&gt;routes.rb&lt;/code&gt; with &lt;code&gt;root &#39;pages#home&#39;&lt;/code&gt;. That will make it so the root URL of our app points to the action created in the previous step.&lt;/p&gt;
&lt;p&gt;Going back to the browser at &lt;a href=&#34;http://127.0.0.1:3000/&#34;&gt;http://127.0.0.1:3000/&lt;/a&gt; you should see this now:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2023/01/implementing-basic-http-authentication-in-rails/homepage.png&#34; alt=&#34;A browser navigated to http://127.0.0.1:3000/. On the page, a header reads &amp;ldquo;Pages#home&amp;rdquo;, with a sentence below reading &amp;ldquo;Find me in app/views/pages/home.html.erb&amp;rdquo;.&#34;&gt;&lt;/p&gt;
&lt;p&gt;Now we can restrict access to this page with Basic HTTP Auth by adding this code to the &amp;ldquo;PagesController&amp;rdquo;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-diff&#34; data-lang=&#34;diff&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; class PagesController &amp;lt; ApplicationController
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;background-color:#dfd&#34;&gt;+  before_action :authenticate_http_basic
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;background-color:#dfd&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   def home
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   end
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;background-color:#dfd&#34;&gt;+  def authenticate_http_basic
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;background-color:#dfd&#34;&gt;+    return if authenticate_with_http_basic { |un, pw| do_authentication(un, pw) }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;background-color:#dfd&#34;&gt;+
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;background-color:#dfd&#34;&gt;+    request_http_basic_authentication
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;background-color:#dfd&#34;&gt;+  end
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;background-color:#dfd&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;background-color:#dfd&#34;&gt;+  def do_authentication(username, password)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;background-color:#dfd&#34;&gt;+    username == &amp;#34;username&amp;#34; &amp;amp;&amp;amp; password == &amp;#34;password&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;background-color:#dfd&#34;&gt;+  end
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;background-color:#dfd&#34;&gt;&lt;/span&gt; end
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And that&amp;rsquo;s really all it takes. Try to navigate to &lt;a href=&#34;http://127.0.0.1:3000/&#34;&gt;http://127.0.0.1:3000/&lt;/a&gt; in the browser and you&amp;rsquo;ll now encounter this:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2023/01/implementing-basic-http-authentication-in-rails/basic-http-auth-popup.png&#34; alt=&#34;A popup is shown above the home page, showing the site which created it (http://127.0.0.1:3000), and reading &amp;ldquo;This site is asking you to sign in&amp;rdquo;, followed by text inputs for Username and Password. At the bottom of the popup are buttons for Cancel and Sign in.&#34;&gt;&lt;/p&gt;
&lt;p&gt;Basic HTTP Auth in action! Hit cancel or input the wrong credentials and a &amp;ldquo;HTTP Basic: Access denied.&amp;rdquo; message will be shown; type in &amp;ldquo;username&amp;rdquo; and &amp;ldquo;password&amp;rdquo; and our beautiful homepage shows up.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s now discuss the few lines of code that we added to the controller.&lt;/p&gt;
&lt;p&gt;First is the &lt;code&gt;authenticate_http_basic&lt;/code&gt; method which we&amp;rsquo;ve registered to the controller&amp;rsquo;s &lt;code&gt;before_action&lt;/code&gt; callback. That means that before processing any of the controller&amp;rsquo;s actions (&lt;code&gt;home&lt;/code&gt; being the only one), the method will be invoked and serve as a precondition for its execution.&lt;/p&gt;
&lt;p&gt;In the method, the first thing we do is call &lt;code&gt;authenticate_with_http_basic&lt;/code&gt;, which is how we tell Rails to authenticate the current request using Basic HTTP Auth. The block that we pass to the method is provided the username and password that the user typed in and is where we put any custom logic that we may have for validating the credentials.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;authenticate_with_http_basic&lt;/code&gt; returns whatever the block returns. That&amp;rsquo;s why we have that &lt;code&gt;return if ...&lt;/code&gt; guard clause as the first line of our &lt;code&gt;authenticate_http_basic&lt;/code&gt; method. If the block returns truthy, the auth is deemed successful and the user is allowed in the page; if it returns falsy, execution continues and reaches the &lt;code&gt;request_http_basic_authentication&lt;/code&gt; line; which prompts the authentication popup form that we saw earlier.&lt;/p&gt;
&lt;p&gt;In our case, the custom logic that validates the credentials is very simple. It just calls a &lt;code&gt;do_authentication&lt;/code&gt; method that checks the inputs against hardcoded values. But in the real world, this can be anything. For the client that I discussed at the beginning to this article, the requirement was to invoke an external web service to validate the provided credentials. You could also check the credentials against some database or file, etc.&lt;/p&gt;
&lt;h4 id=&#34;encapsulating-the-basic-http-auth-logic-in-a-module&#34;&gt;Encapsulating the Basic HTTP Auth logic in a module&lt;/h4&gt;
&lt;p&gt;I also thought it&amp;rsquo;d be nice to encapsulate this in a module for easier reuse. That&amp;rsquo;s something that&amp;rsquo;s easy to accomplish thanks to &lt;a href=&#34;https://api.rubyonrails.org/v7.0.4/classes/ActiveSupport/Concern.html&#34;&gt;Rails&amp;rsquo; Concerns&lt;/a&gt;. For our little demo app, it&amp;rsquo;d look something like this:&lt;/p&gt;
&lt;p&gt;Create a new &lt;code&gt;app/controllers/concerns/http_basic_auth.rb&lt;/code&gt; file and add the following code:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ruby&#34; data-lang=&#34;ruby&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;# Provides the `authenticate_http_basic` method which can be used to&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;# authenticate requests using credentials provided via Basic HTTP Auth.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;module&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;HttpBasicAuth&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080&#34;&gt;extend&lt;/span&gt; &lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;ActiveSupport&lt;/span&gt;::&lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;Concern&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  included &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#06b;font-weight:bold&#34;&gt;authenticate_http_basic&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;if&lt;/span&gt; authenticate_with_http_basic { |un, pw| do_authentication(un, pw) }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      request_http_basic_authentication
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080&#34;&gt;private&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#06b;font-weight:bold&#34;&gt;do_authentication&lt;/span&gt;(username, password)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#888&#34;&gt;# TODO: Implement custom credentials validation logic.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      username == &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;username&amp;#34;&lt;/span&gt; &amp;amp;&amp;amp; password == &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;password&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;end&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And in the controller that we want to restrict access to, all we need is this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ruby&#34; data-lang=&#34;ruby&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;PagesController&lt;/span&gt; &amp;lt; &lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;ApplicationController&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080&#34;&gt;include&lt;/span&gt; &lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;HttpBasicAuth&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  before_action &lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;:authenticate_http_basic&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#06b;font-weight:bold&#34;&gt;home&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;end&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If the entire app needs Basic HTTP Auth then adding this to the base &lt;code&gt;ApplicationController&lt;/code&gt; might make more sense. If only some actions need to be behind the authentication, then the &lt;a href=&#34;https://guides.rubyonrails.org/action_controller_overview.html#filters&#34;&gt;&lt;code&gt;:only&lt;/code&gt; and &lt;code&gt;:except&lt;/code&gt; modifiers&lt;/a&gt; can be used for finer grained control.&lt;/p&gt;
&lt;p&gt;And that&amp;rsquo;s all for now! It may be surprising to some but sometimes even Basic HTTP Auth is necessary. For those cases, Rails has our backs.&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>Using Devise for Authentication in Rails Without Database Stored Accounts</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2023/01/using-devise-for-authentication-without-database-stored-accounts/"/>
      <id>https://www.endpointdev.com/blog/2023/01/using-devise-for-authentication-without-database-stored-accounts/</id>
      <published>2023-01-19T00:00:00+00:00</published>
      <author>
        <name>Kevin Campusano</name>
      </author>
      <content type="html">
        &lt;p&gt;&lt;img src=&#34;/blog/2023/01/using-devise-for-authentication-without-database-stored-accounts/sunset-plane.webp&#34; alt=&#34;A plane flies low over a lake, which reflecs the orange sky of a sunset. The lake is backed by tall mountains which are given depth by the end of the day&amp;rsquo;s haze.&#34;&gt;&lt;/p&gt;
&lt;!-- Photo by Seth Jensen, 2021 --&gt;
&lt;p&gt;We can pretty much say that thanks to the venerable &lt;a href=&#34;https://github.com/heartcombo/devise&#34;&gt;Devise&lt;/a&gt; &lt;a href=&#34;https://rubygems.org/&#34;&gt;gem&lt;/a&gt;, the authentication problem has been solved in &lt;a href=&#34;https://rubyonrails.org/&#34;&gt;Ruby on Rails&lt;/a&gt;. There are some instances however, when the requirements veer a little further away from convention and some customization needs to happen.&lt;/p&gt;
&lt;p&gt;Such was the case of a recent project where we had to implement authentication and session management on a small web application that would serve as an &lt;a href=&#34;https://microservices.io/patterns/apigateway.html&#34;&gt;API gateway&lt;/a&gt; into other system components. The interesting part was that there was no database to store accounts, and credentials would have to be validated against an external web service.&lt;/p&gt;
&lt;p&gt;Luckily for us, the Devise gem is customizable enough to be able to fulfill this requirement via custom authentication strategies. With custom authentication strategies, one can implement completely bespoke authentication logic while still enjoying a lot of the features that Devise offers out of the box.&lt;/p&gt;
&lt;p&gt;In this article, we&amp;rsquo;re going to walk through doing just that. Let&amp;rsquo;s get started.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;To learn more about this capability of Devise, and how it relates to the underlying &lt;a href=&#34;https://github.com/wardencommunity/warden&#34;&gt;Warden&lt;/a&gt; concepts, here are some interesting sources:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://4trabes.com/2012/10/31/remote-authentication-with-devise/&#34;&gt;Remote authentication with devise&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://insights.kyan.com/devise-authentication-strategies-a1a6b4e2b891&#34;&gt;Devise authentication strategies&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://blog.plataformatec.com.br/2019/01/custom-authentication-methods-with-devise/&#34;&gt;Custom authentication methods with Devise&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/wardencommunity/warden/wiki/Strategies&#34;&gt;Warden strategies&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/blockquote&gt;
&lt;h3 id=&#34;setting-up-a-new-rails-project&#34;&gt;Setting up a new Rails project&lt;/h3&gt;
&lt;p&gt;If you want to work along with me, and you like &lt;a href=&#34;https://www.docker.com/&#34;&gt;Docker&lt;/a&gt; and &lt;a href=&#34;https://code.visualstudio.com/&#34;&gt;VS Code&lt;/a&gt;, take a look at &lt;a href=&#34;/blog/2023/01/developing-rails-apps-in-a-dev-container-with-vs-code/&#34;&gt;this blog post&lt;/a&gt; to learn how to set up a containerized development environment for Ruby on Rails with minimal effort.&lt;/p&gt;
&lt;p&gt;If not, you can follow &lt;a href=&#34;https://www.ruby-lang.org/en/documentation/installation/&#34;&gt;the official docs&lt;/a&gt; for installing Ruby.&lt;/p&gt;
&lt;p&gt;Either way, once you have your environment ready, we can go ahead and start setting up our new Rails project.&lt;/p&gt;
&lt;p&gt;First, install the rails gem:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ gem install rails&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Then, make sure you are located in the directory where you want to create the new project and do:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ rails new . --minimal&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;--minimal&lt;/code&gt; is an option to &lt;code&gt;rails new&lt;/code&gt; added in version 6.1 that disables a lot of default features and gems. You can learn more about it &lt;a href=&#34;https://github.com/rails/rails/pull/39282&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;&lt;/blockquote&gt;
&lt;h3 id=&#34;installing-devise&#34;&gt;Installing Devise&lt;/h3&gt;
&lt;p&gt;Now, we need to add the Devise gem by adding this to your &lt;code&gt;Gemfile&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rb&#34; data-lang=&#34;rb&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;gem &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;devise&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And then running the following to install it in the project:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ bin/rails generate devise:install&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Let&amp;rsquo;s also create a &amp;ldquo;home&amp;rdquo; page which we will point the app root route to. Run:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ bin/rails generate controller Pages home --no-helper&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;That will create a new &lt;code&gt;PagesController&lt;/code&gt; with a &lt;code&gt;home&lt;/code&gt; action and its corresponding view.&lt;/p&gt;
&lt;p&gt;Next, in the &lt;code&gt;config/routes.rb&lt;/code&gt; file, replace the &lt;code&gt;get &#39;pages/home&#39;&lt;/code&gt; line created by the previous command with &lt;code&gt;root &amp;quot;pages#home&amp;quot;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Also, like I said at the beginning, we won&amp;rsquo;t use a database for storing accounts or validating credentials. So, we can comment out this line on the Devise initializer at &lt;code&gt;config/initializers/devise.rb&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ruby&#34; data-lang=&#34;ruby&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;Devise&lt;/span&gt;.setup &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;do&lt;/span&gt; |config|
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#888&#34;&gt;# ...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#888&#34;&gt;# ==&amp;gt; ORM configuration&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#888&#34;&gt;## require &amp;#39;devise/orm/active_record&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#888&#34;&gt;# ...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;end&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now we have a strong enough foundation to get started. Run &lt;code&gt;bin/rails server&lt;/code&gt; and navigate to the URL that the Puma development server produced and you should see this:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2023/01/using-devise-for-authentication-without-database-stored-accounts/homepage.png&#34; alt=&#34;A browser viewing localhost:3001. On the page, a header reads &amp;ldquo;Pages#home&amp;rdquo;, with a sentence below reading &amp;ldquo;Find me in app/views/pages/home.html.erb&amp;rdquo;.&#34;&gt;&lt;/p&gt;
&lt;h3 id=&#34;defining-the-user-model&#34;&gt;Defining the User model&lt;/h3&gt;
&lt;p&gt;For Devise to work, it needs to be associated with a model class from our app that represents user accounts. Normally, this would be some &lt;code&gt;ActiveRecord::Base&lt;/code&gt; derived class, like most conventional implementations. For us, though, this will not work because, like I said at the beginning, we don&amp;rsquo;t have a database. Neither accounts nor credentials will be stored locally, but rather in an external web service.&lt;/p&gt;
&lt;p&gt;So what we do instead is define a class that looks &lt;em&gt;enough&lt;/em&gt; like an ActiveRercord such that Devise can work with it. Thanks to Rails&amp;rsquo; modularity, this is easy, as we only need to include a few modules into said class. Here&amp;rsquo;s what our &lt;code&gt;User&lt;/code&gt; model class ends up looking like:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ruby&#34; data-lang=&#34;ruby&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;# app/models/user.rb&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;User&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080&#34;&gt;include&lt;/span&gt; &lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;ActiveModel&lt;/span&gt;::&lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;API&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080&#34;&gt;include&lt;/span&gt; &lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;ActiveModel&lt;/span&gt;::&lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;Validations&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080&#34;&gt;extend&lt;/span&gt; &lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;ActiveModel&lt;/span&gt;::&lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;Callbacks&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080&#34;&gt;extend&lt;/span&gt; &lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;Devise&lt;/span&gt;::&lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;Models&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  define_model_callbacks &lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;:validation&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080&#34;&gt;attr_accessor&lt;/span&gt; &lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;:email&lt;/span&gt;, &lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;:password&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;end&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;As you can see, all we have done is &lt;code&gt;include&lt;/code&gt; and &lt;code&gt;extend&lt;/code&gt; various modules as well as define the validation callbacks. This will augment the class with the APIs necessary for Devise to be able to interact with it properly. We also define email and password fields which will be our credentials.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;You can read more about &lt;code&gt;ActiveModel::Callbacks&lt;/code&gt; and &lt;code&gt;define_model_callbacks&lt;/code&gt; &lt;a href=&#34;https://api.rubyonrails.org/classes/ActiveModel/Callbacks.html&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;Now that this class is available, in order to tell Devise that it needs to work with it, we add the following line to the &lt;code&gt;config/routes.rb&lt;/code&gt; file:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-diff&#34; data-lang=&#34;diff&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; Rails.application.routes.draw do
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   # ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;background-color:#dfd&#34;&gt;+  devise_for :users
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;background-color:#dfd&#34;&gt;&lt;/span&gt; end
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id=&#34;implementing-the-custom-authentication-strategy&#34;&gt;Implementing the custom authentication strategy&lt;/h3&gt;
&lt;p&gt;Now that Devise is hooked up, let&amp;rsquo;s finally implement the custom authentication strategy. For this we will take three steps:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Write a component that implements the authentication logic.&lt;/li&gt;
&lt;li&gt;Write a component that implements the serialization logic.&lt;/li&gt;
&lt;li&gt;Register the new strategy in the initializer and model class.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Let&amp;rsquo;s get started with step 1. Here&amp;rsquo;s what the class looks like:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ruby&#34; data-lang=&#34;ruby&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;# app/custom_auth/devise/strategies/custom_authenticatable.rb&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;# Based on https://gist.github.com/madtrick/3917079&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;module&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;Devise&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;module&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;Strategies&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888&#34;&gt;# The class needs to inherit from Devise::Strategies::Authenticatable which&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888&#34;&gt;# implements most of the underlying logic for auth strategies in Devise.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888&#34;&gt;# You can read the code here:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888&#34;&gt;# https://github.com/heartcombo/devise/blob/main/lib/devise/strategies/authenticatable.rb&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;CustomAuthenticatable&lt;/span&gt; &amp;lt; &lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;Authenticatable&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#888&#34;&gt;# This is the method called by Warden to authenticate a user.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#888&#34;&gt;# More info in https://github.com/wardencommunity/warden/wiki/Strategies#authenticate&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#06b;font-weight:bold&#34;&gt;authenticate!&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;if&lt;/span&gt; credentials_valid?
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#888&#34;&gt;# Signals Warden that the authentication was successful.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#888&#34;&gt;# Expects an instance of the model class that Devise is configured to work with.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#888&#34;&gt;# This should be the user account that matches the provided credentials.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          success!(validated_user)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#888&#34;&gt;# Signals Warden that the authentication failed.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#038&#34;&gt;fail&lt;/span&gt;!
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#080&#34;&gt;private&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#888&#34;&gt;# Returns a boolean indicating whether the provided credentials are valid.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#888&#34;&gt;# This is where you can implement any bespoke logic to do so: Read a file,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#888&#34;&gt;# call a service, validate a one-time-use token, etc.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#888&#34;&gt;#&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#888&#34;&gt;# authentication_hash is provided by the base class and includes all the&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#888&#34;&gt;# fields included in the login form.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#06b;font-weight:bold&#34;&gt;credentials_valid?&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        authentication_hash[&lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;:email&lt;/span&gt;] == &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;test@email.com&amp;#34;&lt;/span&gt; &amp;amp;&amp;amp; authentication_hash[&lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;:password&lt;/span&gt;] == &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;password&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#06b;font-weight:bold&#34;&gt;validated_user&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#888&#34;&gt;# mapping.to is a reference to the model class that Devise is configured&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#888&#34;&gt;# to use that represents user accounts. In this case, it&amp;#39;s the User class.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        mapping.to.new(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;email&lt;/span&gt;: authentication_hash[&lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;:email&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;password&lt;/span&gt;: authentication_hash[&lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;:password&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        )
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;end&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Feel free to read through that code and the comments for some explanations on what each piece does. There are a few key points to go over.&lt;/p&gt;
&lt;p&gt;First of all, the class needs to inherit from &lt;code&gt;Devise::Strategies::Authenticatable&lt;/code&gt;. This is the base class that Devise provides for us to create custom authentication strategies. The most important method that we need to define is &lt;code&gt;authenticate!&lt;/code&gt;. This method is invoked by the powers that be (i.e. Warden) to run the actual authentication logic. After calling it, Warden expects it to invoke either &lt;code&gt;success!&lt;/code&gt; or &lt;code&gt;fail!&lt;/code&gt;, depending on the authentication results, and the rest of the system will act accordingly. &lt;code&gt;success!&lt;/code&gt; expects an instance of User being passed as an argument. This User instance represents the account that matches the given credentials.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;authenticate!&lt;/code&gt; method is where Devise and Warden give you the ability to fully customize how to authenticate the given credentials. I&amp;rsquo;ve chosen to implement a simple check against hardcoded values for our example here, but this can be anything. In my real world use case, I had to make a call to an external web service, but you could also check a file, validate a token with some algorithm, anything that&amp;rsquo;s possible with Ruby and Rails really.&lt;/p&gt;
&lt;p&gt;The next step is to implement the logic to serialize and deserialize the instance of User that represents the logged-in account to and from the Rails session store. This is encapsulated in a very simple module that looks like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ruby&#34; data-lang=&#34;ruby&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;# app/custom_auth/devise/models/custom_authenticatable.rb&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;# Based on https://gist.github.com/madtrick/3916999&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;module&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;Devise&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;module&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;Models&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;module&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;CustomAuthenticatable&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#080&#34;&gt;extend&lt;/span&gt; &lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;ActiveSupport&lt;/span&gt;::&lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;Concern&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;module&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;ClassMethods&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#888&#34;&gt;# Recreates a resource from session data.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#888&#34;&gt;#&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#888&#34;&gt;# It takes as many params as elements in the array returned in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#888&#34;&gt;# serialize_into_session.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#06b;font-weight:bold&#34;&gt;serialize_from_session&lt;/span&gt;(email)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#080&#34;&gt;new&lt;/span&gt;(&lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;email&lt;/span&gt;:)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#888&#34;&gt;# Returns an array with the data from the user that needs to be&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#888&#34;&gt;# serialized into the session.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#06b;font-weight:bold&#34;&gt;serialize_into_session&lt;/span&gt;(user)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          [user.email]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;end&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And this one is very self-explanatory. There&amp;rsquo;s a &lt;code&gt;serialize_into_session&lt;/code&gt; method that receives the User instance for the logged-in account and returns an array of the individual fields of it that we want Devise to include in the session data that persists across requests. And there&amp;rsquo;s also a &lt;code&gt;serialize_from_session&lt;/code&gt; method that receives the fields from the serialized array as individual parameters and has to return a new User instance.&lt;/p&gt;
&lt;p&gt;And finally, we need to register the new strategy and put it to work. We do that by adding these lines in the Devise initializer at &lt;code&gt;config/initializers/devise.rb&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ruby&#34; data-lang=&#34;ruby&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;Devise&lt;/span&gt;.setup &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;do&lt;/span&gt; |config|
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#888&#34;&gt;# ...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  config.warden &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;do&lt;/span&gt; |manager|
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    manager.strategies.add(&lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;:custom&lt;/span&gt;, &lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;Devise&lt;/span&gt;::&lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;Strategies&lt;/span&gt;::&lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;CustomAuthenticatable&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    manager.default_strategies(&lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;scope&lt;/span&gt;: &lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;:user&lt;/span&gt;).unshift(&lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;:custom&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;Devise&lt;/span&gt;.add_module &lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;:custom_authenticatable&lt;/span&gt;, &lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;controller&lt;/span&gt;: &lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;:sessions&lt;/span&gt;, &lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;route&lt;/span&gt;: &lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;:session&lt;/span&gt;, &lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;strategy&lt;/span&gt;: &lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;:custom&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#888&#34;&gt;# ...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;end&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Here, we&amp;rsquo;ve registered our new custom authentication strategy with Warden and added it as a default. We&amp;rsquo;ve also declared a new Devise &amp;ldquo;module&amp;rdquo; (via the &lt;a href=&#34;https://www.rubydoc.info/github/plataformatec/devise/Devise.add_module&#34;&gt;&lt;code&gt;Devise.add_module&lt;/code&gt;&lt;/a&gt; method) that will use that strategy (as given by the &lt;code&gt;strategy:&lt;/code&gt; parameter) and act as part of the sessions-related functionality (as given by the &lt;code&gt;controller:&lt;/code&gt; and &lt;code&gt;route:&lt;/code&gt; parameters). This means that, by adding this module to our User model class, Devise will render the routes necessary for session handling. Namely, &lt;code&gt;sign_in&lt;/code&gt; and &lt;code&gt;sign_out&lt;/code&gt;. Like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; $ bin/rails routes
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              Prefix Verb   URI Pattern               Controller#Action
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    new_user_session GET    /users/sign_in(.:format)  devise/sessions#new
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        user_session POST   /users/sign_in(.:format)  devise/sessions#create
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;destroy_user_session DELETE /users/sign_out(.:format) devise/sessions#destroy&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now, all that&amp;rsquo;s left is adding the module to the &lt;code&gt;User&lt;/code&gt; class at &lt;code&gt;app/models/user.rb&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ruby&#34; data-lang=&#34;ruby&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;User&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#888&#34;&gt;# ...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  devise &lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;:custom_authenticatable&lt;/span&gt;, &lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;authentication_keys&lt;/span&gt;: [&lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;:email&lt;/span&gt;, &lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;:password&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;end&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Note how we specify the &lt;code&gt;authentication_keys&lt;/code&gt; to be &lt;code&gt;email&lt;/code&gt; and &lt;code&gt;password&lt;/code&gt;, the same fields that &lt;code&gt;Devise::Strategies::CustomAuthenticatable&lt;/code&gt; uses to run the validation logic, and are defined as attributes in &lt;code&gt;User&lt;/code&gt;. These can be anything really. The nice thing about using &lt;code&gt;email&lt;/code&gt; and &lt;code&gt;password&lt;/code&gt; in particular is that Devise&amp;rsquo;s default views and controllers already work with these fields, so no additional changes and configurations need to be done if we follow that convention.&lt;/p&gt;
&lt;p&gt;With all this, we&amp;rsquo;re basically plugging some of our code right into the middle of Devise&amp;rsquo;s logic for authentication and leveraging the rest of the functionality provided by it, like automatic views and controllers and such. As we&amp;rsquo;ll see next.&lt;/p&gt;
&lt;h3 id=&#34;implementing-session-management&#34;&gt;Implementing session management&lt;/h3&gt;
&lt;p&gt;Now that we&amp;rsquo;ve laid out all the piping that we need, the rest of the work to add support for sessions to our little test app is actually just business as usual with Devise.&lt;/p&gt;
&lt;p&gt;By adding the &lt;code&gt;custom_authenticatable&lt;/code&gt; Devise module to the User class, and the &lt;code&gt;devise_for :users&lt;/code&gt; line on the &lt;code&gt;config/routes.rb&lt;/code&gt; file, the session management actions are already in. So all we have to do is add a few links to actually use them. Adding the following snippet on &lt;code&gt;app/views/layouts/application.html.erb&lt;/code&gt; inside the &lt;code&gt;&amp;lt;body&amp;gt;&lt;/code&gt; element will suffice:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;&amp;lt;&lt;/span&gt;% if user_signed_in? %&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt;&amp;gt;Hello &lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;&amp;lt;&lt;/span&gt;%= current_user.email %&amp;gt;&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;span&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;&amp;lt;&lt;/span&gt;%= button_to &amp;#34;Log out&amp;#34;, destroy_user_session_path, method: :delete %&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;&amp;lt;&lt;/span&gt;% else %&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;&amp;lt;&lt;/span&gt;%= link_to &amp;#34;Log in&amp;#34;, new_user_session_path %&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;&amp;lt;&lt;/span&gt;% end %&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;p&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;class&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;notice&amp;#34;&lt;/span&gt;&amp;gt;&lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;&amp;lt;&lt;/span&gt;%= notice %&amp;gt;&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;p&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;p&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;class&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;alert&amp;#34;&lt;/span&gt;&amp;gt;&lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;&amp;lt;&lt;/span&gt;%= alert %&amp;gt;&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;p&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This should be very familiar if you&amp;rsquo;ve worked with Devise before. If not, there are more details &lt;a href=&#34;https://github.com/heartcombo/devise/wiki/How-To:-Add-sign_in,-sign_out,-and-sign_up-links-to-your-layout-template&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;All this does is show a link to the log in page when there&amp;rsquo;s no user logged in; and a hello message along with a log out button when there is.&lt;/p&gt;
&lt;p&gt;Run the app with &lt;code&gt;bin/rails server&lt;/code&gt;, click the &amp;ldquo;Log in&amp;rdquo; link, and you&amp;rsquo;ll see Devise&amp;rsquo;s default log in page. Type in the hardcoded credentials from &lt;code&gt;Devise::Strategies::CustomAuthenticatable&lt;/code&gt; and submit the form to see something like this:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2023/01/using-devise-for-authentication-without-database-stored-accounts/logged-in.png&#34; alt=&#34;Alt text&#34;&gt;&lt;/p&gt;
&lt;p&gt;We&amp;rsquo;ve just been redirected back to the root and are greeted and shown a result message courtesy of Devise.&lt;/p&gt;
&lt;p&gt;And that&amp;rsquo;s it! We&amp;rsquo;ve developed a pretty simple custom authentication strategy for Devise that&amp;rsquo;s very straightforward. It does not use a database at all!&lt;/p&gt;
&lt;p&gt;The important thing though, is that we can use this pattern to implement any number of more complex procedures. And we&amp;rsquo;ve done so in a way that does not lock us out of leveraging the rest of Devise&amp;rsquo;s out-of-the-box capabilities like automatic controllers and views.&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>Implementing Authentication in ASP.NET Core Web APIs</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2022/06/implementing-authentication-in-asp.net-core-web-apis/"/>
      <id>https://www.endpointdev.com/blog/2022/06/implementing-authentication-in-asp.net-core-web-apis/</id>
      <published>2022-06-17T00:00:00+00:00</published>
      <author>
        <name>Kevin Campusano</name>
      </author>
      <content type="html">
        &lt;p&gt;&lt;img src=&#34;/blog/2022/06/implementing-authentication-in-asp.net-core-web-apis/stockholm-buildings.webp&#34; alt=&#34;Several buildings with a lightly cloudy blue sky&#34;&gt;&lt;/p&gt;
&lt;!-- Photo by Seth Jensen --&gt;
&lt;p&gt;Authentication is a complex space. There are many problem scenarios and many more solutions. When it comes to &lt;a href=&#34;https://docs.microsoft.com/en-us/aspnet/core/tutorials/first-web-api?view=aspnetcore-6.0&amp;amp;tabs=visual-studio-code&#34;&gt;Web APIs&lt;/a&gt; written with &lt;a href=&#34;https://github.com/dotnet/aspnetcore&#34;&gt;ASP.NET Core&lt;/a&gt;, there are various fully featured options like &lt;a href=&#34;https://duendesoftware.com/&#34;&gt;Duende IdentityServer&lt;/a&gt; or &lt;a href=&#34;https://docs.microsoft.com/en-us/azure/api-management/api-management-howto-protect-backend-with-aad&#34;&gt;Azure Active Directory&lt;/a&gt;. These promise to be &amp;ldquo;everything but the kitchen sink&amp;rdquo; solutions which are robust and allow you to deal with many complex requirements.&lt;/p&gt;
&lt;p&gt;But what if our requirements dictate that we need something simpler? Do we have to roll out our own from scratch? Or does ASP.NET Core offer smaller, customizable, somewhat independent puzzle pieces that we can put together without having to write all the code ourselves and still have a good amount of control?&lt;/p&gt;
&lt;p&gt;Spoiler alert: The answer to that last question is yes. And we&amp;rsquo;re going to talk about it in this very article.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;There is a &lt;a href=&#34;#table-of-contents&#34;&gt;Table of contents&lt;/a&gt; at the end of this post.&lt;/p&gt;&lt;/blockquote&gt;
&lt;h3 id=&#34;two-approaches-to-authentication-jwt-and-api-keys&#34;&gt;Two approaches to authentication: JWT and API Keys&lt;/h3&gt;
&lt;p&gt;In this article, we&amp;rsquo;ll take an existing ASP.NET Core Web API and add authentication capabilities to it. Specifically, we&amp;rsquo;ll support two authentication schemes commonly used for Web APIs: JWT and API Keys. Also, we will use our own database for storage of user accounts and credentials.&lt;/p&gt;
&lt;p&gt;The project that we will work with is a simple ASP.NET Web API backed by a &lt;a href=&#34;https://www.postgresql.org/&#34;&gt;Postgres&lt;/a&gt; database. It has a few endpoints for &lt;a href=&#34;https://en.wikipedia.org/wiki/Create,_read,_update_and_delete&#34;&gt;CRUD&lt;/a&gt;ing automotive related data and for calculating values of vehicles based on various aspects of them. You can read all about the process of building it &lt;a href=&#34;https://www.endpointdev.com/blog/2021/07/dotnet-5-web-api/&#34;&gt;here&lt;/a&gt;. I also added a few database integration tests for it &lt;a href=&#34;https://www.endpointdev.com/blog/2022/01/database-integration-testing-with-dotnet/&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;You can find it &lt;a href=&#34;https://github.com/megakevin/end-point-blog-dotnet-5-web-api&#34;&gt;on GitHub&lt;/a&gt;. If you&amp;rsquo;d like to follow along, clone the repository and checkout this commit: &lt;a href=&#34;https://github.com/megakevin/end-point-blog-dotnet-5-web-api/tree/cd290c765fcd2c6693008d3dc76fa931098dcaa0&#34;&gt;cd290c765fcd2c6693008d3dc76fa931098dcaa0&lt;/a&gt;. It represents the project as it was before applying all the changes from this article.&lt;/p&gt;
&lt;p&gt;You can follow the instructions in &lt;a href=&#34;https://github.com/megakevin/end-point-blog-dotnet-5-web-api/blob/json-web-token/VehicleQuotes/README.md&#34;&gt;the project&amp;rsquo;s README file&lt;/a&gt; in order to get the app up and running.&lt;/p&gt;
&lt;h3 id=&#34;managing-user-accounts-with-aspnet-core-identity&#34;&gt;Managing user accounts with ASP.NET Core Identity&lt;/h3&gt;
&lt;p&gt;Let&amp;rsquo;s deal first with the requirement of storing the user accounts in our own database.&lt;/p&gt;
&lt;p&gt;Luckily for us, ASP.NET Core provides us with &lt;a href=&#34;https://docs.microsoft.com/en-us/aspnet/core/security/authentication/identity?view=aspnetcore-6.0&amp;amp;tabs=netcore-cli&#34;&gt;Identity&lt;/a&gt;. This is an API that offers a comprehensive solution for authentication. It can connect with the aforementioned Duende
IdentityServer for &lt;a href=&#34;https://openid.net/connect/&#34;&gt;OpenID Connect&lt;/a&gt; and &lt;a href=&#34;https://oauth.net/2/&#34;&gt;OAuth 2.0&lt;/a&gt;, supports authentication via third parties like Facebook or Google, and can fully integrate with user interfaces on web apps, complete with scaffolding/​autogeneration capabilities too.&lt;/p&gt;
&lt;p&gt;Most importantly for us, it supports management of user accounts stored in our own database. It includes data for third party logins, passwords, roles for authorization, email confirmation, access tokens, etc.&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s a lot of of functionality baked in there. But we don&amp;rsquo;t need all that, so let&amp;rsquo;s see how we can take only the bits and pieces that we need in order to fulfill our specific requirements.&lt;/p&gt;
&lt;p&gt;Specifically, we want:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Tables in our database for storage of user accounts and passwords.&lt;/li&gt;
&lt;li&gt;A programmatic way to create, fetch and validate users using those tables.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;It&amp;rsquo;s actually pretty simple.&lt;/p&gt;
&lt;h4 id=&#34;install-the-necessary-nuget-packages&#34;&gt;Install the necessary NuGet packages&lt;/h4&gt;
&lt;p&gt;First, we need to install a couple of &lt;a href=&#34;https://www.nuget.org/&#34;&gt;NuGet&lt;/a&gt; packages:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://www.nuget.org/packages/Microsoft.AspNetCore.Identity/&#34;&gt;Microsoft.AspNetCore.Identity&lt;/a&gt; which contains the core library.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.nuget.org/packages/Microsoft.AspNetCore.Identity.EntityFrameworkCore&#34;&gt;Microsoft.AspNetCore.Identity.EntityFrameworkCore&lt;/a&gt; which includes the classes that Identity needs in order to properly interact with &lt;a href=&#34;https://docs.microsoft.com/en-us/ef/&#34;&gt;Entity Framework&lt;/a&gt;, which is what we&amp;rsquo;re using in our Web API for interfacing with the database.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We can install them by running these two commands from the &lt;code&gt;VehicleQuotes&lt;/code&gt; directory:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ dotnet add package Microsoft.AspNetCore.Identity
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ dotnet add package Microsoft.AspNetCore.Identity.EntityFrameworkCore&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;That will add the following lines to the &lt;code&gt;VehicleQuotes/VehicleQuotes.csproj&lt;/code&gt; project file:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-diff&#34; data-lang=&#34;diff&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &amp;lt;Project Sdk=&amp;#34;Microsoft.NET.Sdk.Web&amp;#34;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &amp;lt;ItemGroup&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;background-color:#dfd&#34;&gt;+    &amp;lt;PackageReference Include=&amp;#34;Microsoft.AspNetCore.Identity&amp;#34; Version=&amp;#34;2.2.0&amp;#34; /&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;background-color:#dfd&#34;&gt;+    &amp;lt;PackageReference Include=&amp;#34;Microsoft.AspNetCore.Identity.EntityFrameworkCore&amp;#34; Version=&amp;#34;6.0.5&amp;#34; /&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;background-color:#dfd&#34;&gt;&lt;/span&gt;     ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &amp;lt;/ItemGroup&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &amp;lt;/Project&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h4 id=&#34;update-the-dbcontext-to-include-the-identity-tables&#34;&gt;Update the DbContext to include the Identity tables&lt;/h4&gt;
&lt;p&gt;Next step is to configure our &lt;code&gt;DbContext&lt;/code&gt; class so that it includes the new tables that we need from the Identity library. So let&amp;rsquo;s go to &lt;code&gt;VehicleQuotes/Data/VehicleQuotesContext.cs&lt;/code&gt; and update it to do so.&lt;/p&gt;
&lt;p&gt;We need to include these new &lt;code&gt;using&lt;/code&gt; statements at the top of the file so that we have access to the classes that we need from the NuGet packages we just installed:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-csharp&#34; data-lang=&#34;csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;using&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;Microsoft.AspNetCore.Identity&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;using&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;Microsoft.AspNetCore.Identity.EntityFrameworkCore&lt;/span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Next, instead of &lt;code&gt;DbContext&lt;/code&gt;, the &lt;code&gt;VehicleQuotesContext&lt;/code&gt; class should inherit from &lt;code&gt;IdentityUserContext&amp;lt;IdentityUser&amp;gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;IdentityUserContext&lt;/code&gt; is a class provided by ASP.NET Core Identity that&amp;rsquo;s designed so that our &lt;code&gt;DbContext&lt;/code&gt; can inherit from it and gain user management functionality. Namely, it includes a new &lt;code&gt;DbSet&lt;/code&gt; (and consequently, a table) for holding user accounts (aptly named &lt;code&gt;Users&lt;/code&gt;), among other things that we won&amp;rsquo;t need.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;IdentityUserContext&lt;/code&gt; has a more feature rich counterpart called &lt;code&gt;IdentityDbContext&lt;/code&gt;, which also includes &lt;code&gt;DbSet&lt;/code&gt;s to support roles based authorization. We don&amp;rsquo;t need all that so we use its simpler cousin. Feel free to explore the &lt;a href=&#34;https://github.com/dotnet/aspnetcore/blob/main/src/Identity/EntityFrameworkCore/src/IdentityDbContext.cs&#34;&gt;source code on GitHub&lt;/a&gt; to see all it offers.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;The &lt;a href=&#34;https://docs.microsoft.com/en-us/dotnet/standard/generics/&#34;&gt;generic type parameter&lt;/a&gt; that we give it, &lt;code&gt;IdentityUser&lt;/code&gt;, is a class that&amp;rsquo;s also provided by the Identity library. Its purpose is to serve as a default &lt;a href=&#34;https://docs.microsoft.com/en-us/ef/core/modeling/entity-types?tabs=data-annotations&#34;&gt;Entity Type&lt;/a&gt; for our user model and, as a consequence, our &lt;code&gt;Users&lt;/code&gt; &lt;code&gt;DbSet&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;In summary, by having our &lt;code&gt;DbContext&lt;/code&gt; class inherit from &lt;code&gt;IdentityUserContext&amp;lt;IdentityUser&amp;gt;&lt;/code&gt;, we&amp;rsquo;re telling Identity that we want it to augment our &lt;code&gt;DbContext&lt;/code&gt; (and database) to include the core user management tables and that we want our users table to have the same columns as &lt;code&gt;IdentityUser&lt;/code&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;If we wanted to include more columns in our users table, what we would have to do is create a new class, make it inherit from &lt;code&gt;IdentityUser&lt;/code&gt;, define any additional fields that we want on it, and use that class as a type parameter to &lt;code&gt;IdentityUserContext&lt;/code&gt;. For us for now, the default works just fine. You can learn more about customizing Identity in &lt;a href=&#34;https://docs.microsoft.com/en-us/aspnet/core/security/authentication/customize-identity-model?view=aspnetcore-6.0&#34;&gt;the official docs&lt;/a&gt;.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;The change looks like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-diff&#34; data-lang=&#34;diff&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;background-color:#fdd&#34;&gt;-public class VehicleQuotesContext : DbContext
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;background-color:#fdd&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#000;background-color:#dfd&#34;&gt;+public class VehicleQuotesContext : IdentityUserContext&amp;lt;IdentityUser&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Finally, &lt;code&gt;IdentityUserContext&lt;/code&gt; has some logic that it needs to run when it is being created. In order to allow it to run that logic, let&amp;rsquo;s add the following line to our &lt;code&gt;VehicleQuotesContext&lt;/code&gt;&amp;rsquo;s &lt;code&gt;OnModelCreating&lt;/code&gt; method:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-diff&#34; data-lang=&#34;diff&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; protected override void OnModelCreating(ModelBuilder modelBuilder)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;background-color:#dfd&#34;&gt;+    base.OnModelCreating(modelBuilder);
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;background-color:#dfd&#34;&gt;&lt;/span&gt;     // ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This calls &lt;code&gt;IdentityUserContext&lt;/code&gt;&amp;rsquo;s own &lt;code&gt;OnModelCreating&lt;/code&gt; implementation so that it can set itself up properly.&lt;/p&gt;
&lt;p&gt;The complete file should be looking like this now:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-csharp&#34; data-lang=&#34;csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;using&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;Microsoft.AspNetCore.Identity&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;using&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;Microsoft.AspNetCore.Identity.EntityFrameworkCore&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;using&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;Microsoft.EntityFrameworkCore&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;using&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;VehicleQuotes.Models&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;namespace&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;VehicleQuotes&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;VehicleQuotesContext&lt;/span&gt; : IdentityUserContext&amp;lt;IdentityUser&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;public&lt;/span&gt; VehicleQuotesContext (DbContextOptions&amp;lt;VehicleQuotesContext&amp;gt; options)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            : &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;base&lt;/span&gt;(options)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;public&lt;/span&gt; DbSet&amp;lt;Make&amp;gt; Makes { &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;get&lt;/span&gt;; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;set&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;public&lt;/span&gt; DbSet&amp;lt;Size&amp;gt; Sizes { &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;get&lt;/span&gt;; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;set&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;public&lt;/span&gt; DbSet&amp;lt;BodyType&amp;gt; BodyTypes { &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;get&lt;/span&gt;; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;set&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;public&lt;/span&gt; DbSet&amp;lt;Model&amp;gt; Models { &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;get&lt;/span&gt;; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;set&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;public&lt;/span&gt; DbSet&amp;lt;ModelStyle&amp;gt; ModelStyles { &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;get&lt;/span&gt;; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;set&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;public&lt;/span&gt; DbSet&amp;lt;ModelStyleYear&amp;gt; ModelStyleYears { &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;get&lt;/span&gt;; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;set&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;public&lt;/span&gt; DbSet&amp;lt;QuoteRule&amp;gt; QuoteRules { &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;get&lt;/span&gt;; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;set&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;public&lt;/span&gt; DbSet&amp;lt;QuoteOverride&amp;gt; QuoteOverides { &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;get&lt;/span&gt;; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;set&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;public&lt;/span&gt; DbSet&amp;lt;Quote&amp;gt; Quotes { &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;get&lt;/span&gt;; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;set&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;protected&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;override&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;void&lt;/span&gt; OnModelCreating(ModelBuilder modelBuilder)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;base&lt;/span&gt;.OnModelCreating(modelBuilder);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            modelBuilder.Entity&amp;lt;Size&amp;gt;().HasData(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;new&lt;/span&gt; Size { ID = &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;1&lt;/span&gt;, Name = &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;Subcompact&amp;#34;&lt;/span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;new&lt;/span&gt; Size { ID = &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;2&lt;/span&gt;, Name = &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;Compact&amp;#34;&lt;/span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;new&lt;/span&gt; Size { ID = &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;3&lt;/span&gt;, Name = &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;Mid Size&amp;#34;&lt;/span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;new&lt;/span&gt; Size { ID = &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;5&lt;/span&gt;, Name = &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;Full Size&amp;#34;&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            );
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            modelBuilder.Entity&amp;lt;BodyType&amp;gt;().HasData(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;new&lt;/span&gt; BodyType { ID = &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;1&lt;/span&gt;, Name = &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;Coupe&amp;#34;&lt;/span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;new&lt;/span&gt; BodyType { ID = &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;2&lt;/span&gt;, Name = &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;Sedan&amp;#34;&lt;/span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;new&lt;/span&gt; BodyType { ID = &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;3&lt;/span&gt;, Name = &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;Hatchback&amp;#34;&lt;/span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;new&lt;/span&gt; BodyType { ID = &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;4&lt;/span&gt;, Name = &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;Wagon&amp;#34;&lt;/span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;new&lt;/span&gt; BodyType { ID = &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;5&lt;/span&gt;, Name = &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;Convertible&amp;#34;&lt;/span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;new&lt;/span&gt; BodyType { ID = &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;6&lt;/span&gt;, Name = &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;SUV&amp;#34;&lt;/span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;new&lt;/span&gt; BodyType { ID = &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;7&lt;/span&gt;, Name = &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;Truck&amp;#34;&lt;/span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;new&lt;/span&gt; BodyType { ID = &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;8&lt;/span&gt;, Name = &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;Mini Van&amp;#34;&lt;/span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;new&lt;/span&gt; BodyType { ID = &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;9&lt;/span&gt;, Name = &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;Roadster&amp;#34;&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            );
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h4 id=&#34;applying-database-changes&#34;&gt;Applying database changes&lt;/h4&gt;
&lt;p&gt;The &lt;code&gt;Users&lt;/code&gt; &lt;code&gt;DbSet&lt;/code&gt; that we added into our data model by inheriting from &lt;code&gt;IdentityUserContext&amp;lt;IdentityUser&amp;gt;&lt;/code&gt; will become a table once we create and apply a database migration. That&amp;rsquo;s what we will do next.&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s simple in ASP.NET Core. All we need to do is run a command like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;dotnet ef migrations add AddIdentityTables&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;That should produce a new migration file named something like &lt;code&gt;20220605003253_AddIdentityTables.cs&lt;/code&gt;. If you explore it, you&amp;rsquo;ll see how it contains the definitions for a few new database tables. Including the one that we want: &lt;code&gt;AspNetUsers&lt;/code&gt;. That&amp;rsquo;s the one that we will use to store our user account records.&lt;/p&gt;
&lt;p&gt;Next, we apply the migration with:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;dotnet ef database update&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If you now connect to the database, you&amp;rsquo;ll see the new tables in there.&lt;/p&gt;
&lt;p&gt;If you have the database running in a Docker container like we discussed in the beginning of the article, you should be able to connect to it with:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ psql -h localhost -U vehicle_quotes&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Then, to see the tables:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;vehicle_quotes=# \dt
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    List of relations
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; Schema |         Name          | Type  |     Owner      
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;--------+-----------------------+-------+----------------
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; public | AspNetUserClaims      | table | vehicle_quotes
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; public | AspNetUserLogins      | table | vehicle_quotes
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; public | AspNetUserTokens      | table | vehicle_quotes
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; public | AspNetUsers           | table | vehicle_quotes
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(14 rows)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And that&amp;rsquo;s pretty much it when it comes to having a sensible storage for user accounts. That was pretty inexpensive, wasn&amp;rsquo;t it? All we had to do was install some NuGet packages, tweak our existing DbContext, and run some migrations.&lt;/p&gt;
&lt;p&gt;The best thing is that we&amp;rsquo;re not done yet. We can also take advantage of ASP.NET Core Identity to manage users programmatically. Instead of interacting with these tables directly, we will use the service classes provided by Identity to create new users, fetch existing ones and validate their credentials.&lt;/p&gt;
&lt;p&gt;Before we can do that though, we must first do some configuration in our app&amp;rsquo;s &lt;code&gt;Startup&lt;/code&gt; class so that said services are properly set up to our liking and are made available to our application.&lt;/p&gt;
&lt;!-- Next step for us is creating and fetching users. Let&#39;s see how we can make that happen. --&gt;
&lt;h4 id=&#34;configuring-the-identity-services&#34;&gt;Configuring the Identity services&lt;/h4&gt;
&lt;p&gt;We need to add some code to &lt;code&gt;VehicleQuotes/Startup.cs&lt;/code&gt;. With it, we configure the Identity system and add a few service classes to ASP.NET Core&amp;rsquo;s &lt;a href=&#34;https://en.wikipedia.org/wiki/Inversion_of_control&#34;&gt;IoC&lt;/a&gt; &lt;a href=&#34;https://www.tutorialsteacher.com/ioc/ioc-container&#34;&gt;container&lt;/a&gt; so that they are available to our app via &lt;a href=&#34;https://en.wikipedia.org/wiki/Dependency_injection&#34;&gt;Dependency Injection&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;We need a new &lt;code&gt;using&lt;/code&gt; statement:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-csharp&#34; data-lang=&#34;csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;using&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;Microsoft.AspNetCore.Identity&lt;/span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And the following code added to the &lt;code&gt;ConfigureServices&lt;/code&gt; method:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-csharp&#34; data-lang=&#34;csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;services
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    .AddIdentityCore&amp;lt;IdentityUser&amp;gt;(options =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        options.SignIn.RequireConfirmedAccount = &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;false&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        options.User.RequireUniqueEmail = &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;true&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        options.Password.RequireDigit = &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;false&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        options.Password.RequiredLength = &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;6&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        options.Password.RequireNonAlphanumeric = &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;false&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        options.Password.RequireUppercase = &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;false&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        options.Password.RequireLowercase = &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;false&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    })
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    .AddEntityFrameworkStores&amp;lt;VehicleQuotesContext&amp;gt;();&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The call to &lt;code&gt;AddIdentityCore&lt;/code&gt; makes several Identity utility classes available to the application. Among those, &lt;code&gt;UserManager&lt;/code&gt; is the only one we will use. We will use it later to&amp;hellip; well, manage users. You can also see how we&amp;rsquo;ve set a few options related to how the user accounts are handled. &lt;code&gt;options.SignIn.RequireConfirmedAccount&lt;/code&gt; controls whether new accounts need to be confirmed via email before they are available. With &lt;code&gt;options.User.RequireUniqueEmail&lt;/code&gt;, we tell Identity to enforce uniqueness of emails on user accounts. And finally the &lt;code&gt;options.Password.*&lt;/code&gt; options configure the password strength requirements.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;You can explore all the available options in &lt;a href=&#34;https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.identity.identityoptions?view=aspnetcore-6.0&#34;&gt;the official docs&lt;/a&gt;.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;Then, the call to &lt;code&gt;AddEntityFrameworkStores&lt;/code&gt; tells the Identity system that it should use our &lt;code&gt;VehicleQuotesContext&lt;/code&gt; for data storage.&lt;/p&gt;
&lt;h4 id=&#34;creating-users&#34;&gt;Creating users&lt;/h4&gt;
&lt;p&gt;With that configuration out of the way, we can now write some code to create new user accounts. To keep things simple, we&amp;rsquo;ll add a new &lt;code&gt;UsersController&lt;/code&gt; to our project that will expose a new endpoint that offers that functionality.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s start with this in &lt;code&gt;VehicleQuotes/Controllers/UsersController.cs&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-csharp&#34; data-lang=&#34;csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;using&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;Microsoft.AspNetCore.Identity&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;using&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;Microsoft.AspNetCore.Mvc&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;namespace&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;VehicleQuotes.Controllers&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#369&#34;&gt;    [Route(&amp;#34;api/[controller]&lt;/span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;)]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#369&#34;&gt;    [ApiController]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;UsersController&lt;/span&gt; : ControllerBase
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;readonly&lt;/span&gt; UserManager&amp;lt;IdentityUser&amp;gt; _userManager;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;public&lt;/span&gt; UsersController(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            UserManager&amp;lt;IdentityUser&amp;gt; userManager
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            _userManager = userManager;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;As you can see, this controller defines a dependency on &lt;code&gt;UserManager&amp;lt;IdentityUser&amp;gt;&lt;/code&gt;, an instance of which is injected via the constructor. This is one of the classes made available to us when we configured the Identity core services in our app&amp;rsquo;s &lt;code&gt;Startup&lt;/code&gt;. We will use it to create new user records.&lt;/p&gt;
&lt;p&gt;Before that though, we need to define a new class that encapsulates the payload for a request to our endpoint. When it comes to creating user accounts, all we need is a username, a password, and an email. As such, we add the following class in a new &lt;code&gt;VehicleQuotes/ResourceModels/User.cs&lt;/code&gt; file:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-csharp&#34; data-lang=&#34;csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;using&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;System.ComponentModel.DataAnnotations&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;namespace&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;VehicleQuotes.ResourceModels&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;User&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#369&#34;&gt;        [Required]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;string&lt;/span&gt; UserName { &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;get&lt;/span&gt;; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;set&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#369&#34;&gt;        [Required]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;string&lt;/span&gt; Password { &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;get&lt;/span&gt;; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;set&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#369&#34;&gt;        [Required]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;string&lt;/span&gt; Email { &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;get&lt;/span&gt;; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;set&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now, we shall use this type as the parameter for a new &lt;code&gt;PostUser&lt;/code&gt; action method in the &lt;code&gt;UserController&lt;/code&gt; which will expose the new user account creation endpoint in our API. The method looks like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-csharp&#34; data-lang=&#34;csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;// POST: api/Users&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#369&#34;&gt;[HttpPost]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;async&lt;/span&gt; Task&amp;lt;ActionResult&amp;lt;User&amp;gt;&amp;gt; PostUser(User user)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;if&lt;/span&gt; (!ModelState.IsValid)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;return&lt;/span&gt; BadRequest(ModelState);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;var&lt;/span&gt; result = &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;await&lt;/span&gt; _userManager.CreateAsync(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;new&lt;/span&gt; IdentityUser() { UserName = user.UserName, Email = user.Email },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        user.Password
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    );
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;if&lt;/span&gt; (!result.Succeeded)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;return&lt;/span&gt; BadRequest(result.Errors);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    user.Password = &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;null&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;return&lt;/span&gt; Created(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;, user);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Be sure to also add the following &lt;code&gt;using&lt;/code&gt; statements:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-csharp&#34; data-lang=&#34;csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;using&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;System.Threading.Tasks&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;using&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;VehicleQuotes.ResourceModels&lt;/span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;System.Threading.Tasks&lt;/code&gt; allows us to reference the class &lt;code&gt;Task&amp;lt;&amp;gt;&lt;/code&gt; which is the return type of the new &lt;code&gt;PostUser&lt;/code&gt; method. &lt;code&gt;VehicleQuotes.ResourceModels&lt;/code&gt; is where our new &lt;code&gt;User&lt;/code&gt; class lives.&lt;/p&gt;
&lt;p&gt;Thanks to the instance of &lt;code&gt;UserManager&amp;lt;IdentityUser&amp;gt;&lt;/code&gt; that we&amp;rsquo;re holding onto, this method is very straightforward. The most interesting portion is this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-csharp&#34; data-lang=&#34;csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;var&lt;/span&gt; result = &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;await&lt;/span&gt; _userManager.CreateAsync(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;new&lt;/span&gt; IdentityUser() { UserName = user.UserName, Email = user.Email },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    user.Password
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Here we&amp;rsquo;re &lt;code&gt;new&lt;/code&gt;ing up an &lt;code&gt;IdentityUser&lt;/code&gt; instance using the given request parameters and passing it on to &lt;code&gt;UserManager&amp;lt;IdentityUser&amp;gt;&lt;/code&gt;&amp;rsquo;s &lt;code&gt;CreateAsync&lt;/code&gt; method, along with the password that was also given in the incoming request. This puts the Identity system to work for us and properly create a new user account.&lt;/p&gt;
&lt;p&gt;Then, we can inspect its return value (which we capture in the &lt;code&gt;result&lt;/code&gt; variable) to determine if the operation was successful. That way we can respond appropriately to our API&amp;rsquo;s caller.&lt;/p&gt;
&lt;p&gt;Finally, with&amp;hellip;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-csharp&#34; data-lang=&#34;csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;user.Password = &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;null&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;return&lt;/span&gt; Created(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;, user);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;we return the data representing the newly created user account but we&amp;rsquo;re discreet and make sure not to include the password.&lt;/p&gt;
&lt;p&gt;With that, we can test our API. Fire it up with &lt;code&gt;dotnet run&lt;/code&gt; (or &lt;a href=&#34;https://docs.microsoft.com/en-us/aspnet/core/test/hot-reload?view=aspnetcore-6.0&#34;&gt;&lt;code&gt;dotnet watch&lt;/code&gt;&lt;/a&gt;!) and send a &lt;code&gt;POST&lt;/code&gt; request to our new endpoint at &lt;code&gt;http://0.0.0.0:5000/api/Users&lt;/code&gt; with a payload like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;&amp;#34;userName&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;newuser000&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;&amp;#34;email&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;newuser000@endpointdev.com&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;&amp;#34;password&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;password&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;I just tried it in &lt;a href=&#34;https://www.postman.com/&#34;&gt;Postman&lt;/a&gt; and this is what it looked like:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2022/06/implementing-authentication-in-asp.net-core-web-apis/post-user.webp&#34; alt=&#34;Successful user creation request in Postman&#34;&gt;&lt;/p&gt;
&lt;p&gt;Feel free to test it out further. Try repeated emails or usernames. Try passwords that don&amp;rsquo;t meet the criteria we defined when configuring Identity in the app&amp;rsquo;s &lt;code&gt;Startup&lt;/code&gt; class. It all works as you&amp;rsquo;d expect.&lt;/p&gt;
&lt;p&gt;You can inspect the database and see the newly created record too:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;vehicle_quotes=# select id, user_name, email, password_hash from &amp;#34;AspNetUsers&amp;#34;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;-[ RECORD 1 ]-+--------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;id            | aaad07b4-f109-4255-8caa-185fd7694c72
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;user_name     | newuser000
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;email         | newuser000@endpointdev.com
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;password_hash | AQAAAAEAACcQAAAAEJJTV7M2Ejqd3K3iC...&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And there it is, that&amp;rsquo;s our record. With a hashed password and everything.&lt;/p&gt;
&lt;p&gt;Now let&amp;rsquo;s see what would an endpoint to fetch users look like:&lt;/p&gt;
&lt;h4 id=&#34;fetching-users&#34;&gt;Fetching users&lt;/h4&gt;
&lt;p&gt;&lt;code&gt;UserManager&amp;lt;IdentityUser&amp;gt;&lt;/code&gt; offers a &lt;code&gt;FindByNameAsync&lt;/code&gt; method that we can use to retrieve users by name. We can add a new endpoint that leverages it like so:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-csharp&#34; data-lang=&#34;csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;// GET: api/Users/username&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#369&#34;&gt;[HttpGet(&amp;#34;{username}&amp;#34;)]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;async&lt;/span&gt; Task&amp;lt;ActionResult&amp;lt;User&amp;gt;&amp;gt; GetUser(&lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;string&lt;/span&gt; username)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    IdentityUser user = &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;await&lt;/span&gt; _userManager.FindByNameAsync(username);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;if&lt;/span&gt; (user == &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;null&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;return&lt;/span&gt; NotFound();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;new&lt;/span&gt; User
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        UserName = user.UserName,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        Email = user.Email
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    };
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This is even more straightforward than the previous one. We just call the &lt;code&gt;FindByNameAsync&lt;/code&gt; method by giving it the username of the account we want, make sure that we actually found it, and then return the data.&lt;/p&gt;
&lt;p&gt;For the response, we use the same &lt;code&gt;User&lt;/code&gt; class that we created to represent the input for the creation endpoint. If we added more fields to the user profile, we could include them here. Alas, we only have username and email for now.&lt;/p&gt;
&lt;p&gt;Restart the app and we can now make a request like this:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2022/06/implementing-authentication-in-asp.net-core-web-apis/get-user.webp&#34; alt=&#34;Successful user fetch request in Postman&#34;&gt;&lt;/p&gt;
&lt;p&gt;Pretty neat, huh? Try a username that does not exist and you should see the API respond with a 404.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;One quick improvement that we can do before we move on: let&amp;rsquo;s change &lt;code&gt;PostUser&lt;/code&gt;&amp;rsquo;s return statement to this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-csharp&#34; data-lang=&#34;csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;return&lt;/span&gt; CreatedAtAction(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;GetUser&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;new&lt;/span&gt; { username = user.UserName }, user);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;All that does is include a &lt;code&gt;Location&lt;/code&gt; header on the POST Users endpoint&amp;rsquo;s response that contains the URL for the newly created user. &lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/201&#34;&gt;That&amp;rsquo;s just being a good citizen&lt;/a&gt;.&lt;/p&gt;&lt;/blockquote&gt;
&lt;h3 id=&#34;implementing-jwt-bearer-token-authentication&#34;&gt;Implementing JWT Bearer Token authentication&lt;/h3&gt;
&lt;p&gt;Now that we have the user management capabilities that we need, let&amp;rsquo;s implement some actual authentication. We will start by adding &lt;a href=&#34;https://jwt.io/&#34;&gt;JWT&lt;/a&gt;-based authentication to our API.&lt;/p&gt;
&lt;p&gt;The strategy that we will use is to create a new API endpoint that clients can &lt;code&gt;POST&lt;/code&gt; credentials to and that will respond to them with a fresh, short-lived token. They will then be able to use that token for subsequent requests by including it via headers.&lt;/p&gt;
&lt;p&gt;We will pick a random endpoint to secure, just to serve as an example. That is, an endpoint that requires authentication in order to be accessed. &lt;code&gt;GET api/BodyTypes&lt;/code&gt; is a good candidate. It is defined in &lt;code&gt;VehicleQuotes/Controllers/BodyTypesController.cs&lt;/code&gt;&amp;rsquo;s &lt;code&gt;GetBodyTypes&lt;/code&gt; action method. Feel free to test it out.&lt;/p&gt;
&lt;h4 id=&#34;creating-tokens&#34;&gt;Creating tokens&lt;/h4&gt;
&lt;p&gt;Let&amp;rsquo;s start by creating the new endpoint that clients will call to obtain the auth tokens. In order to do so, we need a few things:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;A class that represents incoming request data.&lt;/li&gt;
&lt;li&gt;A class that represents outgoing response data.&lt;/li&gt;
&lt;li&gt;A class that can generate tokens for a given user.&lt;/li&gt;
&lt;li&gt;A new action method in &lt;code&gt;UsersController&lt;/code&gt; that does the work.&lt;/li&gt;
&lt;/ol&gt;
&lt;h5 id=&#34;the-request-data-structure&#34;&gt;The request data structure&lt;/h5&gt;
&lt;p&gt;To deal with step one, let&amp;rsquo;s define a new class in &lt;code&gt;VehicleQuotes/ResourceModels/AuthenticationRequest.cs&lt;/code&gt; that looks like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-csharp&#34; data-lang=&#34;csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;using&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;System.ComponentModel.DataAnnotations&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;namespace&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;VehicleQuotes.ResourceModels&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;AuthenticationRequest&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#369&#34;&gt;        [Required]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;string&lt;/span&gt; UserName { &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;get&lt;/span&gt;; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;set&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#369&#34;&gt;        [Required]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;string&lt;/span&gt; Password { &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;get&lt;/span&gt;; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;set&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;All users need to authenticate is provide a set of credentials: username and password. So we have this class that contains fields for both and that will be used as input for our endpoint.&lt;/p&gt;
&lt;h5 id=&#34;the-response-data-structure&#34;&gt;The response data structure&lt;/h5&gt;
&lt;p&gt;Next, we need to define a class to represent that endpoint&amp;rsquo;s response. I&amp;rsquo;ve added the following class in &lt;code&gt;VehicleQuotes/ResourceModels/AuthenticationResponse.cs&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-csharp&#34; data-lang=&#34;csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;using&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;System&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;namespace&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;VehicleQuotes.ResourceModels&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;AuthenticationResponse&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;string&lt;/span&gt; Token { &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;get&lt;/span&gt;; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;set&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;public&lt;/span&gt; DateTime Expiration { &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;get&lt;/span&gt;; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;set&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Just a simple data structure containing the token itself and a date letting clients know when they can expect it to expire.&lt;/p&gt;
&lt;h5 id=&#34;the-class-that-creates-jwts&#34;&gt;The class that creates JWTs&lt;/h5&gt;
&lt;p&gt;Step 3 is creating a class that can produce the tokens. This is the most interesting part in terms of complexity. Before we can do that though, let&amp;rsquo;s add the following configurations to &lt;code&gt;VehicleQuotes/appsettings.json&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;Jwt&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;:&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;&amp;#34;Key&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;this is the secret key for the jwt, it must be kept secure&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;&amp;#34;Issuer&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;vehiclequotes.endpointdev.com&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;&amp;#34;Audience&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;vehiclequotes.endpointdev.com&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;&amp;#34;Subject&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;JWT for vehiclequotes.endpointdev.com&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;,&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;These are values that we&amp;rsquo;ll need when creating the tokens. We&amp;rsquo;ll go over the purpose of each them as they come up as we continue writing our code.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Here we&amp;rsquo;ll gloss over some details on the inner workings of JWTs as a standard. You can learn more about them at &lt;a href=&#34;https://jwt.io/introduction&#34;&gt;jwt.io&lt;/a&gt;.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;For now, let&amp;rsquo;s add the following class in &lt;code&gt;VehicleQuotes/Services/JwtService.cs&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-csharp&#34; data-lang=&#34;csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;using&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;System&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;using&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;System.IdentityModel.Tokens.Jwt&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;using&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;System.Security.Claims&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;using&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;System.Text&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;using&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;Microsoft.AspNetCore.Identity&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;using&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;Microsoft.Extensions.Configuration&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;using&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;Microsoft.IdentityModel.Tokens&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;using&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;VehicleQuotes.ResourceModels&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;namespace&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;VehicleQuotes.Services&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;JwtService&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;int&lt;/span&gt; EXPIRATION_MINUTES = &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;1&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;readonly&lt;/span&gt; IConfiguration _configuration;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;public&lt;/span&gt; JwtService(IConfiguration configuration)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            _configuration = configuration;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;public&lt;/span&gt; AuthenticationResponse CreateToken(IdentityUser user)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;var&lt;/span&gt; expiration = DateTime.UtcNow.AddMinutes(EXPIRATION_MINUTES);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;var&lt;/span&gt; token = CreateJwtToken(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                CreateClaims(user),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                CreateSigningCredentials(),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                expiration
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            );
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;var&lt;/span&gt; tokenHandler = &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;new&lt;/span&gt; JwtSecurityTokenHandler();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;new&lt;/span&gt; AuthenticationResponse {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                Token = tokenHandler.WriteToken(token),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                Expiration = expiration
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            };
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;private&lt;/span&gt; JwtSecurityToken CreateJwtToken(Claim[] claims, SigningCredentials credentials, DateTime expiration) =&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;new&lt;/span&gt; JwtSecurityToken(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                _configuration[&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;Jwt:Issuer&amp;#34;&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                _configuration[&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;Jwt:Audience&amp;#34;&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                claims,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                expires: expiration,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                signingCredentials: credentials
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            );
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;private&lt;/span&gt; Claim[] CreateClaims(IdentityUser user) =&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;new&lt;/span&gt;[] {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;new&lt;/span&gt; Claim(JwtRegisteredClaimNames.Sub, _configuration[&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;Jwt:Subject&amp;#34;&lt;/span&gt;]),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;new&lt;/span&gt; Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;new&lt;/span&gt; Claim(JwtRegisteredClaimNames.Iat, DateTime.UtcNow.ToString()),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;new&lt;/span&gt; Claim(ClaimTypes.NameIdentifier, user.Id),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;new&lt;/span&gt; Claim(ClaimTypes.Name, user.UserName),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;new&lt;/span&gt; Claim(ClaimTypes.Email, user.Email)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            };
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;private&lt;/span&gt; SigningCredentials CreateSigningCredentials() =&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;new&lt;/span&gt; SigningCredentials(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;new&lt;/span&gt; SymmetricSecurityKey(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    Encoding.UTF8.GetBytes(_configuration[&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;Jwt:Key&amp;#34;&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                ),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                SecurityAlgorithms.HmacSha256
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            );
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;CreateToken&lt;/code&gt; method is the element that&amp;rsquo;s most worth discussing here. It receives an instance of &lt;code&gt;IdentityUser&lt;/code&gt; as a parameter (which, remember, is the entity class that represents our user accounts), uses it to construct a JWT, and returns it within a &lt;code&gt;AuthenticationResponse&lt;/code&gt; object (which is what we decided that our endpoint would return). To do so, we use various classes built into .NET.&lt;/p&gt;
&lt;p&gt;The main class that represents the JWT is &lt;code&gt;JwtSecurityToken&lt;/code&gt;. We &lt;code&gt;new&lt;/code&gt; up one of those in the &lt;code&gt;CreateJwtToken&lt;/code&gt; method with this call:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-csharp&#34; data-lang=&#34;csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;new&lt;/span&gt; JwtSecurityToken (
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    _configuration[&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;Jwt:Issuer&amp;#34;&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    _configuration[&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;Jwt:Audience&amp;#34;&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    claims,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    expires: expiration,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    signingCredentials: credentials
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&amp;ldquo;Issuer&amp;rdquo; and &amp;ldquo;Audience&amp;rdquo; are two important values for how JWTs work. They specify which entity is creating the token (i.e. the &amp;ldquo;Issuer&amp;rdquo;) and which entity is the token intended for (i.e. the &amp;ldquo;Audience&amp;rdquo;). We use the &lt;code&gt;IConfiguration&lt;/code&gt; instance that we got as a dependency to fetch their values from the &lt;code&gt;VehicleQuotes/appsettings.json&lt;/code&gt; file.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The &amp;ldquo;Issuer&amp;rdquo; and &amp;ldquo;Audience&amp;rdquo; parameters in &lt;code&gt;JwtSecurityToken&lt;/code&gt;&amp;rsquo;s constructor correspond to JWT claims &lt;code&gt;iss&lt;/code&gt; and &lt;code&gt;aud&lt;/code&gt;, respectively. You can learn more about them and other claims in &lt;a href=&#34;https://datatracker.ietf.org/doc/html/rfc7519#section-4.1&#34;&gt;the RFC&lt;/a&gt;.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;The next parameter that &lt;code&gt;JwtSecurityToken&lt;/code&gt;&amp;rsquo;s constructor needs is the claims array. In JWT terms, a claim is essentially a statement about the entity for which the token is generated, some data that identifies it. For example, if we&amp;rsquo;re generating a token for a user, what you would expect to see in such a token&amp;rsquo;s claims are things like username, email, and any other non-secret profile info.&lt;/p&gt;
&lt;p&gt;In our case, as you can see in the &lt;code&gt;CreateClaims&lt;/code&gt; method, we add a number of claims:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-csharp&#34; data-lang=&#34;csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;new&lt;/span&gt;[] {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;new&lt;/span&gt; Claim(JwtRegisteredClaimNames.Sub, _configuration[&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;Jwt:Subject&amp;#34;&lt;/span&gt;]),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;new&lt;/span&gt; Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;new&lt;/span&gt; Claim(JwtRegisteredClaimNames.Iat, DateTime.UtcNow.ToString()),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;new&lt;/span&gt; Claim(ClaimTypes.NameIdentifier, user.Id),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;new&lt;/span&gt; Claim(ClaimTypes.Name, user.UserName),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;new&lt;/span&gt; Claim(ClaimTypes.Email, user.Email)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;};&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Along with the user id, name and email, we also add &lt;code&gt;sub&lt;/code&gt;, &lt;code&gt;jti&lt;/code&gt; and &lt;code&gt;iat&lt;/code&gt; claims. These are standardized claims of which you can learn more about in &lt;a href=&#34;https://datatracker.ietf.org/doc/html/rfc7519#section-4.1&#34;&gt;the RFC&lt;/a&gt;. The data that we put in here will make its way into the encoded token that our API caller eventually sees. We&amp;rsquo;ll see that later.&lt;/p&gt;
&lt;p&gt;The next parameter to &lt;code&gt;JwtSecurityToken&lt;/code&gt; is the expiration date of the token. Here we are setting it to just one minute in the future to comply with our original requirement that the token should be short-lived so that it only allows a handful of requests over a short period of time.&lt;/p&gt;
&lt;p&gt;Finally there&amp;rsquo;s the &lt;code&gt;signingCredentials&lt;/code&gt; parameter which tells the &lt;code&gt;JwtSecurityToken&lt;/code&gt; how to cryptographically sign the token. As you can see in the code:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-csharp&#34; data-lang=&#34;csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;new&lt;/span&gt; SigningCredentials(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;new&lt;/span&gt; SymmetricSecurityKey(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        Encoding.UTF8.GetBytes(_configuration[&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;Jwt:Key&amp;#34;&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    SecurityAlgorithms.HmacSha256
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;That&amp;rsquo;s a &lt;code&gt;SigningCredentials&lt;/code&gt; instance that we create using the &amp;ldquo;key&amp;rdquo; that we have configured in &lt;code&gt;VehicleQuotes/appsettings.json&lt;/code&gt;, along with the algorithm to use to produce it.&lt;/p&gt;
&lt;p&gt;And that&amp;rsquo;s about it. There isn&amp;rsquo;t much else to this class. It is somewhat involved but that&amp;rsquo;s just how JWTs are created in .NET.&lt;/p&gt;
&lt;h5 id=&#34;the-action-method-that-puts-it-all-together&#34;&gt;The action method that puts it all together&lt;/h5&gt;
&lt;p&gt;Now all we need to do is actually create an endpoint that exposes this functionality to clients. Since we have the core logic encapsulated in our &lt;code&gt;JwtService&lt;/code&gt; class, the actual action method is simple. Here are the changes that we need to make in order to implement it:&lt;/p&gt;
&lt;p&gt;First, on &lt;code&gt;VehicleQuotes/Controllers/UsersController.cs&lt;/code&gt;, we add a new using statement so that we can reference our new &lt;code&gt;JwtService&lt;/code&gt; class:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-csharp&#34; data-lang=&#34;csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;using&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;VehicleQuotes.Services&lt;/span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Next, we declare a new parameter of type &lt;code&gt;JwtService&lt;/code&gt; in the controller&amp;rsquo;s constructor so that we signal to ASP.NET Core&amp;rsquo;s Dependency Injection subsystem that we want to use one of those. We also hold onto it via a new instance variable called &lt;code&gt;_jwtService&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-diff&#34; data-lang=&#34;diff&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; // ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; public class UsersController : ControllerBase
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     private readonly UserManager&amp;lt;IdentityUser&amp;gt; _userManager;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;background-color:#dfd&#34;&gt;+    private readonly JwtService _jwtService;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;background-color:#dfd&#34;&gt;&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     public UsersController(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         UserManager&amp;lt;IdentityUser&amp;gt; userManager,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;background-color:#dfd&#34;&gt;+        JwtService jwtService
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;background-color:#dfd&#34;&gt;&lt;/span&gt;     ) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         _userManager = userManager;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;background-color:#dfd&#34;&gt;+        _jwtService = jwtService;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;background-color:#dfd&#34;&gt;&lt;/span&gt;     }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     // ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We also need to tell ASP.NET Core that &lt;code&gt;JwtService&lt;/code&gt; should be available for Dependency Injection. To do so, we can add this line in &lt;code&gt;VehicleQuotes/Startup.cs&lt;/code&gt;&amp;rsquo;s &lt;code&gt;ConfigureServices&lt;/code&gt; method:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-csharp&#34; data-lang=&#34;csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;services.AddScoped&amp;lt;Services.JwtService&amp;gt;();&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;Note that this way of defining dependencies is not recommended and only done this way here to keep things simple for an illustrative app that&amp;rsquo;s never going to run in production. Ideally what you want to do here is define the dependency as an abstraction (i.e. an interface) and a concrete implementation that fulfills it. For example:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-csharp&#34; data-lang=&#34;csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;services.AddScoped&amp;lt;ITokenCreationService, JwtService&amp;gt;();&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This way, classes that depend on this service can reference the interface, not the concrete type. In doing that, they adhere to the &lt;a href=&#34;https://en.wikipedia.org/wiki/Dependency_inversion_principle&#34;&gt;Dependency Inversion&lt;/a&gt; principle and become more easily testable because they allow mocks to be provided as dependencies.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;Finally, we write the actual action method:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-csharp&#34; data-lang=&#34;csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;// POST: api/Users/BearerToken&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#369&#34;&gt;[HttpPost(&amp;#34;BearerToken&amp;#34;)]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;async&lt;/span&gt; Task&amp;lt;ActionResult&amp;lt;AuthenticationResponse&amp;gt;&amp;gt; CreateBearerToken(AuthenticationRequest request)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;if&lt;/span&gt; (!ModelState.IsValid)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;return&lt;/span&gt; BadRequest(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;Bad credentials&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;var&lt;/span&gt; user = &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;await&lt;/span&gt; _userManager.FindByNameAsync(request.UserName);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;if&lt;/span&gt; (user == &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;null&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;return&lt;/span&gt; BadRequest(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;Bad credentials&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;var&lt;/span&gt; isPasswordValid = &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;await&lt;/span&gt; _userManager.CheckPasswordAsync(user, request.Password);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;if&lt;/span&gt; (!isPasswordValid)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;return&lt;/span&gt; BadRequest(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;Bad credentials&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;var&lt;/span&gt; token = _jwtService.CreateToken(user);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;return&lt;/span&gt; Ok(token);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Here too we&amp;rsquo;re leveraging the &lt;code&gt;UserManager&lt;/code&gt; instance that ASP.NET Core Identity so graciously provided us with. In summary, we find the user account by name using the incoming request data, check if the given password is correct, then ask our &lt;code&gt;JwtService&lt;/code&gt; to create a token for this user, and finally return it wrapped in a 200 response.&lt;/p&gt;
&lt;p&gt;If you hit that endpoint with a POST and a set of existing credentials, you should see something like this:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2022/06/implementing-authentication-in-asp.net-core-web-apis/post-bearer-token.webp&#34; alt=&#34;Successful JTW creation in Postman&#34;&gt;&lt;/p&gt;
&lt;p&gt;If you take that big string that came back in the &lt;code&gt;&amp;quot;token&amp;quot;&lt;/code&gt; field in the response JSON, and paste it in &lt;a href=&#34;https://jwt.io/&#34;&gt;jwt.io&lt;/a&gt;&amp;rsquo;s token decoder, you should be able to see all the claims that we added to the token:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2022/06/implementing-authentication-in-asp.net-core-web-apis/jwt-decoded.webp&#34; alt=&#34;The JTW decoded showing all the claims&#34;&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Notice that the keywords here are &amp;ldquo;Encoded&amp;rdquo; and &amp;ldquo;Decoded&amp;rdquo;. The claims that we put in our JWTs are not protected in any way. As such, we should never put secrets in there.&lt;/p&gt;&lt;/blockquote&gt;
&lt;h4 id=&#34;securing-an-endpoint-with-jwt-authentication&#34;&gt;Securing an endpoint with JWT authentication&lt;/h4&gt;
&lt;p&gt;Now that we have a way for obtaining tokens, let&amp;rsquo;s see how we can actually use them to gain access to some resources. To demonstrate that, let&amp;rsquo;s secure an endpoint in a way that it denies unauthenticated requests.&lt;/p&gt;
&lt;h5 id=&#34;applying-the-authorize-attribute&#34;&gt;Applying the Authorize attribute&lt;/h5&gt;
&lt;p&gt;First we need to signal ASP.NET Core that the endpoint requires auth. We do that by annotating the corresponding action method with the &lt;code&gt;Authorize&lt;/code&gt; attribute. We&amp;rsquo;ve already decided that we were going to use &lt;code&gt;VehicleQuotes/Controllers/BodyTypesController.cs&lt;/code&gt;&amp;rsquo;s &lt;code&gt;GetBodyTypes&lt;/code&gt; method as a guinea pig. So, let&amp;rsquo;s go into that file and add the following &lt;code&gt;using&lt;/code&gt; statement:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-csharp&#34; data-lang=&#34;csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;using&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;Microsoft.AspNetCore.Authorization&lt;/span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;That will allow us access to the attribute, which we can apply to the action method like so:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-diff&#34; data-lang=&#34;diff&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; // GET: api/BodyTypes
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;background-color:#dfd&#34;&gt;+ [Authorize]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;background-color:#dfd&#34;&gt;&lt;/span&gt;  [HttpGet]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  public async Task&amp;lt;ActionResult&amp;lt;IEnumerable&amp;lt;BodyType&amp;gt;&amp;gt;&amp;gt; GetBodyTypes()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      return await _context.BodyTypes.ToListAsync();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;With this, we&amp;rsquo;ve told ASP.NET Core that we want it to require auth for this endpoint.&lt;/p&gt;
&lt;h5 id=&#34;enabling-and-configuring-the-jwt-authentication&#34;&gt;Enabling and configuring the JWT authentication&lt;/h5&gt;
&lt;p&gt;Now, we need to tell it how to actually perform the check. To do that, we need to install the &lt;a href=&#34;https://www.nuget.org/packages/Microsoft.AspNetCore.Authentication.JwtBearer&#34;&gt;&lt;code&gt;Microsoft.AspNetCore.Authentication.JwtBearer&lt;/code&gt;&lt;/a&gt; NuGet package. We can do that from the &lt;code&gt;VehicleQuotes&lt;/code&gt; directory with the following command:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Once we have that installed, we get access to additional services which we can use to configure the &amp;ldquo;JwtBearer&amp;rdquo; authentication scheme. As usual, we do the configuration in &lt;code&gt;VehicleQuotes/Startup.cs&lt;/code&gt;&amp;rsquo;s. Here&amp;rsquo;s what we need to do:&lt;/p&gt;
&lt;p&gt;Add a few new &lt;code&gt;using&lt;/code&gt; statements:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-csharp&#34; data-lang=&#34;csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;using&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;Microsoft.AspNetCore.Authentication.JwtBearer&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;using&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;Microsoft.IdentityModel.Tokens&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;using&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;System.Text&lt;/span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Add the following code at the end of the &lt;code&gt;ConfigureServices&lt;/code&gt; method:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-csharp&#34; data-lang=&#34;csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;services
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    .AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    .AddJwtBearer(options =&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        options.TokenValidationParameters = &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;new&lt;/span&gt; TokenValidationParameters()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            ValidateIssuer = &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;true&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            ValidateAudience = &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;true&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            ValidateLifetime = &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;true&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            ValidateIssuerSigningKey = &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;true&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            ValidAudience = Configuration[&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;Jwt:Audience&amp;#34;&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            ValidIssuer = Configuration[&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;Jwt:Issuer&amp;#34;&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            IssuerSigningKey = &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;new&lt;/span&gt; SymmetricSecurityKey(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                Encoding.UTF8.GetBytes(Configuration[&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;Jwt:Key&amp;#34;&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            )
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        };
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    });&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The call to &lt;code&gt;AddAuthentication&lt;/code&gt; includes all the internal core service classes that are needed to do authentication in our app.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;JwtBearerDefaults.AuthenticationScheme&lt;/code&gt; parameter that we give it is the name of the authentication scheme to use as the default. More on that later. For now, know that ASP.NET Core supports multiple authentication schemes to be used at the same time. In fact, our own plan here is to eventually support two auth schemes: JWTs and API Keys. We&amp;rsquo;re starting with JWT first and as such, that&amp;rsquo;s the one we specify as the default.&lt;/p&gt;
&lt;p&gt;The call to &lt;code&gt;AddJwtBearer&lt;/code&gt; configures the JWT authentication scheme. That is, it allows the app to perform authentication checks based on an incoming JWT token.&lt;/p&gt;
&lt;p&gt;The most important part of the configuration is the values that we are passing to &lt;code&gt;TokenValidationParameters&lt;/code&gt;. As you can see, we are able to specify which aspects of the incoming JWTs to validate. You can see all available options for &lt;code&gt;TokenValidationParameters&lt;/code&gt; in &lt;a href=&#34;https://docs.microsoft.com/en-us/dotnet/api/microsoft.identitymodel.tokens.tokenvalidationparameters?view=azure-dotnet&#34;&gt;the official documentation&lt;/a&gt;. Here we&amp;rsquo;ve chosen to validate obvious things like the issuer, audience, and signing key.&lt;/p&gt;
&lt;p&gt;The last configuration step is to add this line right before &lt;code&gt;app.UseAuthorization();&lt;/code&gt; in the &lt;code&gt;Configure&lt;/code&gt; method:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-csharp&#34; data-lang=&#34;csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;app.UseAuthentication();&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;That will enable the authentication &lt;a href=&#34;https://docs.microsoft.com/en-us/aspnet/core/fundamentals/middleware/?view=aspnetcore-6.0&#34;&gt;middleware&lt;/a&gt;. That way the framework will perform authentication checks as part of the request processing pipeline. In other words, actually put all the configuration that we&amp;rsquo;ve done to good use.&lt;/p&gt;
&lt;p&gt;Alright, now that we have all the configuration ready and have secured an endpoint, let&amp;rsquo;s try hitting it with a GET on &lt;code&gt;api/BodyTypes&lt;/code&gt; and see what happens:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2022/06/implementing-authentication-in-asp.net-core-web-apis/unauthorized-response.webp&#34; alt=&#34;Unauthorized response for unauthenticated request&#34;&gt;&lt;/p&gt;
&lt;p&gt;Ok! So far so good. We made an unauthenticated request into an endpoint that requires authentication and as a result we got a 401 back. That&amp;rsquo;s just what we wanted.&lt;/p&gt;
&lt;p&gt;Now, let&amp;rsquo;s get a token by POSTing to &lt;code&gt;api/Users/BearerToken&lt;/code&gt;:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2022/06/implementing-authentication-in-asp.net-core-web-apis/post-bearer-token-2.webp&#34; alt=&#34;Another successful JTW creation in Postman&#34;&gt;&lt;/p&gt;
&lt;p&gt;We can copy that token and include as a header in the GET request to &lt;code&gt;api/BodyTypes&lt;/code&gt;. The header key should be &lt;code&gt;Authorization&lt;/code&gt; and the value should be &lt;code&gt;Bearer &amp;lt;our token&amp;gt;&lt;/code&gt;. In Postman, we can setup a similar request if we choose the &amp;ldquo;Authorization&amp;rdquo; tab, select &amp;ldquo;Bearer Token&amp;rdquo; in the &amp;ldquo;Type&amp;rdquo; drop-down list and paste the token in the &amp;ldquo;Token&amp;rdquo; text box.&lt;/p&gt;
&lt;p&gt;Do that, and you should now see a 200 response from the endpoint:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2022/06/implementing-authentication-in-asp.net-core-web-apis/authorized-response-jwt.webp&#34; alt=&#34;Successful response for request authenticated with JWT&#34;&gt;&lt;/p&gt;
&lt;p&gt;Neat! Now that we passed a valid token, it wants to talk to us again. Let a few minutes pass, enough for the token to expire and try the request again to see how it&amp;rsquo;s 401&amp;rsquo;ing again.&lt;/p&gt;
&lt;h3 id=&#34;implementing-api-key-authentication&#34;&gt;Implementing API Key authentication&lt;/h3&gt;
&lt;p&gt;Now let&amp;rsquo;s change gears from JWT and implement an alternate authentication strategy in our Web API: API Keys. Authentication with API Keys is fairly common in the web service world.&lt;/p&gt;
&lt;p&gt;The core idea of API Keys is that the API provider (in this case, us) produces a secret string that is given to the clients for safekeeping. The clients then can use that key to access the API and make as many requests as they want. So it&amp;rsquo;s essentially just a glorified password.&lt;/p&gt;
&lt;p&gt;The main functional differences when it comes to JWT as we have implemented it is that the API Keys won&amp;rsquo;t expire and that we will store them in our database. Then, when processing incoming requests, as part of the authentication step, our app will check if the given API Key exists in our internal records. If it does, then the request is allowed to go through, if it does not, then a 401 is sent back.&lt;/p&gt;
&lt;p&gt;This is going to be interesting because ASP.NET Core does not include an authentication scheme out of the box for this kind of behavior. For JWT, we were able to use the &lt;code&gt;Microsoft.AspNetCore.Authentication.JwtBearer&lt;/code&gt; package. For this we have to get our hands dirty and actually implement a custom authentication handler that will run the logic that we need.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s get started.&lt;/p&gt;
&lt;h4 id=&#34;creating-api-keys&#34;&gt;Creating API Keys&lt;/h4&gt;
&lt;p&gt;Similarly to when we implemented JWTs, we&amp;rsquo;ll start by creating the new endpoint that clients will call to obtain their keys. In order to make it work, we&amp;rsquo;ll need:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;A new model and database table to store the keys&lt;/li&gt;
&lt;li&gt;A service class to create the keys.&lt;/li&gt;
&lt;li&gt;A new action method in &lt;code&gt;UsersController&lt;/code&gt; that does the work.&lt;/li&gt;
&lt;/ol&gt;
&lt;h5 id=&#34;the-api-key-model-and-database-table&#34;&gt;The API Key model and database table&lt;/h5&gt;
&lt;p&gt;For storing API Keys, we just need a simple table that is linked to users via a one-to-many relationship and includes a name and a value. Using Entity Framework, our model could look like this in &lt;code&gt;VehicleQuotes/Models/UserApiKey.cs&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-csharp&#34; data-lang=&#34;csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;using&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;System.ComponentModel.DataAnnotations&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;using&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;System.Text.Json.Serialization&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;using&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;Microsoft.AspNetCore.Identity&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;using&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;Microsoft.EntityFrameworkCore&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;namespace&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;VehicleQuotes.Models&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#369&#34;&gt;    [Index(nameof(Value), IsUnique = true)]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;UserApiKey&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#369&#34;&gt;        [JsonIgnore]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;int&lt;/span&gt; ID { &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;get&lt;/span&gt;; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;set&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#369&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#369&#34;&gt;        [Required]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;string&lt;/span&gt; Value { &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;get&lt;/span&gt;; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;set&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#369&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#369&#34;&gt;        [JsonIgnore]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#369&#34;&gt;        [Required]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;string&lt;/span&gt; UserID { &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;get&lt;/span&gt;; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;set&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#369&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#369&#34;&gt;        [JsonIgnore]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;public&lt;/span&gt; IdentityUser User { &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;get&lt;/span&gt;; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;set&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Easy enough. We express the relationship between the &amp;ldquo;keys&amp;rdquo; and &amp;ldquo;users&amp;rdquo; tables via the &lt;code&gt;User&lt;/code&gt; navigation property and the &lt;code&gt;UserID&lt;/code&gt; field. We also define a unique index on the &lt;code&gt;Value&lt;/code&gt; field and annotate some fields with &lt;code&gt;Required&lt;/code&gt; because we don&amp;rsquo;t want them to allow null. Interestingly, we also annotated some of the fields with the &lt;code&gt;JsonIgnore&lt;/code&gt; attribute so that when we include objects of this type in API responses (which, as you&amp;rsquo;ll see, we will), those fields are not included.&lt;/p&gt;
&lt;p&gt;We also need to add a new &lt;code&gt;DbSet&lt;/code&gt; on our DbContext class at &lt;code&gt;VehicleQuotes/Data/VehicleQuotesContext.cs&lt;/code&gt; so that Entity Framework picks it up as part of the data model:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-csharp&#34; data-lang=&#34;csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;public&lt;/span&gt; DbSet&amp;lt;UserApiKey&amp;gt; UserApiKeys { &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;get&lt;/span&gt;; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;set&lt;/span&gt;; }&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;With that, let&amp;rsquo;s now create and run a migration so that the new table can be added to the database. All it takes is running this to create the migration:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;dotnet ef migrations add AddUserApiKeysTable&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And this to apply it:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;dotnet ef database update&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now the new table should appear in the database:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;vehicle_quotes=# \dt
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    List of relations
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; Schema |         Name          | Type  |     Owner      
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;--------+-----------------------+-------+----------------
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; public | user_api_keys         | table | vehicle_quotes
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; (15 rows)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h5 id=&#34;the-class-that-creates-api-keys&#34;&gt;The class that creates API Keys&lt;/h5&gt;
&lt;p&gt;The next step is very straightforward. All we need is some logic that, when given a user account (in the form of an instance of &lt;code&gt;IdentityUser&lt;/code&gt;), can generate a new API Key, insert it in the database, and return it. The following unremarkable class, defined in &lt;code&gt;VehicleQuotes/Services/ApiKeyService.cs&lt;/code&gt;, encapsulates said logic:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-csharp&#34; data-lang=&#34;csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;using&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;System&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;using&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;Microsoft.AspNetCore.Identity&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;using&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;VehicleQuotes.Models&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;namespace&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;VehicleQuotes.Services&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;ApiKeyService&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;readonly&lt;/span&gt; VehicleQuotesContext _context;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;public&lt;/span&gt; ApiKeyService(VehicleQuotesContext context)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            _context = context;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;public&lt;/span&gt; UserApiKey CreateApiKey(IdentityUser user)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;var&lt;/span&gt; newApiKey = &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;new&lt;/span&gt; UserApiKey
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                User = user,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                Value = GenerateApiKeyValue()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            };
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            _context.UserApiKeys.Add(newApiKey);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            _context.SaveChanges();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;return&lt;/span&gt; newApiKey;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;string&lt;/span&gt; GenerateApiKeyValue() =&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;$&amp;#34;{Guid.NewGuid().ToString()}-{Guid.NewGuid().ToString()}&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;As you can see, this class&amp;rsquo;s single public method, aptly named &lt;code&gt;CreateApiKey&lt;/code&gt;, just takes the given user and creates a new &lt;code&gt;UserApiKey&lt;/code&gt; that&amp;rsquo;s associated with it and saves it into the database. The key values themselves are just two &lt;a href=&#34;https://en.wikipedia.org/wiki/Universally_unique_identifier&#34;&gt;GUIDs&lt;/a&gt; concatenated.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;This is an admittedly simplistic and not-all-that-secure method for generating the keys themselves. For simplicity, we&amp;rsquo;ve gone with this. In a production app however, it&amp;rsquo;d be better to use a true cryptographically secure string. &lt;a href=&#34;https://jonathancrozier.com/blog/how-to-generate-a-cryptographically-secure-random-string-in-dot-net-with-c-sharp&#34;&gt;Here&amp;rsquo;s an article&lt;/a&gt; that explains how to do that with .NET.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;Naturally, this class needs to be used elsewhere in the application, so let&amp;rsquo;s make it available for Dependency Injection by adding the following line to &lt;code&gt;VehicleQuotes/Startup.cs&lt;/code&gt;&amp;rsquo;s &lt;code&gt;ConfigureServices&lt;/code&gt; method.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-csharp&#34; data-lang=&#34;csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;services.AddScoped&amp;lt;Services.ApiKeyService&amp;gt;();&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h5 id=&#34;the-action-method-that-puts-it-all-together-1&#34;&gt;The action method that puts it all together&lt;/h5&gt;
&lt;p&gt;Now let&amp;rsquo;s finally write a new action method on &lt;code&gt;VehicleQuotes/Controllers/UsersController.cs&lt;/code&gt; so that there&amp;rsquo;s an endpoint that clients can call to get API Keys. Before adding the action method though, as usual, we need to declare the following dependency as a constructor parameter and hold it in an instance variable:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-diff&#34; data-lang=&#34;diff&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; public class UsersController : ControllerBase
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     private readonly UserManager&amp;lt;IdentityUser&amp;gt; _userManager;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     private readonly JwtService _jwtService;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;background-color:#dfd&#34;&gt;+    private readonly ApiKeyService _apiKeyService;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;background-color:#dfd&#34;&gt;&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     public UsersController(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         UserManager&amp;lt;IdentityUser&amp;gt; userManager,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         JwtService jwtService,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;background-color:#dfd&#34;&gt;+        ApiKeyService apiKeyService 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;background-color:#dfd&#34;&gt;&lt;/span&gt;     ) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         _userManager = userManager;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         _jwtService = jwtService;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;background-color:#dfd&#34;&gt;+        _apiKeyService = apiKeyService;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;background-color:#dfd&#34;&gt;&lt;/span&gt;     }}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The action method itself would look like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-csharp&#34; data-lang=&#34;csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;// POST: api/Users/ApiKey&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#369&#34;&gt;[HttpPost(&amp;#34;ApiKey&amp;#34;)]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;async&lt;/span&gt; Task&amp;lt;ActionResult&amp;gt; CreateApiKey(AuthenticationRequest request)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;if&lt;/span&gt; (!ModelState.IsValid)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;return&lt;/span&gt; BadRequest(ModelState);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;var&lt;/span&gt; user = &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;await&lt;/span&gt; _userManager.FindByNameAsync(request.UserName);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;if&lt;/span&gt; (user == &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;null&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;return&lt;/span&gt; BadRequest(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;Bad credentials&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;var&lt;/span&gt; isPasswordValid = &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;await&lt;/span&gt; _userManager.CheckPasswordAsync(user, request.Password);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;if&lt;/span&gt; (!isPasswordValid)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;return&lt;/span&gt; BadRequest(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;Bad credentials&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;var&lt;/span&gt; token = _apiKeyService.CreateApiKey(user);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;return&lt;/span&gt; Ok(token);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This method is very similar to the other one that generates JWTs. Painfully so. In fact the only difference is that this one calls the &lt;code&gt;ApiKeyService&lt;/code&gt;&amp;rsquo;s &lt;code&gt;CreateApiKey&lt;/code&gt; method instead of &lt;code&gt;JwtService&lt;/code&gt;&amp;rsquo;s &lt;code&gt;CreateToken&lt;/code&gt;, for obvious reasons.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;These two are ripe for some refactoring to eliminate duplication but we won&amp;rsquo;t do that here. Take a look at the &lt;a href=&#34;https://github.com/megakevin/end-point-blog-dotnet-5-web-api/tree/json-web-token&#34;&gt;finished project on GitHub&lt;/a&gt; to see &lt;a href=&#34;https://github.com/megakevin/end-point-blog-dotnet-5-web-api/commit/9a078015cec2e8a42a4898e203a1a50db69731e8&#34;&gt;a neat refactoring option&lt;/a&gt;.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;Anyway, you can now try a POST into &lt;code&gt;api/Users/ApiKey&lt;/code&gt;, pass it a valid set of credentials, and you should see it respond with a brand new API Key:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2022/06/implementing-authentication-in-asp.net-core-web-apis/post-api-key.webp&#34; alt=&#34;Successful response for authenticated request&#34;&gt;&lt;/p&gt;
&lt;p&gt;The key can also be found in the database:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;vehicle_quotes=# select id, SUBSTRING(value,1,13), user_id from user_api_keys;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; id |   substring   |               user_id                
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;----+---------------+--------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  1 | efd2133b-cc4a | aaad07b4-f109-4255-8caa-185fd7694c72
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(1 row)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h4 id=&#34;securing-an-endpoint-with-api-key-authentication&#34;&gt;Securing an endpoint with API Key authentication&lt;/h4&gt;
&lt;p&gt;Now that users have a way of getting API Keys, we can start securing endpoints with that authentication scheme. In order to acomplish that, we need to take three steps:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Implement a custom authentication handler that runs the authentication logic.&lt;/li&gt;
&lt;li&gt;Configure the new authentication handler, plugging it into ASP.NET Core&amp;rsquo;s auth mechanisms.&lt;/li&gt;
&lt;li&gt;Secure certain endpoints via the Authorization attribute, specifying the scheme that we want to use to do so.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;We&amp;rsquo;ll do that next.&lt;/p&gt;
&lt;h5 id=&#34;implementing-the-api-key-authentication-handler&#34;&gt;Implementing the API Key authentication handler&lt;/h5&gt;
&lt;p&gt;Like we&amp;rsquo;ve touched on before, the &amp;ldquo;authentication handler&amp;rdquo; is a class that can plug into ASP.NET Core&amp;rsquo;s authentication middleware and can run the authentication logic for a given authentication scheme. In practical terms, it&amp;rsquo;s a class that inherits from &lt;code&gt;Microsoft.AspNetCore.Authentication.AuthenticationHandler&lt;/code&gt; and implements the &lt;code&gt;HandleAuthenticateAsync&lt;/code&gt; method. Ours will live in &lt;code&gt;VehicleQuotes/Authentication/ApiKey/ApiKeyAuthenticationHandler.cs&lt;/code&gt; and it looks like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-csharp&#34; data-lang=&#34;csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;using&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;System.Security.Claims&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;using&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;System.Text.Encodings.Web&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;using&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;System.Threading.Tasks&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;using&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;Microsoft.AspNetCore.Authentication&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;using&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;Microsoft.AspNetCore.Identity&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;using&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;Microsoft.EntityFrameworkCore&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;using&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;Microsoft.Extensions.Logging&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;using&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;Microsoft.Extensions.Options&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;namespace&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;VehicleQuotes.Authentication.ApiKey&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;ApiKeyAuthenticationHandler&lt;/span&gt; : AuthenticationHandler&amp;lt;AuthenticationSchemeOptions&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;string&lt;/span&gt; API_KEY_HEADER = &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;Api-Key&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;readonly&lt;/span&gt; VehicleQuotesContext _context;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;public&lt;/span&gt; ApiKeyAuthenticationHandler(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            IOptionsMonitor&amp;lt;AuthenticationSchemeOptions&amp;gt; options,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            ILoggerFactory logger,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            UrlEncoder encoder,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            ISystemClock clock,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            VehicleQuotesContext context
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ) : &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;base&lt;/span&gt;(options, logger, encoder, clock)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            _context = context;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;protected&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;override&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;async&lt;/span&gt; Task&amp;lt;AuthenticateResult&amp;gt; HandleAuthenticateAsync()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;if&lt;/span&gt; (!Request.Headers.ContainsKey(API_KEY_HEADER))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;return&lt;/span&gt; AuthenticateResult.Fail(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;Header Not Found.&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;string&lt;/span&gt; apiKeyToValidate = Request.Headers[API_KEY_HEADER];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;var&lt;/span&gt; apiKey = &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;await&lt;/span&gt; _context.UserApiKeys
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                .Include(uak =&amp;gt; uak.User)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                .SingleOrDefaultAsync(uak =&amp;gt; uak.Value == apiKeyToValidate);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;if&lt;/span&gt; (apiKey == &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;null&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;return&lt;/span&gt; AuthenticateResult.Fail(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;Invalid key.&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;return&lt;/span&gt; AuthenticateResult.Success(CreateTicket(apiKey.User));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;private&lt;/span&gt; AuthenticationTicket CreateTicket(IdentityUser user)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;var&lt;/span&gt; claims = &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;new&lt;/span&gt;[] {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;new&lt;/span&gt; Claim(ClaimTypes.NameIdentifier, user.Id),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;new&lt;/span&gt; Claim(ClaimTypes.Name, user.UserName),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;new&lt;/span&gt; Claim(ClaimTypes.Email, user.Email)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            };
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;var&lt;/span&gt; identity = &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;new&lt;/span&gt; ClaimsIdentity(claims, Scheme.Name);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;var&lt;/span&gt; principal = &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;new&lt;/span&gt; ClaimsPrincipal(identity);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;var&lt;/span&gt; ticket = &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;new&lt;/span&gt; AuthenticationTicket(principal, Scheme.Name);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;return&lt;/span&gt; ticket;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The first thing to note is how we&amp;rsquo;ve defined the base class: &lt;code&gt;AuthenticationHandler&amp;lt;AuthenticationSchemeOptions&amp;gt;&lt;/code&gt;. &lt;code&gt;AuthenticationHandler&lt;/code&gt; is a generic, and it allows us to control the type of options object that it accepts. In this case, we&amp;rsquo;ve used &lt;code&gt;AuthenticationSchemeOptions&lt;/code&gt;, which is just a default one already provided by the framework. This is because we don&amp;rsquo;t really need any custom options.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;If we did, then we would define a new class that inherits from &lt;code&gt;AuthenticationSchemeOptions&lt;/code&gt;, give it the new fields that we need, and use that as a generic time parameter instead. We would then be able to set values for these new fields during configuration in the app&amp;rsquo;s &lt;code&gt;Startup&lt;/code&gt; class. Just like we&amp;rsquo;ve done with the &amp;ldquo;Jwt Bearer&amp;rdquo; auth scheme via the &lt;code&gt;AddJwtBearer&lt;/code&gt; method.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;The next point of interest in this class is its constructor. The key aspect of it is that it calls base and passes it a series of parameters that it itself gets. This is because &lt;code&gt;AuthenticationHandler&lt;/code&gt; does have some constructor logic that needs to be run for things to work properly, so we make sure to do that.&lt;/p&gt;
&lt;p&gt;Finally, there&amp;rsquo;s the &lt;code&gt;HandleAuthenticateAsync&lt;/code&gt; method which does the actual authentication. This method inspects the incoming request looking for an &amp;ldquo;Api-Key&amp;rdquo; header. If it finds it, it takes its value and makes a query into the database to try and find a record in the &lt;code&gt;user_api_keys&lt;/code&gt; table that matches the incoming value. If it finds that, it creates an &lt;code&gt;AuthenticationTicket&lt;/code&gt; which contains the identity of the user that the key belongs to, and returns it wrapped in a &lt;code&gt;AuthenticateResult.Success&lt;/code&gt;. That return value signals ASP.NET Core&amp;rsquo;s authentication middleware that the request is authentic. Otherwise, it returns &lt;code&gt;AuthenticateResult.Fail&lt;/code&gt;, which prompts ASP.NET Core to halt the request and return a 401.&lt;/p&gt;
&lt;p&gt;Something interesting to note is how the &lt;code&gt;AuthenticationTicket&lt;/code&gt;, similarly to the JWT Bearer scheme&amp;rsquo;s &lt;code&gt;JwtSecurityToken&lt;/code&gt;, also includes an array of &amp;ldquo;claims&amp;rdquo; that serve to identify the user that has been authenticated. The &amp;ldquo;claims&amp;rdquo; concept is central to how auth works in ASP.NET Core.&lt;/p&gt;
&lt;h5 id=&#34;enabling-and-configuring-the-api-key-authentication&#34;&gt;Enabling and configuring the API Key authentication&lt;/h5&gt;
&lt;p&gt;Now we need to tell the framework that we want it to use a new authentication scheme for our app, spearheaded by the custom authentication handler that we just wrote. There are two steps to make that happen.&lt;/p&gt;
&lt;p&gt;First, we configure our new scheme in the app&amp;rsquo;s &lt;code&gt;Startup&lt;/code&gt; class. For that, we need these two new &lt;code&gt;using&lt;/code&gt; statements:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-csharp&#34; data-lang=&#34;csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;using&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;Microsoft.AspNetCore.Authentication&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;using&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;VehicleQuotes.Authentication.ApiKey&lt;/span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Then we add this right after the &lt;code&gt;AddJwtBearer&lt;/code&gt; call in the &lt;code&gt;ConfigureServices&lt;/code&gt; method:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-diff&#34; data-lang=&#34;diff&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; public void ConfigureServices(IServiceCollection services)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     // ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     services
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         .AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         .AddJwtBearer(options =&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;             options.TokenValidationParameters = new TokenValidationParameters()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;             {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                 ValidateIssuer = true,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                 ValidateAudience = true,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                 ValidateLifetime = true,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                 ValidateIssuerSigningKey = true,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                 ValidAudience = Configuration[&amp;#34;Jwt:Audience&amp;#34;],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                 ValidIssuer = Configuration[&amp;#34;Jwt:Issuer&amp;#34;],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                 IssuerSigningKey = new SymmetricSecurityKey(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                     Encoding.UTF8.GetBytes(Configuration[&amp;#34;Jwt:Key&amp;#34;])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                 )
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;             };
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         })
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;background-color:#dfd&#34;&gt;+        .AddScheme&amp;lt;AuthenticationSchemeOptions, ApiKeyAuthenticationHandler&amp;gt;(
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;background-color:#dfd&#34;&gt;+            &amp;#34;ApiKey&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;background-color:#dfd&#34;&gt;+            options =&amp;gt; { }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;background-color:#dfd&#34;&gt;+        );
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;background-color:#dfd&#34;&gt;&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;A simple configuration as far as auth schemes go. We specify both the types of the authentication handler and the options object that it accepts via the generic type parameters to the &lt;code&gt;AddScheme&lt;/code&gt; method. &lt;code&gt;&amp;quot;ApiKey&amp;quot;&lt;/code&gt; is just the name we&amp;rsquo;ve given our custom auth scheme. It can be anything as long as it&amp;rsquo;s not &amp;ldquo;Bearer&amp;rdquo;, which is the name of the Jwt Bearer scheme (which is the value returned by &lt;code&gt;JwtBearerDefaults.AuthenticationScheme&lt;/code&gt;). We&amp;rsquo;ll refer back to it later. Finally, since we have no special options to give it, we specify a lambda that does nothing with its options.&lt;/p&gt;
&lt;h5 id=&#34;updating-the-authorize-attribute-to-use-our-two-schemes&#34;&gt;Updating the Authorize attribute to use our two schemes&lt;/h5&gt;
&lt;p&gt;Now that the auth scheme is configured, we need to use it to secure an endpoint. We can use the same that we used for JWT: &lt;code&gt;POST api/BodyTypes&lt;/code&gt;, defined in &lt;code&gt;BodyTypesController&lt;/code&gt;&amp;rsquo;s &lt;code&gt;GetBodyTypes&lt;/code&gt; action method. Remember though, that we wanted to have both auth schemes (JWT and API Key) work on the endpoint. For that, the &lt;code&gt;Authorize&lt;/code&gt; attribute allows a comma separated string of scheme names as a parameter. So, we can get both our configured schemes working if we update the attribute like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-csharp&#34; data-lang=&#34;csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#369&#34;&gt;[Authorize(AuthenticationSchemes = $&amp;#34;{JwtBearerDefaults.AuthenticationScheme},ApiKey&amp;#34;)]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;async&lt;/span&gt; Task&amp;lt;ActionResult&amp;lt;IEnumerable&amp;lt;BodyType&amp;gt;&amp;gt;&amp;gt; GetBodyTypes()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;await&lt;/span&gt; _context.BodyTypes.ToListAsync();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;JwtBearerDefaults.AuthenticationScheme&lt;/code&gt; contains the name of the JWT Bearer auth scheme. Next to it, we just put &amp;ldquo;ApiKey&amp;rdquo;, which is the name we have given our new custom one.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;It&amp;rsquo;d be nice to put that &amp;ldquo;ApiKey&amp;rdquo; string somewhere safe similar to how the &amp;ldquo;Jwt Bearer&amp;rdquo; scheme has it in a constant. Take a look at the &lt;a href=&#34;https://github.com/megakevin/end-point-blog-dotnet-5-web-api/tree/json-web-token&#34;&gt;finished project on GitHub&lt;/a&gt; to see &lt;a href=&#34;https://github.com/megakevin/end-point-blog-dotnet-5-web-api/commit/8e9432068bfad977980c7c28702773a25ee293b8&#34;&gt;one way to organize that&lt;/a&gt; and also how to &lt;a href=&#34;https://github.com/megakevin/end-point-blog-dotnet-5-web-api/commit/05138e927986fc191d4a042a3455ed1ee1947b8f&#34;&gt;make the &lt;code&gt;Startup&lt;/code&gt; configuration a little less verbose&lt;/a&gt; by using extension methods.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;And finally, let&amp;rsquo;s test our endpoint and marvel at the fruit of our work.&lt;/p&gt;
&lt;p&gt;Make sure to create a new API Key by POSTing to &lt;code&gt;api/Users/ApiKey&lt;/code&gt;, and copy the &amp;ldquo;value&amp;rdquo; from the response. We can use it as the value for the &lt;code&gt;Api-Key&lt;/code&gt; header a GET request to &lt;code&gt;api/BodyTypes&lt;/code&gt;. In Postman, we can do that by choosing the &amp;ldquo;Authorization&amp;rdquo; tab, selecting &amp;ldquo;API Key&amp;rdquo; in the &amp;ldquo;Type&amp;rdquo; drop-down list, writing &amp;ldquo;Api-Key&amp;rdquo; in the &amp;ldquo;Key&amp;rdquo; text box, and putting our key in the &amp;ldquo;Value&amp;rdquo; text box.&lt;/p&gt;
&lt;p&gt;With that, we can make the request and see how the endpoint now allows authentication via API Keys:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2022/06/implementing-authentication-in-asp.net-core-web-apis/authorized-response-api-key.webp&#34; alt=&#34;Successful response for request authenticated with API Key&#34;&gt;&lt;/p&gt;
&lt;p&gt;Of course, requests authenticated via JWT will also work for this endpoint.&lt;/p&gt;
&lt;h3 id=&#34;thats-all&#34;&gt;That&amp;rsquo;s all&lt;/h3&gt;
&lt;p&gt;And there you have it! We&amp;rsquo;ve updated an existing ASP.NET Core Web API application so that it supports authentication using two strategies: JWT and API Keys. We leveraged the Identity libraries to securely store and manage user accounts. We used ASP.NET Core&amp;rsquo;s built-in authentication capabilities to enable JWT generation and usage. For API Keys, the framework didn&amp;rsquo;t provide an implementation out of the box. However, it proved to be extensible enough so that we could implement our own.&lt;/p&gt;
&lt;h3 id=&#34;table-of-contents&#34;&gt;Table of contents&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#two-approaches-to-authentication-jwt-and-api-keys&#34;&gt;Two approaches to authentication: JWT and API Keys&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#managing-user-accounts-with-aspnet-core-identity&#34;&gt;Managing user accounts with ASP.NET Core Identity&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#install-the-necessary-nuget-packages&#34;&gt;Install the necessary NuGet packages&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#update-the-dbcontext-to-include-the-identity-tables&#34;&gt;Update the DbContext to include the Identity tables&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#applying-database-changes&#34;&gt;Applying database changes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#configuring-the-identity-services&#34;&gt;Configuring the Identity services&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#creating-users&#34;&gt;Creating users&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#fetching-users&#34;&gt;Fetching users&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#implementing-jwt-bearer-token-authentication&#34;&gt;Implementing JWT Bearer Token authentication&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#creating-tokens&#34;&gt;Creating tokens&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#the-request-data-structure&#34;&gt;The request data structure&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#the-response-data-structure&#34;&gt;The response data structure&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#the-class-that-creates-jwts&#34;&gt;The class that creates JWTs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#the-action-method-that-puts-it-all-together&#34;&gt;The action method that puts it all together&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#securing-an-endpoint-with-jwt-authentication&#34;&gt;Securing an endpoint with JWT authentication&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#applying-the-authorize-attribute&#34;&gt;Applying the Authorize attribute&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#enabling-and-configuring-the-jwt-authentication&#34;&gt;Enabling and configuring the JWT authentication&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#implementing-api-key-authentication&#34;&gt;Implementing API Key authentication&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#creating-api-keys&#34;&gt;Creating API Keys&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#the-api-key-model-and-database-table&#34;&gt;The API Key model and database table&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#the-class-that-creates-api-keys&#34;&gt;The class that creates API Keys&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#the-action-method-that-puts-it-all-together-1&#34;&gt;The action method that puts it all together&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#securing-an-endpoint-with-api-key-authentication&#34;&gt;Securing an endpoint with API Key authentication&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#implementing-the-api-key-authentication-handler&#34;&gt;Implementing the API Key authentication handler&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#enabling-and-configuring-the-api-key-authentication&#34;&gt;Enabling and configuring the API Key authentication&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#updating-the-authorize-attribute-to-use-our-two-schemes&#34;&gt;Updating the Authorize attribute to use our two schemes&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#thats-all&#34;&gt;That&amp;rsquo;s all&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

      </content>
    </entry>
  
</feed>
