privacyIDEA – Free of charge MFA for your Citrix Gateway

Nowadays there are still a lot of companies who are relying on a single factor authentication when publishing apps and desktops to the internet. Often this is happening because there is not enough budget for the IT department. You should be aware there are open source solutions available which will not cost you a penny and make the corporate authentication more secure. What I mean by that: There is no excuse in not using a 2-factor authentication in the year 2020.

Many enterprises out there are running their Citrix ADC infrastructure with an Advanced/Enterprise license and maybe work with the Native OTP feature which is available since Build 12.0.51.24. But what about the smaller companies which maybe just own a Citrix Gateway license without licensed nFactor framework? If you have worked with NativeOTP before you know it is very limited regarding the management functionality. Another problem (from a security perspective) is that the OTP secret will be stored in clear text in the Active Directory except you are already running ADC 13.0.41 which will let you encrypt the secret.

Two months ago one of my clients had interruptions with their ADC infrastructure. Funny that the incident was related to that mentioned 13.0.41 build 😉 After restoring the services we spoke about how they handle their 2-Factor Authentication. That was the first time I heard about privacyIDEA which is an opensource authentication server with a promising feature set. privacyIDEA is developed by the company “NetKnights GmbH” based in Kassel (Germany). They also offer an enterprise edition with a service level agreement.

While reading through the features I was thinking this sounds almost to good to be true. What I can tell you after using privacyIDEA for several weeks I am really surprised on how well it is working. I tested the following scenarios:

  • TOTP with the Google Authenticator and Microsoft Authenticator App
  • Push OTP with the privacyIDEA App available on iOS and Android
  • HOTP with a hardware token (Feitian C100 – about 10$)
  • TANs/Tokens printed on a sheet of paper

Preview of the Self Service Portal

MFA75

MFA76

MFA77

Let us not beat about the bush it is about time installing and configuring the solution 🙂

Server Installation

(1) Our foundation for the installation will be a virtual machine with Ubuntu 16.04 LTS.  Grab the ISO from here and install the server. 1vCPU, 512MB RAM and a 16GB HDD was more than enough for my lab environment.

MFA1

MFA2

(2) Make sure to install the OpenSSH server

MFA3

(3) Configure a static IP address for the system

sudo nano /etc/network/interfaces

iface ens160 inet static
address 192.168.2.157
netmask 255.255.255.0
gateway 192.168.2.1
dns-nameservers 8.8.8.8 8.8.4.4

(4) Make sure to update the system

sudo apt update && sudo apt upgrade -y

(5) Enable root account

sudo passwd root

(6) Enable SSH access for root account

sudo nano /etc/ssh/sshd_config

PermitRootLogin Yes
#StrictModes yes

 MFA5

(7) Restart SSH Service

service sshd restart

Installation of privacyIDEA

(1) Open a SSH session with the root user.

(2) Install the privacyIDEA components with the following commands.

wget https://lancelot.netknights.it/NetKnights-Release.asc

gpg –with-fingerprint NetKnights-Release.asc

apt-key add NetKnights-Release.asc

add-apt-repository http://lancelot.netknights.it/community/xenial/stable

apt update

apt install privacyidea-apache2

apt-get install privacyidea-radius

MFA6

(3) Create local administrator account for privacyIDEA

pi-manage admin add admin -e admin@localhost

MFA7

Create the LDAP(S) resolver

(1) Browse to https://IpAddressOfServer and login with the created admin account.

MFA8

(2) Go to Config > Users > New ldapresolver

(3) Fill out the following fields:

Resolver name
Server URI (can be ldap:// or ldaps://)
Base DN
Bind DN
Bind Password

MFA9

(4) Click on “Preset Active Directory” and test the LDAP resolver.

MFA10

(5) For each domain controller you will need to create an own ldap resolver.

Create the LDAP(S) Realm

(1) Go to Config > Realms

(2) Create a new realm and link the previous created ldap resolver(s) to it.

MFA11

(3) Set the realm as default.

MFA12

You should now be able to login with a domain user account (sAMAccountName) to the privacyIDEA server. If this is not working you missed a step and should fix this before continuing.

Create the privacyIDEA Policies

(1) Go to Config > Policies > Create new Policy

MFA13

(1) hide_welcome -> This policy will prevent a welcome information when logging into the web console. We are going to use the policy template “hide_welcome”.

MFA14

MFA15

(2) selfservice -> Specifies which tokens can be enrolled and the strength of the PIN code. We are going to use the policy template “selfservice1” with some modifications.

MFA16

Allow the users only to enroll TOTP tokens and enforce a minimum pin length.

MFA17

(3) enroll_tokenlabel -> Gives you the possibility to modify the token label.

tokenlabel: @/Company

tokenissuer: LAB

MFA18

(4) portal_timeout -> Default timeout is 120 seconds. We are going to increase the timeout to 900 seconds.

MFA20

Enroll your first TOTP

(1) Now we can try to enroll our first token. Browse to the web fronted of the privacyIDEA server and login with a domain user account.

MFA21

(2) Select “Enroll Tokens”

MFA22

(3) Specify your PIN code and enroll the token.

MFA23

(4) Scan the QR code with the app of your choice.

MFA24

You should see something similar to this:

MFA19

Congratulations we successfully enrolled our first token. Now lets continue with the Free RADIUS configuration.

Configuration of Free RADIUS

(1) Start a SSH session with the root user and execute the following commands.

cp -a /etc/freeradius /etc/freeradius_original
rm /etc/freeradius/{clients.conf,users}

(2) Now we need to specify which RADIUS client are allowed to communicate with the privacyIDEA server. The IP address 192.168.2.98 is the NSIP of my Citrix ADC. If you are going to create a high availability setup of the privacyIDEA server please specify the SNIP.

nano /etc/freeradius/clients.conf

MFA25

client CitrixADC {
ipaddr = 192.168.2.98
netmask = 32
secret = ‘123456’
}

(3) Change the default authorization type to perl.

nano /etc/freeradius/users

MFA26

DEFAULT Auth-type := perl

(4) Now we need to tell the Free RADIUS server which perl module it should use.

nano /etc/freeradius/modules/perl

MFA27

module = /usr/share/privacyidea/freeradius/privacyidea_radius.pm

(5) Afterwards restart the Free RADIUS service with the command:

service freeradius restart

(6) Create an Authentication RADIUS server on the Citrix ADC to verify if the server is working.

MFA28

SSL Certificate and HTTP Redirect

Most of our users are going to use the self enrollment portal so we want to equip the privacyIDEA server with a trusted SSL certificate to prevent certificate mismatch errors.

(1) You are going to need the certificate in PEM format.  I like to use this script from Trond Haavarstein (@xenappblog) to convert a .pfx certificate in various formats.

Rename the certificate file to: “privacyideaserver.pem”
Rename the key file to: “privacyideaserver.key”

Rename the original cert file/key and replace them with your own certificate.

/etc/ssl/certs/privacyideaserver.pem
/etc/ssl/private/privacyideaserver.key

(2) Execute the following command to enable the rewriting feature of Apache.

a2enmod rewrite

(3) Edit the privacyidea apache configuration file and uncomment the “<VirtualHost _default_: 80” part.

nano /etc/apache2/sites-enabled/privacyidea.conf

MFA29

(4) Restart the Apache service

apache2ctl restart

Now we should get redirected when coming from port 80 and  have a trusted connection when browsing to our privacyIDEA server.

MFA30

Administrator Access

Until now we only have one local account for administrating the privacyIDEA server. We want that the administrators can login with their administrative domain account. To make this happen we need to create a separate LDAP Resolver & LDAP Realm.

(1) Create a security group in Active Directory and assign it to a user > LAB_PER_MFA_Administrator

(2) Go to “Config > Users” and create an admin LDAP resolver with a search filter.

Search Filter: (memberOf:1.2.840.113556.1.4.1941:=CN=LAB_PER_MFA_Administrator,OU=Groups Permissions,OU=CANCOM,DC=flashmob-saulgau,DC=de)(objectClass=person)

MFA31

(4) Click on “Test LDAP resolver”. You should receive the following information: Your LDAP config seems to be OK, 1 user objects found.

(5) Go to “Config > Realms” and create the admin realm. Assign the previous created Admin LDAP resolver.

MFA32

(6) Try to login with the user account which is member of the group “LAB_PER_MFA_Administrator”. It is important that you specify the realm name (@admin). Without specifying the realm it will use the default realm.

MFA33

In case you choose a different realm than “admin” you need to specify it in the privacyIDEA configuration file.

nano /etc/privacyidea/pi.cfg

MFA34

Import Hardware Token

(1) Before we can assign hardware tokens to our users we need to create a csv file which contains the necessary informations to import the tokens into the database. The stucture is the following: SerialNumber, Seed,  Type, OTP Length, TimeStep

MFA35

(2) Go to “Tokens > Import Tokens” and upload the csv file.

MFA36

(3) Select the imported token and resync the OTP.

MFA37

MFA38

(4) After you have resycned the token you can assign it to a user and set a PIN code.

MFA40

(5) Enter your PIN + OTP and select “Test token”. We should get a notification that the authentication was successful.

MFA41

Push OTP

For implementing the Push OTP feature we need to have a Google Firebase account. We are using the “Spark Plan” which is a free offering. No need for entering any credit cards details.  Link: https://console.firebase.google.com

(1) First we need to create a new project at Google Firebase.

MFA42

MFA43

MFA44

MFA45

(2) The next step is to go to the “Project settings” and create a service account. After you have generated the private key you will be prompted to download the .json file.

MFA46

MFA47

MFA48

(3) Copy the json file to your privacyIDEA server. Path: “/etc/privacyidea”. Make sure to change the owner to “privacyidea”.

MFA50

(4) We go back to the Firebase portal and create the App for iOS.

MFA51

(5) The iOS Bundle ID needs to be “privacyidea.authenticator”. Please double check if you not have any typos! Otherwise it is not going to work. (This ID is linked to the Apple Notification Service)

MFA52

(6) Download the “GoogleService-info.plist”

MFA53

(7) Skip the following steps.

MFA54

(8) Now we are going to create the Android app.

MFA55

MFA56

(9) Download the “google-services.json” file.

MFA57

(10) Skip the following steps.

MFA58

(11) Go to “Project Settings > Cloud Messaging” and upload the privacyIDEA APNs Authentication Key. The key file can be downloaded from the following URL: Key-File

Key ID: 2FZRBAT74S
Team ID: 627QALYL3B

MFA59

MFA60

(12) The APNs authentication key should be imported now. If this is not working please check the following post if there was a change from the developers.

MFA61

(13) Before we can create the  Firebase Gateway we need to gather some informations.

JSON config file: Specify the path to your private key of the service account
Example: /etc/privacyidea/citrixguyblog-pushotp-firebase-adminsdk-x12w0-388ee505b4.json

apikey: Get it from the google-services.json > api_key > current_key
Example: AIzaSyDGeveOZgLwH-AXmPNdOd_Ssg2Wf54oBIo

apikeyios: Get it from GoogleService-Info.plist > API_KEY
Example: AIzaSyD_E2Y1cTRPYHZ0Xm0Fq_ZvSoSZBFvK3-U

appid: App-ID of the created Android App
Example: 1:96915215012:android:21a8ad920cde688e9a8c31

appidios: App-ID of the created iOS App
Example:1:96915215012:ios:2befa616e9374c709a8c31

MFA63

projectid: citrixguyblog-pushotp

MFA64

projectnumber: Get it from the google-services.json > project_number
Example: 96915215012

registration URL: To make the OTP challenge possible we need to publish “/ttype/push” and “/validate” from the MFA server to the internet. We are going to solve this with a ADC Content Switch in a later step.
Example: https://apps.flashmob-saulgau.de/ttype/push

time to live: 1

(14) Go to “Config > System > SMS Gateways” and create a new SMS Gateway definition.

MFA62

(15) Fill out the parameters with the information we collected in the previous step and create the gateway,

MFA65

(16) We need two additional policies to enable Push OTP.

pushenroll > Set push_ssl_verify to “0” and select the created “PushOTP” firebase configuration.

MFA66

pushauth > Set push_ssl_verify to “0” and configure “push_wait” to 20 seconds.

MFA67

(17) Publish the MFA server to the Internet

add server MFA-01 192.168.2.158
add serviceGroup svcgrp_mfa_ssl_443 SSL -maxClient 0 -maxReq 0 -cip DISABLED -usip NO -useproxyport YES -cltTimeout 180 -svrTimeout 360 -CKA NO -TCPB NO -CMP NO
add lb vserver lb_vsrv_mfa_ssl_443 SSL 0.0.0.0 0 -persistenceType NONE -cltTimeout 180
bind lb vserver lb_vsrv_mfa_ssl_443 svcgrp_mfa_ssl_443
add cs action cs_act_mfa -targetLBVserver lb_vsrv_mfa_ssl_443
add cs policy cs_pol_mfa -rule “HTTP.REQ.URL.CONTAINS(\”/ttype/push\”) || HTTP.REQ.URL.CONTAINS(\”/validate\”)” -action cs_act_mfa

The configuration will depend on your setup. I binded the Content Switch Policy to my Unified Gateway. If you only have a Citrix Gateway (ICA-Proxy) license you will not be able to use the Content Switch feature of the Citrix ADC. In case you can not use the CS feature I would suggest you to use Nginx instead.

(18) Test if “/ttype/push” is accessible from the Internet. Otherwise the token enrollment process will not work.

MFA68

(19) Download the “privacyIDEA Authenticator” from the AppStore.

MFA71

(20) Finally we can enroll our first push token.

MFA69

(21) Scan the QR code with the privacyIDEA Authenticator.

MFA70

(22) With the following URL we can verify if the Push Token is working.  Pass = PIN https://apps.flashmob-saulgau.de/validate/check?user=jmooren&pass=1234

We should receive a push notification and confirm it (German: Zulassen).

MFA71_1

In the JSON output we can see that the token is matching which means the authentication was successful.

MFA72

(23) The final step is to edit the “selfservice” policy and allow users to enroll Push Tokens on their own.

MFA73

High Availability

It is possible to create a redundant (Active-Active) privacyIDEA infrastructure with MySQL Master-Master Replication.

(1) Prepare a second Ubuntu Server (MFA-02) and install privacyIDEA.

(2) Edit the MySQL configuration file (MFA-01)

nano /etc/mysql/my.cnf

MFA78

[mysqld]
bind-address = 0.0.0.0
server-id=1
log_bin = /var/log/mysql/bin.log
binlog-do-db=pi
replicate-do-db=pi
auto-increment-offset = 1

(3) Restart the MySQL service on MFA-01

service mysql restart

(4) Make a backup of the database (MFA-01)

mysqldump -p –allow-keywords –master-data –databases pi -r /etc/privacyidea/dbbackup.sql

(5) Copy the database (MFA-01)

scp /etc/privacyidea/dbbackup.sql root@192.168.2.159:/etc/privacyidea/

(6) Restore the database (MFA-02)

mysql -u root -p
drop database pi;
source /etc/privacyidea/dbbackup.sql;

(7) Copy the encryption key (MFA-01)

scp /etc/privacyidea/enckey root@192.168.2.159:/etc/privacyidea/

(8) Take over the secrets (PI_PEPPER, SECRET_KEY) from the privacyIDEA configuration file from MFA-01 to MFA-02. Path of the file: /etc/privacyidea/pi.cfg

MFA79

(9) Edit the MySQL configuration file (MFA-02)

nano /etc/mysql/my.cnf

[mysqld]
bind-address = 0.0.0.0
server-id=2
log_bin= /var/log/mysql/bin.log
binlog-do-db=pi
replicate-do-db=pi
auto-increment-offset = 2

(10) Restart the MySQL service on MFA-02

service mysql restart

(11) Create the MySQL replication user (MFA-01)

mysql -u root -p

CREATE USER ‘replicator’@’192.168.2.159’ IDENTIFIED by ‘replicatorpw’;
GRANT REPLICATION SLAVE ON *.* TO ‘replicator’@’192.168.2.159’;

(12) Show the Master Status. Please note the File name and position number (MFA-01)

mysql> SHOW MASTER STATUS\G
*************************** 1. row ***************************
File: bin.000001
Position: 1975
Binlog_Do_DB: pi
Binlog_Ignore_DB:
Executed_Gtid_Set:
1 row in set (0.00 sec)

(13) Create the MySQL replication user (MFA-02)

mysql -u root -p

CREATE USER ‘replicator’@’192.168.2.158’ IDENTIFIED by ‘replicatorpw’;
GRANT REPLICATION SLAVE ON *.* TO ‘replicator’@’192.168.2.158’;

(14) Prepare MySQL Replication with the information from Step 12 (MFA-02)

CHANGE MASTER TO MASTER_HOST=’192.168.2.158′, MASTER_USER=’replicator’, MASTER_PASSWORD=’replicatorpw’, MASTER_LOG_FILE=’bin.000001‘, MASTER_LOG_POS=1975;

(15) Show the Master Status. Please note the file name and the position number (MFA-02)

mysql> SHOW MASTER STATUS\G
*************************** 1. row ***************************
File: bin.000001
Position: 154
Binlog_Do_DB: pi
Binlog_Ignore_DB:
Executed_Gtid_Set:
1 row in set (0.00 sec)

(16) Start MySQL Replication with the information from Step 15 (MFA-01)

CHANGE MASTER TO MASTER_HOST=’192.168.2.159′, MASTER_USER=’replicator’, MASTER_PASSWORD=’replicatorpw’, MASTER_LOG_FILE=’bin.000001‘, MASTER_LOG_POS=154;
start slave;

(17) Start MySQL Replication on MFA-02

start slave;

(18) Verify on both servers if the replication is running without errors. Slave_IO_Running and  Slave_SQL_Running should both have the status “Yes”.

show slave status\G

MFA74

(19) Configure the Free RADIUS the same way as on MFA-01

(20) Replace the SSL Certificate and enable the HTTP Responder

(21) Load Balance the privacyIDEA Management Website

(22) Load Balance the RADIUS server for ADC authentication

Summary

Looking back the last two years I can see a clear shift of companys moving to cloud based Multi Factor Authentication offerings such as Azure MFA, Okta or Duo Security. These solutions work well and are easy to implement if you have the needed wherewithal in your cashbox. I hope this install guide is helping some people out there to make their environment more secure and benefit of privacyIDEA. If you have any suggestions for improvements feel free to leave a comment or contact me via Twitter.

2 comments

    1. I don’t think there is a way to integrate it with a RDS Gateway for the moment. In addition there is no available RDWeb plugin for privacyIDEA. The only solution which is working without any 3rd party components is Azure MFA…
      You could try to use the privacyIDEA Credential Provider. This could work but I didn’t test it.

Leave a Reply

Your email address will not be published. Required fields are marked *