OTP (One Time Password) validation shell script to integrate PrivacyIDEA ( with FreeRadius ( in environments where Perl is not available to use the standard check script (e.g. on OS X)




Scripts implementing the PrivacyIDEA OTP (One Time Password) check, one implemented as a shell script and the other in python, to integrate with FreeRadius in environments where the FreeRadius Perl plugin is not available to use the standard check script (e.g. on OS X).

Version 2.0, latest version, documentation and bugtracker available on my GitLab instance

Copyright (c) 2015 - 2016 Frederik Lindenaar. free for distribution under the GNU License, see below


When integrating PrivacyIDEA with the stock OS X Server FreeRadius server, I got stuck as the OS X Server not including the FreeRadius rlm_perl module. At that time I created the shell-script privacyidea-checkotp to get around this using the available FreeRadius rlm_exec module. This solution suited my needs and may have glitches, though so far it turned out to be a stable solution.

Recently I have reimplemented this script in Python as starting point for my privacyidea-freeradiusmodule, a FreeRadius rlm_python module (which is available on OS X Server). The Python script is intended as a drop-in replacement for the shell script with better error handling and logging / debugging capabilities. The way to integrate it is the same as the shell script version, the only change needed is the script name.

In case you have any comments / questions or issues, please raise them through my GitLab instance so that others can benefit.


Both scripts will be executed using the FreeRadius rtl_exec module, which is not the most efficient way to integrate but will suffice for low to medium volume use. The script depends on curl and sed being installed, which is the case in most environments.

The setup of this solution consists of the following steps:

  1. Setup PrivacyIDEA and make sure it is working on its own
  2. Install the shell or python version of the script as privacyidea-checkotp on your FreeRadius server and make it executable
  3. Copy the provided privacyidea.freeradiusmodule into the FreeRadius raddb/modules directory as privacyidea
  4. Update raddb/modules/privacyidea so that [WRAPPERSCRIPT_PATH] points to the script as installed in step #1 and [PRIVACYIDEA_URL] is replaced with the base URL of your PrivacyIDEA instance.
  5. Check your configuration by running the command configured in raddb/modules/privacyidea followed by a username and valid password/OTP/PIN combination (depending on your configuration. To avoid the password being captured in your shell history, use `cat` instead of the password on the commandline and after entering the command, enter the password/OTP/PIN combination as PrivacyIDEA expects followed by an enter and CTRL-D, eg.: ./privacyidea-checkotp https://server.tld/path username `cat -`
  6. After successfully testing the base setup, add PrivacyIDEA as authorization and authentication provider with the following steps:

    1. Open the virtual host file you want to add PrivacyIDEA authentication to (typically in raddb/sites-available)
    2. In the section authorize {:

      • disable all authorization modules you do not want to succeed
      • add the following to the bottom of this section:
        # Use PrivacyIDEA
        if(! Service-Type == "Outbound-User") {
              update control {
                      Auth-Type := PrivacyIDEA
        else {
              # Service-Type == "Outbound-User"
              if(NAS-Port-Type == "Virtual" && NAS-Port > 0 ) {
                      update control {
                              Auth-Type := Accept
    3. In the section authenticate {:

      • Disable all authentication modules you do not want to succeed
      • add the following to the top of this section so that PrivacyIDEA authentication is tried first:
        Auth-Type PrivacyIDEA {
  7. Last step is to test the configuration, run FreeRadius as radiusd -X and check what happens with an authentication requests reaching the FreeRadius server. Specific requirements on what needs to happen is dependent on your setup (e.g. I am normally not using any PIN codes for the OTP, but require the user's password followed by the OTP).

Please note that this setups works for plain-text (i.e. non-EAP) authentication with FreeRadius, which is what my setup needs. The configuration above does not work with EAP authentication, I am still working on that (any hints for that are welcome!)


This script, documentation and configuration examples are free software: you can redistribute and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

This script, documentation and configuration examples are distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, download it from