Skip to main content

Tutorial: Implementing a Post-Auth Script with X.509 Attributes

Abstract

Extend Access Server's authentication by restricting VPN access based on X.509 attributes and automatically mapping to user groups.

Overview

Access Server includes a post-auth programming hook that lets you extend authentication behavior after a user successfully authenticates. This tutorial explains how to use a post-auth script to:

  • Restrict VPN access based on X.509 attributes in a client certificate.

  • Automatically map users to Access Server groups based on those attributes.

Note

The examples in this guide use a custom X.509 attribute from the client certificate and require Access Server to run in ePKI mode.

Authentication and the post-auth script role

Access Server's authentication system

Access Server supports several robust authentication systems without using a post-auth script — whether you manage it from the Admin Web UI or authenticate against a third-party system. These are the systems already supported:

  1. Local: Access Server's built-in authentication system storing user credential hashes in the user properties database, with management handled in the Admin Web UI.

  2. PAM: Linux system that requires console management or an SSH session on the OS.

  3. LDAP: Once you set up the connection in the Admin Web UI, Access Server can authenticate against an LDAP server.

  4. RADIUS: Once you set up the connection in the Admin Web UI, the Access Server can authenticate against a RADIUS server.

  5. SAML: Once you set up the connection in the Admin Web UI, Access Server can use SAML single sign-on (SSO) by authenticating through an identity provider (IdP).

For more information about these authentication methods, refer to this detailed topic: Authentication System.

The post-auth script process

  1. The user signs in with a VPN client or on the Client Web UI.

  2. They successfully authenticate with their credentials.

  3. The post-auth script runs (hence, post-auth — after authentication).

The post-auth script is a text file written in Python. It can do all sorts of interesting things, like automating user group assignment based on specific criteria, implementing a custom authentication system, adding an extra filter to the login process, or checking the user device's hardware address.

Prerequisites

Important

Custom X.509 attributes are available only when using ePKI mode. This approach does not work if Access Server operates as its own PKI (default mode).

Supported X.509 attributes

The following X.509 attributes were tested for this tutorial:

CN

Common Name

OU

Organizational Unit

O

Organization

L

Locality

ST

State

C

Country

CN+

Common Name of chain

subjectAltName

Allows users to specify additional hostnames for a single SSL certificate

basicConstraints

Used to identify the type of certificate holder/subject

SHA256

Certificate Fingerprint

Important

The example scripts in this tutorial use OU (Organizational Unit). You can adapt them to another supported attribute if needed.

How the post-auth script with X.509 attributes works

This tutorial includes two sample post-auth scripts.

Script 1: Allow or deny access

Process overview:

  1. The user attempts to authenticate.

  2. The post-auth script reads the configured X.509 attribute from the client certificate.

  3. If the value matches the expected value, the VPN connection succeeds.

  4. If it doesn't match, Access Server denies the connection.

Script 2: Group mapping

Process overview:

  1. The user attempts to authenticate.

  2. The post-auth script reads the configured X.509 attribute.

  3. If the value matches an existing Access Server group name, Access Server assigns the user to that group.

  4. If no match exists, Access Server applies the default group settings.

Important

For group mapping to work, the Access Server group name must exactly match the X.509 attribute value.

For example, if the configured X.509 attribute contains 'vpnrole,' then Access Server must have an existing group named 'vpnrole.' Otherwise, the default group settings are applied.

This tutorial uses the OU attribute.

  1. Sign in to the Admin Web UI.

  2. Click Configuration > Advanced VPN.

  3. Under Additional OpenVPN Config Directives (Advanced), enter the following for the Server Config Directives:

    x509-track "OU"

Option A: Set up post-auth script #1 (allow or deny access)

  1. Sign in to the server using SSH and get root privileges.

  2. Download the example script:

    wget https://packages.openvpn.net/as/scripts/post_auth_x509.py -O /root/x509_pas.py1

    1

    This saves the script to the /root/ directory with the name x509_pas.py.

    Tip

    If you have problems downloading the script this way, you may need to install/update the wget and/or ca-certificates package(s) on your system.

  3. (Optional) Edit the script:

    nano /root/x509_pas.py
    • Make your changes to the script, then save and exit.

  4. Load the script into the Access Server configuration and restart:

    sacli --key "auth.module.post_auth_script" --value_file=/root/x509_pas.py ConfigPut
    sacli start

    Important

    Reload the script using these commands after every change.

Example log output

  • Match (authentication succeeds):

    ***** POST_AUTH X509 CHECK: connection attempt        : SUCCESS
  • No match (authentication fails):

    2026-02-16T11:18:53-0500 [stdout#info] ***** POST_AUTH X509 CHECK: client OU                 : 'finance'
    2026-02-16T11:18:53-0500 [stdout#info] ***** POST_AUTH X509 CHECK: required OU               : 'vpnrole'
    2026-02-16T11:18:53-0500 [stdout#info] ***** POST_AUTH X509 CHECK: connection attempt        : FAILED
    2026-02-16T11:18:53-0500 [stdout#info] VPN Auth Failed: "The OU reported 'finance' by this VPN client does not match the required OU 'vpnrole'." ["The OU reported 'finance' by this VPN client does not match the required OU 'vpnrole'."]

Option B: Set up post-auth script #2 (group mapping)

  1. Sign in to the server using SSH and get root privileges.

  2. Download the example script:

    wget https://packages.openvpn.net/as/scripts/post_auth_x509_group.py -O /root/x509_pas_group.py1

    1

    This saves the script to the /root/ directory with the name x509_pas_group.py.

    Tip

    If you have problems downloading the script this way, you may need to install/update the wget and/or ca-certificates package(s) on your system.

  3. (Optional) Edit the script:

    nano /root/x509_pas_group.py
    • Make your changes to the script, then save and exit.

  4. Load the script into the Access Server configuration and restart:

    sacli --key "auth.module.post_auth_script" --value_file=/root/x509_pas_group.py ConfigPut
    sacli start

    Important

    Reload the script using these commands after every change.

Verify group mapping

  • Check the assigned group:

    sacli --pfilt <username> UserPropGet
    • Example output:

      {
        "<username>": {
          "conn_group": "vpnrole",
          "type": "user_connect"
        }
      }

Example log output

  • Match (authentication succeeds):

    ***** POST_AUTH: User group mapping found for '<username>', setting OpenVPN connection group to 'vpnrole' ...
  • No match (authentication fails):

    ***** POST_AUTH: No group mapping matches found for '<username>' ... Using default group settings...

Review logs

Access Server logs post-auth activity in:

/var/log/openvpnas.log

Add print lines to the script

You can edit the post-auth script on your server and add print() statements to write more details to the log. This can help you confirm the values of specific variables while Access Server runs the post-auth script.

Filter for post-auth messages

You can filter the log file to display only post-auth messages:

egrep "POST_AUTH" /var/log/openvpnas.log

To filter by OU:

tr ',' '\n' < /var/log/openvpnas.log | grep 'X509_0_OU'