ASA

Cisco ASA AAA for VPN: LDAP, RADIUS, and TACACS+

Cisco ASA AAA for VPN: LDAP, RADIUS, and TACACS+
In: ASA

Authentication, Authorization, and Accounting (AAA) on a Cisco ASA decides three things for every VPN session: who is the user, what are they allowed to do, and what activity should be logged. The three protocols you can wire into the ASA for these jobs are LDAP (commonly Microsoft Active Directory), RADIUS, and TACACS+. Each one has its sweet spot, and a real production ASA frequently uses all three at the same time, just for different functions. This article walks the configuration of all three on Cisco ASA 9.x and shows when to use which. All output is from a live ASAv 9.23(1) in the PingLabz ASA reference lab.

Before configuring AAA, you should already have a working AnyConnect connection profile (see Cisco ASA AnyConnect SSL VPN Configuration) using local users. The AAA server group then plugs into the existing tunnel-group's authentication-server-group attribute, replacing or augmenting the local fallback.

When to Use Which Protocol

ProtocolBest forNotes
LDAP (most often Microsoft AD)VPN authentication and authorization with group memberships from your existing directory.Native to AD; no extra server needed. Use LDAPS (TCP/636) for production. Map AD group memberships to ASA group-policy attributes via ldap attribute-map.
RADIUSVPN authentication where you want to layer in MFA (Cisco Duo, Microsoft Entra MFA Server, RSA SecurID) or where you want clean accounting.Industry-standard. Most MFA solutions front-end RADIUS. Cleaner accounting than LDAP because RADIUS has Accounting-Start / Stop / Interim packets.
TACACS+Administrator authentication into the ASA itself: SSH, console, ASDM. Very rarely for VPN.Cisco-proprietary. Per-command authorization and per-command accounting (logs every CLI command run by an admin). Required for many regulatory regimes.

The common production split: LDAP for VPN authentication and group lookup, RADIUS for VPN authentication when MFA is required, TACACS+ for admin access into the ASA itself.

AAA Server Groups

All AAA on the ASA is configured in two layers: an aaa-server group (the protocol and the list of servers) and the references to that group from features that consume AAA (tunnel-groups, aaa authentication ssh console, etc.).

From our lab, three server groups are configured (one per protocol):

ASA-PERIM# show running-config aaa-server
aaa-server RADIUS-VPN protocol radius
aaa-server RADIUS-VPN (inside) host 10.10.0.10
 retry-interval 2
 timeout 5
 key *****
 authentication-port 1812
 accounting-port 1813
aaa-server LDAP-VPN protocol ldap
aaa-server LDAP-VPN (inside) host 10.10.0.20
 server-port 636
 ldap-base-dn dc=pinglabz,dc=lab
 ldap-scope subtree
 ldap-naming-attribute sAMAccountName
 ldap-login-password *****
 ldap-login-dn cn=svc-asa,ou=Service,dc=pinglabz,dc=lab
 ldap-over-ssl enable
 server-type microsoft
aaa-server TACACS-ADMIN protocol tacacs+
aaa-server TACACS-ADMIN (inside) host 10.10.0.30
 timeout 5
 key *****

Each server group has a name (RADIUS-VPN, LDAP-VPN, TACACS-ADMIN), a protocol, and one or more host entries. The ASA tries hosts in order; if the first is unreachable after the configured retry/timeout, it tries the second.

Configure RADIUS for VPN Authentication

Two-step pattern: declare the group with its protocol, then add hosts with their shared secret and timing.

ASA-PERIM(config)# aaa-server RADIUS-VPN protocol radius
ASA-PERIM(config)# aaa-server RADIUS-VPN (inside) host 10.10.0.10
ASA-PERIM(config-aaa-server-host)#  key PingLabz-RADIUS-Secret
ASA-PERIM(config-aaa-server-host)#  authentication-port 1812
ASA-PERIM(config-aaa-server-host)#  accounting-port 1813
ASA-PERIM(config-aaa-server-host)#  timeout 5
ASA-PERIM(config-aaa-server-host)#  retry-interval 2
ASA-PERIM(config-aaa-server-host)#  exit

Then bind the group into a tunnel-group:

ASA-PERIM(config)# tunnel-group SSL_PROFILE general-attributes
ASA-PERIM(config-tunnel-general)#  authentication-server-group RADIUS-VPN LOCAL
ASA-PERIM(config-tunnel-general)#  accounting-server-group RADIUS-VPN

The LOCAL after RADIUS-VPN means: try RADIUS first, fall back to the local username database if all RADIUS hosts are unreachable. Always include LOCAL fallback for VPN authentication; otherwise a RADIUS outage cuts off all remote access at exactly the worst moment (when admins need to log in to fix it).

Verify the server is at least reachable on the wire:

ASA-PERIM# test aaa-server authentication RADIUS-VPN host 10.10.0.10 username vpnuser password PingLabzVPN!
INFO: Attempting Authentication test to IP address <10.10.0.10> (timeout: 12 seconds)

The test aaa-server command is the fastest way to confirm the shared secret and reachability are correct. If the test hangs, your shared secret is right but the server is unreachable; if it returns "rejected" with an immediate response, the server is reachable but the credentials are wrong.

Configure LDAP (Active Directory) for Authorization

LDAP setup needs more attributes than RADIUS because there is no standard "give me the user's password and let me see if it matches" call. The ASA binds to the directory as a service account, then performs a sub-tree search to find the user by their login attribute, then re-binds as the user with their typed password.

ASA-PERIM(config)# aaa-server LDAP-VPN protocol ldap
ASA-PERIM(config)# aaa-server LDAP-VPN (inside) host 10.10.0.20
ASA-PERIM(config-aaa-server-host)#  ldap-base-dn dc=pinglabz,dc=lab
ASA-PERIM(config-aaa-server-host)#  ldap-scope subtree
ASA-PERIM(config-aaa-server-host)#  ldap-naming-attribute sAMAccountName
ASA-PERIM(config-aaa-server-host)#  ldap-login-dn cn=svc-asa,ou=Service,dc=pinglabz,dc=lab
ASA-PERIM(config-aaa-server-host)#  ldap-login-password PingLabz-LDAP-Secret
ASA-PERIM(config-aaa-server-host)#  server-type microsoft
ASA-PERIM(config-aaa-server-host)#  ldap-over-ssl enable
ASA-PERIM(config-aaa-server-host)#  server-port 636
ASA-PERIM(config-aaa-server-host)#  exit

The eight attributes:

  • ldap-base-dn: the root of the LDAP tree to search from. Typically your AD domain DN.
  • ldap-scope subtree: search the entire sub-tree below the base DN. The other choice (onelevel) only searches one level deep, which is rarely what you want.
  • ldap-naming-attribute sAMAccountName: the attribute that identifies a user. sAMAccountName is the AD short name (e.g. vpnuser). For OpenLDAP, it would be uid; for AD via UPN, use userPrincipalName.
  • ldap-login-dn + ldap-login-password: the service account the ASA binds as to perform the user search.
  • server-type microsoft: tells the ASA how to interpret password-expiry and account-locked responses. Other choices include generic, sun, openldap.
  • ldap-over-ssl enable + server-port 636: use LDAPS instead of clear-text LDAP. Always use LDAPS in production. Clear LDAP exposes the user's typed password to every device on the inside path between ASA and DC.

Bind to a tunnel-group as the authorization-server-group:

ASA-PERIM(config)# tunnel-group SSL_PROFILE general-attributes
ASA-PERIM(config-tunnel-general)#  authorization-server-group LDAP-VPN

This authorizes the user post-authentication: the ASA performs a second LDAP search to retrieve group memberships and attributes, which can be mapped to ASA group-policies via ldap attribute-map. The full attribute-map mechanism is covered in the DAP article (it ties cleanly into Dynamic Access Policies).

Configure TACACS+ for Admin Access

TACACS+ is rarely used for VPN authentication. Its strength is per-command authorization for admins logging into the ASA itself: every CLI command an admin runs is authorized by the TACACS+ server, and every command is logged via accounting.

ASA-PERIM(config)# aaa-server TACACS-ADMIN protocol tacacs+
ASA-PERIM(config)# aaa-server TACACS-ADMIN (inside) host 10.10.0.30
ASA-PERIM(config-aaa-server-host)#  key PingLabz-TACACS-Secret
ASA-PERIM(config-aaa-server-host)#  server-port 49
ASA-PERIM(config-aaa-server-host)#  timeout 5
ASA-PERIM(config-aaa-server-host)#  exit

Wire into the ASA's admin auth/authz/acct planes:

ASA-PERIM(config)# aaa authentication ssh console TACACS-ADMIN LOCAL
ASA-PERIM(config)# aaa authorization exec authentication-server
ASA-PERIM(config)# aaa accounting ssh console TACACS-ADMIN

What each line does:

  • aaa authentication ssh console TACACS-ADMIN LOCAL: authenticate SSH logins via TACACS+, fall back to local. The console keyword here means console-mode SSH (the standard SSH login flow).
  • aaa authorization exec authentication-server: when an authenticated admin enters exec mode, look up their privilege level on the same server that authenticated them. This drives the priv-15 vs priv-1 split.
  • aaa accounting ssh console TACACS-ADMIN: log SSH session start and stop, including duration.

For per-command logging (which most TACACS+ deployments want), add aaa accounting command privilege 15 TACACS-ADMIN to log every priv-15 command. This produces a full audit trail of who-typed-what.

Authentication, Authorization, Accounting Separated

You can mix protocols by feature. A common production pattern:

FeatureAuthenticationAuthorizationAccounting
VPN (SSL_PROFILE tunnel-group)RADIUS-VPN (with MFA), fall back LOCALLDAP-VPN (group lookup, attribute mapping)RADIUS-VPN (session start/stop with byte counts)
Admin SSHTACACS-ADMIN, fall back LOCALTACACS-ADMIN (per-command)TACACS-ADMIN (per-command)

Each function points at the protocol best suited to it. From our lab, this is exactly what we configured: SSL_PROFILE uses RADIUS for auth + LDAP for authz + RADIUS for acct, while admin SSH uses TACACS for all three.

Common Gotchas

  1. No LOCAL fallback. RADIUS or LDAP server has an outage, and now no one can log in. Always end the auth chain with LOCAL for VPN; always end with LOCAL for admin SSH.
  2. Clear-text LDAP. Without ldap-over-ssl enable, every VPN user's password traverses the inside network in clear-text inside an LDAP bind. Anyone on the path can sniff it. Use LDAPS (TCP/636) or STARTTLS (TCP/389 with negotiated TLS).
  3. Wrong service account permissions. The ldap-login-dn account must have read permission on the user OUs you intend to authenticate against. In AD, a domain user account is typically enough; service accounts often have explicit read-deny on Protected Users group, which breaks lookup.
  4. RADIUS shared-secret typo. Symptom: silent failure. The ASA gets no response and times out without giving a useful error. Verify with test aaa-server authentication; a working secret with bad credentials returns "Reject" while a bad secret hangs.
  5. Confusing authentication-server-group with authorization-server-group. The two attributes are independent. You can authenticate against RADIUS but authorize against LDAP. If you forget the authorization-server-group, no LDAP attribute-map firing will happen and the user gets the tunnel-group default group-policy regardless of their AD group memberships.

Key Takeaways

AAA on the Cisco ASA is configured in two layers: aaa-server groups (the protocol + hosts), then references to those groups from features (tunnel-groups, admin auth). LDAP fits VPN auth + AD group authorization. RADIUS fits VPN auth especially when MFA is in the mix, and provides clean per-session accounting. TACACS+ fits admin auth into the ASA with per-command authorization and audit-grade logging. A real production ASA uses all three concurrently, each for the function it does best.

For the full Cisco ASA reference, including site-to-site IPsec, NAT, ACLs, failover, and the troubleshooting tools, see the Cisco ASA pillar. The next step after AAA is mapping the AAA-returned attributes (and endpoint posture) to runtime decisions: Cisco ASA Dynamic Access Policies (DAP) covers that. For the connection-profile foundation, see Cisco ASA VPN Group Policies and Tunnel Groups.

Written by
More from Ping Labz
Great! You’ve successfully signed up.
Welcome back! You've successfully signed in.
You've successfully subscribed to Ping Labz.
Your link has expired.
Success! Check your email for magic link to sign-in.
Success! Your billing info has been updated.
Your billing was not updated.