External Second Factor

This basic plugin can be used to add a second factor authentication device (SMS, OTP,…). It uses external commands to send or validate a second factor. Any language is allowed to call your 2nd factor system.


Commands receive arguments on command line and must return a 0 code if succeed, another else. Nothing must be written to STDOUT, STDERR is reported in logs (but may be lost with FastCGI server).


All parameters are configured in “General Parameters » Portal Parameters » Extensions » External 2nd Factor”.

  • Activation

  • Code regex: regular expression to create an OTP code. Let this option blank to delegate code Generation / Verification to an external provider

  • Send command: define your command using $attribute like in rules. Example: /usr/local/bin/sendOtp --uid $uid or /usr/local/bin/sendCode --uid $uid --code $code if code is generated by the Portal

  • Validation command: Required ONLY if you delegate code Generation / Verification to an external provider. You must also use $code which is the value entered by user; Example: /usr/local/bin/verify --uid $uid --code $code

  • Re-send interval: Set this to a non-empty value to allow the user to re-send the code in case a transmission error occured. The value sets how many seconds the user has to wait before each attempt

  • Authentication level (Optional): if you want to overwrite the value sent by your authentication module, you can define here the new authentication level. Example: 5

  • Label (Optional): label that should be displayed to the user on the choice screen

  • Logo (Optional): logo file (in static/<skin> directory)


The command line is split in an array and launched with exec(). So you don’t need to enclose arguments in quotes to protect your system against shell injection. However, you can not use any space except to separate arguments.

SELinux note

If your server is enforcing SELinux policies, make sure your external script has a label that is allowed to be executed by httpd.

For example, storing your script in /usr/local/bin/ will give it a bin_t label that will work correctly.

If your script has a httpd_sys_script_exec_t type, it will only be able to do external network requests if the SELinux boolean httpd_can_network_connect is enabled.

If your script has any other label, it will probably not work at all.