<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Ashkan</title>
    <description>The latest articles on DEV Community by Ashkan (@a5hk).</description>
    <link>https://dev.to/a5hk</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F783689%2Fdbe2b55d-0598-4a53-b723-3efd9994471c.png</url>
      <title>DEV Community: Ashkan</title>
      <link>https://dev.to/a5hk</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/a5hk"/>
    <language>en</language>
    <item>
      <title>Step-by-Step Guide to Setting Up 2FA with FreeIPA and LDAP for SSH and LDAP Enabled Applications</title>
      <dc:creator>Ashkan</dc:creator>
      <pubDate>Fri, 24 Nov 2023 22:01:31 +0000</pubDate>
      <link>https://dev.to/a5hk/step-by-step-guide-to-setting-up-2fa-with-freeipa-and-ldap-for-ssh-and-ldap-enabled-applications-40p2</link>
      <guid>https://dev.to/a5hk/step-by-step-guide-to-setting-up-2fa-with-freeipa-and-ldap-for-ssh-and-ldap-enabled-applications-40p2</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;In this tutorial, we'll setup FreeIPA server on Oracle Linux 9. FreeIPA is an open-source identity and authentication management system for Linux networked environments. Then we will install FreeIPA client on Ubuntu 22.04 and set up 2FA for SSH. We also create a bind user to be able to integrate LDAP enabled applications with the LDAP server.&lt;/p&gt;

&lt;h2&gt;
  
  
  Installing FreeIPA server
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Preparing the Server
&lt;/h3&gt;

&lt;p&gt;Set the hostname (FQDN):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;hostnamectl set-hostname ipa.example.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Get the IP address the server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ip &lt;span class="nt"&gt;-br&lt;/span&gt; a
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Example output:&lt;/p&gt;


&lt;pre class="highlight plaintext"&gt;&lt;code&gt;lo               UNKNOWN        127.0.0.1/8
ens160           UP             192.168.136.134/24
&lt;/code&gt;&lt;/pre&gt;

&lt;/blockquote&gt;

&lt;p&gt;Edit the hosts file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;vim /etc/hosts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Example:&lt;/p&gt;


&lt;pre class="highlight plaintext"&gt;&lt;code&gt;192.168.136.134 ipa.example.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/blockquote&gt;

&lt;p&gt;Open the required ports:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;firewall-cmd &lt;span class="nt"&gt;--permanent&lt;/span&gt; &lt;span class="nt"&gt;--add-service&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;freeipa-4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;firewall-cmd &lt;span class="nt"&gt;--reload&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Install and Configure the FreeIPA Server
&lt;/h3&gt;

&lt;p&gt;Install the required packages:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;dnf &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; ipa-server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Start the installation and configuration by running the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;ipa-server-install
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Example output:&lt;/p&gt;


&lt;pre class="highlight plaintext"&gt;&lt;code&gt;This program will set up the IPA Server.
Version 4.10.2
This includes:
  * Configure a stand-alone CA (dogtag) for certificate management
  * Configure the NTP client (chronyd)
  * Create and configure an instance of Directory Server
  * Create and configure a Kerberos Key Distribution Center (KDC)
  * Configure Apache (httpd)
  * Configure SID generation
  * Configure the KDC to enable PKINIT
To accept the default shown in brackets, press the Enter key.
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/blockquote&gt;

&lt;p&gt;Select the default response of &lt;code&gt;no&lt;/code&gt; when asked to configure the integrated DNS.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Do you want to configure integrated DNS (BIND)? [no]:
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Accept the default FQDN.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Enter the fully qualified domain name of the computer
on which you're setting up server software. Using the form
&amp;lt;hostname&amp;gt;.&amp;lt;domainname&amp;gt;
Example: master.example.com


Server host name [ipa.example.com]:
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Accept the default domain name.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;The domain name has been determined based on the host name.

Please confirm the domain name [example.com]:
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Accept the default realm name.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;The kerberos protocol requires a Realm name to be defined.
This is typically the domain name converted to uppercase.

Please provide a realm name [EXAMPLE.COM]:
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Choose a secure password for the &lt;code&gt;Directory Manager&lt;/code&gt; user and confirm it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Certain directory server operations require an administrative user.
This user is referred to as the Directory Manager and has full access
to the Directory for system management tasks and will be added to the
instance of directory server created for IPA.
The password must be at least 8 characters long.

Directory Manager password:
Password (confirm):
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Choose a secure password for the &lt;code&gt;admin&lt;/code&gt; user and confirm it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;The IPA server requires an administrative user, named 'admin'.
This user is a regular system account used for IPA server administration.

IPA admin password:
Password (confirm):
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Accept the default NETBIOS domain name.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Trust is configured but no NetBIOS domain name found, setting it now.
Enter the NetBIOS name for the IPA domain.
Only up to 15 uppercase ASCII letters, digits and dashes are allowed.
Example: EXAMPLE.


NetBIOS domain name [EXAMPLE]:
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Accept the default response of &lt;code&gt;no&lt;/code&gt; for configuring chrony.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Do you want to configure chrony with NTP server or pool address? [no]:
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally the script displays a summary of the configuration. To proceed with the installation enter &lt;code&gt;yes&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;The IPA Master Server will be configured with:
Hostname:       ipa.example.com
IP address(es): 192.168.136.134
Domain name:    example.com
Realm name:     EXAMPLE.COM

The CA will be configured with:
Subject DN:   CN=Certificate Authority,O=EXAMPLE.COM
Subject base: O=EXAMPLE.COM
Chaining:     self-signed

Continue to configure the system with these values? [no]:
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The script needs several minutes to configure the server. Upon completion, it displays some information including a file containing a list of records to add to the DNS system.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Please add records in this file to your DNS system: /tmp/ipa.system.records.7hnslqjy.db
==============================================================================
Setup complete

Next steps:
        1. You must make sure these network ports are open:
                TCP Ports:
                  * 80, 443: HTTP/HTTPS
                  * 389, 636: LDAP/LDAPS
                  * 88, 464: kerberos
                UDP Ports:
                  * 88, 464: kerberos
                  * 123: ntp

        2. You can now obtain a kerberos ticket using the command: 'kinit admin'
           This ticket will allow you to use the IPA tools (e.g., ipa user-add)
           and the web user interface.

Be sure to back up the CA certificates stored in /root/cacert.p12
These files are required to create replicas. The password for these
files is the Directory Manager password
The ipa-server-install command was successful
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here are the contents of the &lt;code&gt;/tmp/ipa.system.records.7hnslqjy.db&lt;/code&gt; file generated at the end of this installation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;_kerberos-master._tcp.example.com. 3600 IN SRV 0 100 88 ipa.example.com.
_kerberos-master._udp.example.com. 3600 IN SRV 0 100 88 ipa.example.com.
_kerberos._tcp.example.com. 3600 IN SRV 0 100 88 ipa.example.com.
_kerberos._udp.example.com. 3600 IN SRV 0 100 88 ipa.example.com.
_kerberos.example.com. 3600 IN TXT "EXAMPLE.COM"
_kerberos.example.com. 3600 IN URI 0 100 "krb5srv:m:tcp:ipa.example.com."
_kerberos.example.com. 3600 IN URI 0 100 "krb5srv:m:udp:ipa.example.com."
_kpasswd._tcp.example.com. 3600 IN SRV 0 100 464 ipa.example.com.
_kpasswd._udp.example.com. 3600 IN SRV 0 100 464 ipa.example.com.
_kpasswd.example.com. 3600 IN URI 0 100 "krb5srv:m:tcp:ipa.example.com."
_kpasswd.example.com. 3600 IN URI 0 100 "krb5srv:m:udp:ipa.example.com."
_ldap._tcp.example.com. 3600 IN SRV 0 100 389 ipa.example.com.
ipa-ca.example.com. 3600 IN A 192.168.136.134
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Test the Server
&lt;/h3&gt;

&lt;p&gt;Authenticate as the &lt;code&gt;admin&lt;/code&gt; user. The &lt;code&gt;kinit&lt;/code&gt; command obtains and caches a Kerberos ticket-granting ticket.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kinit admin
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can list the ticket's information with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;klist
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Example output:&lt;/p&gt;


&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Ticket cache: KCM:1000
Default principal: admin@EXAMPLE.COM
Valid starting       Expires              Service principal
11/17/2023 13:37:44  11/18/2023 12:41:14  krbtgt/EXAMPLE.COM@EXAMPLE.COM
&lt;/code&gt;&lt;/pre&gt;

&lt;/blockquote&gt;

&lt;p&gt;Get a list of the users with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ipa user-find
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Example output:&lt;/p&gt;


&lt;pre class="highlight plaintext"&gt;&lt;code&gt;--------------
1 user matched
--------------
  User login: admin
  Last name: Administrator
  Home directory: /home/admin
  Login shell: /bin/bash
  Principal alias: admin@EXAMPLE.COM, root@EXAMPLE.COM
  UID: 487800000
  GID: 487800000
  Account disabled: False
----------------------------
Number of entries returned 1
&lt;/code&gt;&lt;/pre&gt;

&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Disable anonymous binds
&lt;/h3&gt;

&lt;p&gt;Create a file containing the required configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; ~/disable.ldif &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;
dn: cn=config
changetype: modify
replace: nsslapd-allow-anonymous-access
nsslapd-allow-anonymous-access: rootdse
&lt;/span&gt;&lt;span class="no"&gt;EOF
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Apply the changes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ldapmodify &lt;span class="nt"&gt;-x&lt;/span&gt; &lt;span class="nt"&gt;-D&lt;/span&gt; &lt;span class="s2"&gt;"cn=Directory Manager"&lt;/span&gt; &lt;span class="nt"&gt;-W&lt;/span&gt; &lt;span class="nt"&gt;-h&lt;/span&gt; ipa.example.com &lt;span class="nt"&gt;-p&lt;/span&gt; 389 &lt;span class="nt"&gt;-f&lt;/span&gt; ~/disable.ldif
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Restart the 389 Directory Server instance.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl restart dirsrv.target
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Verify the modification.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ldapsearch -x -D "cn=Directory Manager" -b cn=config -W -h ipa.example.com  -p 389 nsslapd-allow-anonymous-access | grep nsslapd-allow-anonymous-access
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Expected output:&lt;/p&gt;


&lt;pre class="highlight shell"&gt;&lt;code&gt;Enter LDAP Password:
&lt;span class="c"&gt;# requesting: nsslapd-allow-anonymous-access&lt;/span&gt;
nsslapd-allow-anonymous-access: rootdse
&lt;/code&gt;&lt;/pre&gt;

&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Creating a Bind User
&lt;/h3&gt;

&lt;p&gt;We need to create a read-only on our LDAP server. Other applications use this user to query the LDAP server. We can use Apache Directory Studio to create the user. First we need to connect to the server using the &lt;code&gt;admin&lt;/code&gt; account.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--XMkE2x-i--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9omxrng77xkzs5037hgw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--XMkE2x-i--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9omxrng77xkzs5037hgw.png" alt="LDAP connection" width="511" height="554"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now we need to create a new entry:&lt;/p&gt;

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

&lt;p&gt;Configure a &lt;code&gt;uid&lt;/code&gt;:&lt;/p&gt;

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

&lt;p&gt;Add a &lt;code&gt;userPassword&lt;/code&gt; attribute.&lt;/p&gt;

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

&lt;p&gt;And set a plain text password (pre-hashed passwords are not valid).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--XmO5l3bd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y85366vmop5km05y0rb1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--XmO5l3bd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y85366vmop5km05y0rb1.png" alt="Plain text password" width="677" height="458"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click finish. You can use the &lt;code&gt;readonly_user&lt;/code&gt; to integrate LDAP enabled application with the LDAP server.&lt;/p&gt;

&lt;h2&gt;
  
  
  Installing FreeIPA client
&lt;/h2&gt;

&lt;p&gt;Set the hostname (FQDN):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;hostnamectl set-hostname client.example.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Modify the &lt;code&gt;hosts&lt;/code&gt; file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;vim /etc/hosts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Example:&lt;/p&gt;


&lt;pre class="highlight plaintext"&gt;&lt;code&gt;192.168.136.134 ipa.example.com ipa
192.168.136.135 client.example.com client
&lt;/code&gt;&lt;/pre&gt;

&lt;/blockquote&gt;

&lt;p&gt;Install the required packages.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;freeipa-client
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;During installation you'll be prompted with several times. When asked to enter default Kerberos realm, accept the default &lt;code&gt;EXAMPLE.COM&lt;/code&gt;.&lt;/p&gt;

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

&lt;p&gt;When asked to enter Kerberos servers for your realm, hit &lt;code&gt;Ok&lt;/code&gt; to skip.&lt;/p&gt;

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

&lt;p&gt;When asked to enter administrative server for your Kerberos realm, hit &lt;code&gt;Ok&lt;/code&gt; to skip.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9RbYTAzV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/elc64mfyucie7elbg6hg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9RbYTAzV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/elc64mfyucie7elbg6hg.png" alt="Kerberos administrative server prompt" width="800" height="156"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Hit &lt;code&gt;Ok&lt;/code&gt; again to finish the installation.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--fO5zmbVA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hbiimlbchc94tgvzv1l2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fO5zmbVA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hbiimlbchc94tgvzv1l2.png" alt="Service restart prompt" width="425" height="261"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Configure the IPA client.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;ipa-client-install &lt;span class="nt"&gt;--hostname&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;hostname&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt; &lt;span class="nt"&gt;--mkhomedir&lt;/span&gt; &lt;span class="nt"&gt;--server&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;ipa.example.com &lt;span class="nt"&gt;--domain&lt;/span&gt; example.com &lt;span class="nt"&gt;--realm&lt;/span&gt; EXAMPLE.COM
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The script is interactive and uses several prompts. When asked about no DNS discovery, choose &lt;code&gt;yes&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Autodiscovery of servers for failover cannot work with this configuration.
If you proceed with the installation, services will be configured to always access the discovered server for all operations and will not fail over to other servers in case of failure.
Proceed with fixed values and no DNS discovery? [no]: yes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Enter &lt;code&gt;yes&lt;/code&gt; if you want to configure chrony with NTP server.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Do you want to configure chrony with NTP server or pool address? [no]: yes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Enter a NTP server address, if you have entered &lt;code&gt;yes&lt;/code&gt; in the previous step.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Enter NTP source server addresses separated by comma, or press Enter to skip: time.cloudflare.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Press enter whenever you have provided all the servers you want to proceed to the next step.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Enter a NTP source pool address, or press Enter to skip:
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At this point the script displays a summary of the configuration. Enter &lt;code&gt;yes&lt;/code&gt; if you want to continue with the displayed configuration.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Client hostname: client.example.com
Realm: EXAMPLE.COM
DNS Domain: example.com
IPA Server: ipa.example.com
BaseDN: dc=example,dc=com
NTP server: time.cloudflare.com

Continue to configure the system with these values? [no]: yes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The script continues to configure the client.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Synchronizing time
Configuration of chrony was changed by installer.
Attempting to sync time with chronyc.
Time synchronization was successful.
User authorized to enroll computers: admin
Password for admin@EXAMPLE.COM:
Successfully retrieved CA cert
    Subject:     CN=Certificate Authority,O=EXAMPLE.COM
    Issuer:      CN=Certificate Authority,O=EXAMPLE.COM
    Valid From:  2023-11-17 13:23:41
    Valid Until: 2043-11-17 13:23:41

Enrolled in IPA realm EXAMPLE.COM
Created /etc/ipa/default.conf
Configured /etc/sssd/sssd.conf
Configured /etc/krb5.conf for IPA realm EXAMPLE.COM
Systemwide CA database updated.
Adding SSH public key from /etc/ssh/ssh_host_rsa_key.pub
Adding SSH public key from /etc/ssh/ssh_host_ed25519_key.pub
Adding SSH public key from /etc/ssh/ssh_host_dsa_key.pub
Adding SSH public key from /etc/ssh/ssh_host_ecdsa_key.pub
Could not update DNS SSHFP records.
SSSD enabled
Configured /etc/openldap/ldap.conf
Configured /etc/ssh/ssh_config
Configured /etc/ssh/sshd_config.d/04-ipa.conf
Configuring example.com as NIS domain.
Client configuration complete.
The ipa-client-install command was successful
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On Ubuntu user's home directory won't be created automatically. To fix that, open &lt;code&gt;/usr/share/pam-configs/mkhomedir&lt;/code&gt; file for editing.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;vim /usr/share/pam-configs/mkhomedir

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And replace its contents by the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Name: Create home directory on login - FreeIPA
Default: yes
Priority: 900
Session-Type: Additional
Session:
    required pam_mkhomedir.so umask=0027 skel=/etc/skel
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now run the following command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;pam-auth-update
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When prompted to select PAM profiles, make sure &lt;code&gt;Create home directory on login - FreeIPA&lt;/code&gt; is selected and then hit &lt;code&gt;Ok&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--p5ZXYqCI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1cvsavxapseab62ehhm9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--p5ZXYqCI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1cvsavxapseab62ehhm9.png" alt="Pam profiles to be enabled prompt" width="800" height="305"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now on the FreeIPA server, add the client to the &lt;code&gt;hosts&lt;/code&gt; file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;bash &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s1"&gt;'echo 192.168.136.135 client.example.com client &amp;gt;&amp;gt; /etc/hosts'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Adding a User
&lt;/h2&gt;

&lt;p&gt;We will use the web UI to add a new user. The UI is accessible through &lt;code&gt;https://ipa.example.com/ipa/ui/&lt;/code&gt; address. Log in as &lt;code&gt;admin&lt;/code&gt; user.&lt;/p&gt;

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

&lt;p&gt;Click on &lt;code&gt;Add&lt;/code&gt; button.&lt;/p&gt;

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

&lt;p&gt;Fill in the required fields and press &lt;code&gt;Add&lt;/code&gt; button.&lt;/p&gt;

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

&lt;p&gt;After adding the user, you'll see a list of active users. Click on the new user's login name.&lt;/p&gt;

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

&lt;p&gt;To enable 2FA, select &lt;code&gt;Two factor authentication (password + OTP)&lt;/code&gt; and then click the &lt;code&gt;Save&lt;/code&gt; button.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Setting up 2FA
&lt;/h2&gt;

&lt;p&gt;Now the newly added user is able to use the web UI and create a TOTP token for herself. &lt;/p&gt;

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

&lt;p&gt;At first login the user must change the password provided by the administrator.&lt;/p&gt;

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

&lt;p&gt;To generate the OTP token, the user must navigate to &lt;code&gt;OTP Tokens&lt;/code&gt; tab. &lt;/p&gt;

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

&lt;p&gt;Here the user needs to click on the &lt;code&gt;Add&lt;/code&gt; button.&lt;/p&gt;

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

&lt;p&gt;The user must select the type of the token.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--CwpO4q8i--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t1dhm51anzi7ayur44b5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--CwpO4q8i--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t1dhm51anzi7ayur44b5.png" alt="Add OTP Token" width="594" height="264"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A QR code will be displayed. The user should scan the code using an application like Google Authenticator.&lt;/p&gt;

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

&lt;p&gt;At the end the list of all the tokens will be displyed.&lt;/p&gt;

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

&lt;p&gt;Now, &lt;code&gt;Jane Doe&lt;/code&gt; can log in to &lt;code&gt;client.example.com&lt;/code&gt; via SSH. When prompted to enter the password, she should enter the password she selected earlier, followed by the one-time password displayed by the authenticator app.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--BC-0QPkq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uoo7526e8gd2xp65ku2c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BC-0QPkq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uoo7526e8gd2xp65ku2c.png" alt="SSH login" width="596" height="133"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  References and Further Reading
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.oracle.com/en/learn/ol-freeipa/index.html"&gt;https://docs.oracle.com/en/learn/ol-freeipa/index.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/9/html-single/installing_identity_management/index"&gt;https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/9/html-single/installing_identity_management/index&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/9/html-single/managing_idm_users_groups_hosts_and_access_control_rules/index"&gt;https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/9/html-single/managing_idm_users_groups_hosts_and_access_control_rules/index&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/9/html-single/accessing_identity_management_services/index"&gt;https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/9/html-single/accessing_identity_management_services/index&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://luna.oracle.com/lab/a03cfc90-4c3c-488d-9e66-ba514e00b619/steps"&gt;https://luna.oracle.com/lab/a03cfc90-4c3c-488d-9e66-ba514e00b619/steps&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.linuxtechi.com/configure-freeipa-client-on-ubuntu/"&gt;https://www.linuxtechi.com/configure-freeipa-client-on-ubuntu/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://computingforgeeks.com/how-to-configure-freeipa-client-on-ubuntu-centos/"&gt;https://computingforgeeks.com/how-to-configure-freeipa-client-on-ubuntu-centos/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.howtoforge.com/how-to-install-freeipa-client-on-ubuntu-server-1804/"&gt;https://www.howtoforge.com/how-to-install-freeipa-client-on-ubuntu-server-1804/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.tenable.com/audits/items/CIS_Debian_Linux_8_Server_v2.0.2_L1.audit:632ea5de5002b78e71581003f107448a"&gt;https://www.tenable.com/audits/items/CIS_Debian_Linux_8_Server_v2.0.2_L1.audit:632ea5de5002b78e71581003f107448a&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>freeipa</category>
      <category>2fa</category>
      <category>ldap</category>
      <category>ssh</category>
    </item>
    <item>
      <title>Time-based one-time passwords (TOTP) with OpenLDAP</title>
      <dc:creator>Ashkan</dc:creator>
      <pubDate>Thu, 05 Oct 2023 22:33:14 +0000</pubDate>
      <link>https://dev.to/a5hk/time-based-one-time-passwords-totp-with-openldap-5al0</link>
      <guid>https://dev.to/a5hk/time-based-one-time-passwords-totp-with-openldap-5al0</guid>
      <description>&lt;p&gt;Two-factor authentication (2FA) is a method of enhancing the security of online accounts by requiring two types of credentials: something you know, such as a password, and something you have, such as a device. One common way of implementing the second factor is using time-based one-time passwords (TOTP), which are unique numeric codes that are generated based on the current time and a shared secret key. TOTP codes are usually displayed by an authentication app on your smartphone or tablet, and they expire after a short period of time. TOTP is an open standard that is defined in RFC &lt;a href="https://datatracker.ietf.org/doc/html/rfc6238"&gt;6238&lt;/a&gt; and supported by many applications and services.&lt;/p&gt;

&lt;p&gt;In this article, we will install and configure &lt;a href="https://www.openldap.org"&gt;OpenLDAP&lt;/a&gt; on Ubuntu 22.04 and implement TOTP. To implement OTP we need OpenLDAP &lt;a href="https://www.openldap.org/software/roadmap.html"&gt;2.5 or higher&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;NOTICE&lt;/strong&gt;: This guide is for educational purposes only and is &lt;strong&gt;NOT&lt;/strong&gt; meant to be used in production environments.&lt;/p&gt;

&lt;h2&gt;
  
  
  Install and configure OpenLDAP
&lt;/h2&gt;

&lt;p&gt;Run the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;slapd ldap-utils
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Enter a new password:&lt;/p&gt;

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

&lt;p&gt;To reconfigure the default configuration, run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;dpkg-reconfigure slapd
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You will be asked to omit OpenLDAP configuration, select &lt;strong&gt;No&lt;/strong&gt;.&lt;/p&gt;

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

&lt;p&gt;Enter your domain name:&lt;/p&gt;

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

&lt;p&gt;Enter your organization name:&lt;/p&gt;

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

&lt;p&gt;Provide the administration password and then confirm it:&lt;/p&gt;

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

&lt;p&gt;For this guide, when you get prompted to remove the database when slapd is purged, select &lt;strong&gt;Yes&lt;/strong&gt;:&lt;/p&gt;

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

&lt;p&gt;And finally select &lt;strong&gt;Yes&lt;/strong&gt;:&lt;/p&gt;

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

&lt;p&gt;Open &lt;code&gt;ldap.conf&lt;/code&gt; with a text editor:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;vim /etc/ldap/ldap.conf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Find and uncomment the following lines:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#BASE   dc=example,dc=com
#URI    ldap://ldap.example.com ldap://ldap-provider.example.com:666
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Edit these entries, replace BASE with your domain name, and URI with the URI to your ldap server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;BASE    dc=mydomain,dc=com
URI     ldap://ldap.mydomain.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Save the changes and exit the editor. You might need to edit the &lt;code&gt;hosts&lt;/code&gt; file and provide the FQDN to your LDAP server and its IP address:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;vim /etc/hosts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;192.168.1.1 ldap.mydomain.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Creating user accounts
&lt;/h2&gt;

&lt;p&gt;Create a file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;vim users-ou.ldif
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Enter the following contents:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dn: ou=people,dc=mydomain,dc=com
objectClass: organizationalUnit
objectClass: top
ou: people

dn: ou=groups,dc=mydomain,dc=com
objectClass: organizationalUnit
objectClass: top
ou: groups
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Save and close the file. Now run the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ldapadd -x -D cn=admin,dc=mydomain,dc=com -W -f users-ou.ldif
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And enter your administration password. You should see an output like this:&lt;/p&gt;

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

&lt;p&gt;You can use the following command to verify:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ldapsearch &lt;span class="nt"&gt;-Q&lt;/span&gt; &lt;span class="nt"&gt;-LLL&lt;/span&gt; &lt;span class="nt"&gt;-Y&lt;/span&gt; EXTERNAL &lt;span class="nt"&gt;-H&lt;/span&gt; ldapi://
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That should print something like this:&lt;/p&gt;

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

&lt;p&gt;Now create a password using the &lt;code&gt;slappasswd&lt;/code&gt; command. Run the command and enter a password, then confirm it. You should get something like this:&lt;/p&gt;

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

&lt;p&gt;Copy the hash. Now create another file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;vim user.ldif
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Enter the following contents:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dn: uid=johndoe,ou=people,dc=mydomain,dc=com
objectClass: inetOrgPerson
objectClass: organizationalPerson
objectClass: person
objectClass: posixAccount
objectClass: shadowAccount
objectClass: top
homeDirectory: /home/john
givenName: John
sn: Doe
cn: John Doe
uid: johndoe
displayName: John Doe
uidNumber: 8000
gidNumber: 8000
userPassword: {SSHA}eLp4NBSK1SV3VOFY3iUxI8P73vmOW/Lh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace &lt;code&gt;{SSHA}eLp4NBSK1SV3VOFY3iUxI8P73vmOW/Lh&lt;/code&gt; with hash you copied earlier. Run the following command to create a user account:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ldapadd &lt;span class="nt"&gt;-x&lt;/span&gt; &lt;span class="nt"&gt;-D&lt;/span&gt; &lt;span class="nv"&gt;cn&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;admin,dc&lt;span class="o"&gt;=&lt;/span&gt;mydomain,dc&lt;span class="o"&gt;=&lt;/span&gt;com &lt;span class="nt"&gt;-W&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; user.ldif
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create another file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;vim group.ldif
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Enter the contents below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dn: cn=appusers,ou=groups,dc=mydomain,dc=com
objectClass: posixGroup
objectClass: top
cn: appusers
gidNumber: 10000
memberUid: uid=johndoe,ou=people,dc=mydomain,dc=com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Apply the changes to create a group:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ldapadd -x -D cn=admin,dc=mydomain,dc=com -W -f group.ldif
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can use &lt;code&gt;ldapsearch -Q -LLL -Y EXTERNAL -H ldapi://&lt;/code&gt; to verify the changes or use graphical tools such as the &lt;a href="https://directory.apache.org/studio/"&gt;Apache Directory Studio&lt;/a&gt; to verify changes and manage your LDAP server.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Configure TOTP
&lt;/h2&gt;

&lt;p&gt;First otp module must be loaded. Create a file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;vim otpload.ldif
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Enter the following contents:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dn: cn=module{0},cn=config
changetype: modify
add: olcModuleLoad
olcModuleLoad: otp.la
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Apply the changes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;ldapmodify &lt;span class="nt"&gt;-Y&lt;/span&gt; EXTERNAL &lt;span class="nt"&gt;-H&lt;/span&gt; ldapi:// &lt;span class="nt"&gt;-D&lt;/span&gt; &lt;span class="nv"&gt;cn&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;config &lt;span class="nt"&gt;-W&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; otpload.ldif
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The output should be like this:&lt;/p&gt;

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

&lt;p&gt;Now the otp overlay must be added to databases. Create another file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;vim overlay.ldif
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Enter the following contents:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dn: olcOverlay=otp,olcDatabase={1}mdb,cn=config
objectClass: olcOverlayConfig
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;ldapadd &lt;span class="nt"&gt;-Y&lt;/span&gt; EXTERNAL &lt;span class="nt"&gt;-H&lt;/span&gt; ldapi:// &lt;span class="nt"&gt;-D&lt;/span&gt; &lt;span class="nv"&gt;cn&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;config &lt;span class="nt"&gt;-W&lt;/span&gt;  &lt;span class="nt"&gt;-f&lt;/span&gt; overlay.ldif
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To set the otp parameters, create a file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;vim totp.ldif
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And enter the following contents:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dn: ou=people,dc=mydomain,dc=com
changetype: modify
add: objectClass
objectClass: oathTOTPParams
-
add: oathOTPLength
oathOTPLength: 6
-
add: oathHMACAlgorithm
oathHMACAlgorithm: 1.2.840.113549.2.7
-
add: oathTOTPTimeStepPeriod
oathTOTPTimeStepPeriod: 30
-
add: oathTOTPTimeStepWindow
oathTOTPTimeStepWindow: 3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run the command below to apply the configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ldapmodify &lt;span class="nt"&gt;-x&lt;/span&gt; &lt;span class="nt"&gt;-D&lt;/span&gt; &lt;span class="nv"&gt;cn&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;admin,dc&lt;span class="o"&gt;=&lt;/span&gt;mydomain,dc&lt;span class="o"&gt;=&lt;/span&gt;com &lt;span class="nt"&gt;-W&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; totp.ldif
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To be able to use TOTP, users need a key. This key is shared between the server and the user. The following command can be used to generate the key:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;openssl rand 80 &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; key
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To use the key, create a file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;vim token.ldif
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Enter the contents like below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dn: uid=johndoe,ou=people,dc=mydomain,dc=com
changetype: modify
add: objectClass
objectClass: oathTOTPToken
-
add: oathTOTPParams
oathTOTPParams: ou=people,dc=mydomain,dc=com
-
add: oathSecret
oathSecret:&amp;lt; file:key
-
add: objectClass
objectClass: oathTOTPUser
-
add: oathTOTPToken
oathTOTPToken: uid=johndoe,ou=people,dc=mydomain,dc=com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The following command applies the changes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ldapmodify &lt;span class="nt"&gt;-x&lt;/span&gt; &lt;span class="nt"&gt;-D&lt;/span&gt; &lt;span class="nv"&gt;cn&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;admin,dc&lt;span class="o"&gt;=&lt;/span&gt;mydomain,dc&lt;span class="o"&gt;=&lt;/span&gt;com &lt;span class="nt"&gt;-W&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; token.ldif
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can use &lt;code&gt;qrencode&lt;/code&gt; to generate the QR code. First install it with the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;qrencode
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use the commands below to generate the QR code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;base32 &lt;/span&gt;key &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; bkey
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="s2"&gt;"otpauth://totp/myorg:johhdoe@mydomain.com?secret=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&amp;lt;bkey&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;&amp;amp;issuer=myorg&amp;amp;period=30&amp;amp;digits=6&amp;amp;algorithm=SHA1"&lt;/span&gt; | qrencode &lt;span class="nt"&gt;-t&lt;/span&gt; ansiutf8
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;Now you can scan the QR code with an authenticator app such as the Google Authenticator.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to authenticate?
&lt;/h2&gt;

&lt;p&gt;Whenever you get asked to provide your password, enter your password followed by the code you get from the authenticator app. For example if your password is &lt;code&gt;abcdef&lt;/code&gt; and the code that you get from the app is &lt;code&gt;123456&lt;/code&gt;, enter &lt;code&gt;abcdef123456&lt;/code&gt; as your password.&lt;/p&gt;

&lt;h2&gt;
  
  
  References and Further Reading
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.ibm.com/docs/en/rpa/23.0?topic=ldap-installing-configuring-openldap"&gt;https://www.ibm.com/docs/en/rpa/23.0?topic=ldap-installing-configuring-openldap&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.howtoforge.com/how-to-install-and-configure-openldap-phpldapadmin-on-ubuntu-2004/"&gt;https://www.howtoforge.com/how-to-install-and-configure-openldap-phpldapadmin-on-ubuntu-2004/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://ubuntu.com/server/docs/service-ldap"&gt;https://ubuntu.com/server/docs/service-ldap&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.symas.com/post/how-to-guide-two-factor-authentication"&gt;https://www.symas.com/post/how-to-guide-two-factor-authentication&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.irontec.com/openldap-y-passwords-temporales-otp/"&gt;https://blog.irontec.com/openldap-y-passwords-temporales-otp/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://manpages.ubuntu.com/manpages/jammy/en/man5/slapo-otp.5.html"&gt;https://manpages.ubuntu.com/manpages/jammy/en/man5/slapo-otp.5.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.yubico.com/yesdk/users-manual/application-oath/uri-string-format.html"&gt;https://docs.yubico.com/yesdk/users-manual/application-oath/uri-string-format.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Cover image from &lt;a href="https://undraw.co/illustrations"&gt;unDraw&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>totp</category>
      <category>ldap</category>
      <category>2fa</category>
      <category>openldap</category>
    </item>
  </channel>
</rss>
