Juniper SA 4500, Radiator and two-factor authentication using OTP

The past two weeks I’ve been looking into getting a juniper SA 4500 to work with Radiator to do two-factor authentication by using One-Time Passwords (OTP). Basicly, after user authentication is done against a Directory Server (DS), I want Radiator to lookup the user’s mobile number in the DS, create an One-Time Password and SMS this password to the user’s mobile phone.

Although Radiator can handle OTP, the AuthOTP.pm module that comes with Radiator isn’t sufficient to work directly with the Juniper. This is why I had to make a few changes to the original AuthOTP.pm module. Download the patch here.

In the configuration file below, you see an example on how to use the module.

 
# radius.cfg - Niels van Sluis, <niels@van-sluis.nl>
#
# Example Radiator configuration file.
#
# * retrieve mobile number from Directory Server.
# * generate and send One-Time Password to mobile number.
# * authenticate One-Time Password.
 
LogDir          /var/log/radius
DbDir           /etc/radiator
# User a lower trace level in production systems:
Trace           7
 
AuthPort        1812
AcctPort        1813
 
<Client juni-sslvpn.example.com>
        Secret mysecret
        Identifier juni-sslvpn
</Client>
 
<AuthBy LDAP2>
        # Radiator talks to Microsoft AD.
        # Try to find mobile number only.
        Identifier SSLVPN_LDAP
        Host            ldap.example.com
        BaseDN          OU=employees,DC=example,DC=com
        AuthDN          CN=srv_juniper,OU=Service Accounts,DC=example,DC=com
        AuthPassword    *****
        HoldServerConnection
        Timeout         2
        UsernameAttr    sAMAccountName
 
        # Get attribute that contains the mobile number.
        AuthAttrDef     MobileNumber
 
        # We don't do authentication. Authentication is done by OTP.
        NoCheckPassword
 
        # Some code to put the mobile number into memory, so it can be used
        # by OTP.
        PostSearchHook sub {\
            use Radius::Context;\
 
            my $user = $_[1];\
            my $attr = ($_[4]->get('MobileNumber'))[0];\
 
            my $context = &Radius::Context::get("otp:$user", 120);\
            $context->{mobile_number} = $attr;\
        }
</AuthBy>
 
<AuthBy OTP>
        # Authenticate based on One-Time Password sent to user by SMS.
        Identifier SSLVPN_OTP
        EAPType One-Time-Password,Generic-Token
        ChallengeHook sub {my ($self, $user, $p, $context) = @_;\
                $context->{otp_password} = $self->generate_password();\
                system('/etc/radiator/otp/sendsms.php', $user, $context->{mobile_number}, $context->{otp_password});\
                return "Enter One-Time Password"; \
            }
</AuthBy>
 
<AuthBy GROUP>
        Identifier Check-LDAP-and-OTP
        AuthByPolicy ContinueWhileAccept
        AuthBy SSLVPN_LDAP
        AuthBy SSLVPN_OTP
</AuthBY>
 
<Handler Client-Identifier = juni-sslvpn>
        RejectHasReason
        AuthBy Check-LDAP-and-OTP
</Handler>

Click here to download radius.cfg

Configure the Juniper SA 4500

Configuring two-factor authentication on the Juniper is really easy. When creating an user realm, you can choose to use an additional authentication server. So I configured two authentication servers. The first one authenticates against the Directory Server. The second authentication server uses radius to authenticate against Radiator. It will prompt the user to enter the One-Time Password.

Configure the additional Authentication Server

Create a new authentication server that uses RADIUS. Most important here are the ‘Custom Radius Rules’.
auth_server

Custom Radius Rules

The custom radius rules define how the Juniper talks with Radiator.

Rule 1

Here we define that the Juniper expects a challenge from Radiator and makes sure the user will be prompted with a page where he can enter the password that was send to the user’s mobile phone.
radius_rule_1

Rule 2

This rule defines what to do if the password entered by the user is rejected by Radiator. It will show the reason why the password was rejected.
radius_rule_2

Configure an User-Realm

The screen below shows how easy it is to create an user realm that uses an additional authentication server. Make sure the session is ended when authentication to the additional authentication server fails.
user_realm

Well, I hope this document will save you some time and money in setting up two-factor authentication on the Juniper SA 4500. Enjoy ;-)

Leave a Reply