LDAP / Active Directory Integration
Point Athena at your LDAP or Active Directory so staff sign in with their existing directory credentials — no second set of passwords to manage. Athena verifies each login against the directory, maps the user's directory groups to Athena roles, and creates the local account on first sign-in. Local accounts keep working alongside it, so you always retain a break-glass path.
Directory login is configured under Settings → Security → Login (Admin only).
The same settings are available over the REST API at api/settings/ldap and through the
Athena PowerShell module. Keycloak single sign-on lives on the same Login sub-tab — see
Authentication & SSO.
How directory login works#
Athena uses the standard search-then-bind pattern. It never guesses a user's distinguished name from a template — it looks the user up first, then binds as the account it found:
- Service bind. Athena connects to your directory and binds with the dedicated
service account you configure (
BindDn/BindPassword). - Search. Using your
UserSearchFilter(the typed username is safely escaped), Athena finds the one matching entry under theBaseDn. A search that returns zero or more than one entry is treated as a failed login. - Group resolution. Athena reads the user's group membership — by default it
resolves nested (transitive) membership on Active Directory, falling back to the
direct
memberOflist on directories that don't support that. - User bind. Athena opens a fresh connection and binds as the discovered account with the password the user typed. This bind is the real credential check.
- Role & account. The user's groups are mapped to an Athena role, and the account is provisioned or refreshed just-in-time (see Group-to-role mapping and Just-in-time provisioning).
Directory users sign in on the normal Athena login screen (and at api/auth/login) —
there's no separate URL. Athena decides which provider verifies the credentials and stamps the
session accordingly, so roles and authorization work identically no matter how someone signed in.
Before you start#
- A service / bind account in your directory with read access to user and group objects. Athena binds as this account to search; it fails closed (denies all directory logins) if the bind account is not configured, so it never silently falls back to an anonymous search.
- The directory host and port (default
636for LDAPS) reachable from the Athena server. - Your search base DN (for example
DC=corp,DC=example). - For TLS transports, the directory's CA certificate trusted by the Athena server (see Transport & TLS).
- An Admin Athena account to save the settings.
Configure the connection#
Fill in the directory connection on Settings → Security → Login, or send it to
api/settings/ldap. The main fields:
| Field | Meaning | Default / example |
|---|---|---|
Enabled | Turn directory login on. Off = local accounts only. | false |
Host | Directory host — DNS name or IP of the domain controller / LDAP server. | dc01.corp.example |
Port | Directory port. | 636 |
EncryptionMode | Transport security: LDAPS, StartTLS, or LDAP (see Transport & TLS). | LDAPS |
BaseDn | Search base for user lookups. | DC=corp,DC=example |
BindDn | Service-account DN used for the initial search bind. | CN=svc-athena,OU=Service,DC=corp,DC=example |
BindPassword | Service-account password. Write-only — stored encrypted, never returned (see the note below). | •••••••• |
DefaultRole | Role granted when a user's groups match no mapping. | User |
DenyOnNoMatch | Deny sign-in when no group maps, instead of granting the default role. | false |
ConnectionTimeoutSeconds | Connect / bind timeout, so an unreachable directory fails fast. | 10 |
When you read the settings back — in the UI, over the API, or with
Get-AthenaLdapSettings — a stored bind password is shown as a mask
(********), never the real secret. On save, leaving the mask in place keeps the stored
password unchanged; supplying a new value rotates it; clearing it removes it. The stored secret is
encrypted at rest.
Attribute & filter mapping#
The defaults target Active Directory. Adjust these for OpenLDAP or other directories. In the
UserSearchFilter and NestedGroupSearchFilter, {0} is replaced
by the (safely escaped) username or user DN respectively.
| Field | Purpose | Default |
|---|---|---|
UserSearchFilter | Finds the user entry by the typed username. | (sAMAccountName={0}) — use (uid={0}) for OpenLDAP |
GroupMembershipAttribute | Attribute on the user entry that lists direct group membership. | memberOf |
NestedGroupSearchFilter | Resolves transitive (nested) group membership; {0} is the user DN. Leave empty to use only the direct membership attribute. | (member:1.2.840.113556.1.4.1941:={0}) (AD in-chain rule) |
GroupSearchBaseDn | Base DN the nested-group search is rooted at. Empty = use BaseDn. | (empty) |
DisplayNameAttribute | Display name, refreshed on each login. | displayName |
EmailAttribute | Email address, refreshed on each login. | mail |
ExternalIdAttribute | Immutable identity used to recognise returning users across renames / OU moves. | objectGUID |
CaCertificatePath / CaCertificateThumbprint | Trust anchor for the directory's TLS certificate (optional; see Transport & TLS). | (empty) |
Transport & TLS#
The EncryptionMode controls how the connection is secured:
| Mode | Behaviour | Typical port |
|---|---|---|
LDAPS default | Implicit TLS from connect — encrypted before the bind. | 636 |
StartTLS | Connect in the clear, then upgrade to TLS before the bind. | 389 |
LDAP | Plain, unencrypted bind. An explicit admin choice for trusted / isolated networks only. | 389 |
An unset or unrecognised mode is rejected and defaults to the fail-secure LDAPS. For
the encrypted modes, the Athena server must trust the certificate the directory presents — install
the directory's CA into the operating-system trust store, or point Athena at it with
CaCertificatePath / CaCertificateThumbprint.
The bind sends credentials to the directory. Use LDAPS or StartTLS
wherever possible; only choose plain LDAP on a network you fully trust. Athena defaults
to encrypted and never silently downgrades.
Test the connection#
Before you enable directory login, run the built-in probe. It performs the service bind, validates TLS, and checks that the base DN is reachable — and it can test settings you haven't saved yet, so you can validate a change before committing it.
# Probe the currently saved settings
Test-AthenaLdapConnection
# Probe an unsaved configuration (values you pass override the saved ones)
Test-AthenaLdapConnection -Host "dc01.corp.example" `
-BindDn "CN=svc-athena,OU=Service,DC=corp,DC=example" `
-BindPassword "<service-password>"
The probe never throws — a failure comes back as a result with Success = false plus a
human-readable message and a non-sensitive diagnostic hint (the failing step), so you can tell a TLS
problem from a bad bind or an unreachable base DN. The same probe backs the Test connection
button in the Settings UI and the POST api/settings/ldap/test-connection endpoint.
Group-to-role mapping#
Athena has four fixed roles — User, Helpdesk, Operator, and
Admin (see Roles & Permissions). You grant them to
directory users by mapping directory groups to roles. Each mapping is one
group → role rule.
- Highest role wins. If a user's groups match several mappings, they get the highest-privilege role among them.
- No match. A user whose groups match no mapping gets the
DefaultRole— unlessDenyOnNoMatchis on, in which case sign-in is denied. - Per-provider. Mappings are scoped to a provider (
LdaporKeycloak): an LDAP login resolves only againstLdapmappings, so the same group name can be reused for Keycloak without collision. - Edited mappings take effect on the next sign-in — no restart required.
Manage mappings in the console, or with the PowerShell module:
# Map a directory group to the Admin role
New-AthenaLdapMapping -GroupName "athena-admins" -Role Admin
# List the current LDAP mappings
Get-AthenaLdapMapping
# Change a mapping, then remove one by id
Set-AthenaLdapMapping -Id $id -GroupName "athena-operators" -Role Operator
Remove-AthenaLdapMapping -Id $id
Leave DefaultRole at User (or turn on DenyOnNoMatch), then
grant elevated roles only through explicit group mappings. Because the highest matching role wins,
an admin group mapping cleanly overrides any lower-privilege mapping the same user also matches.
Just-in-time provisioning#
You don't pre-create directory accounts in Athena. On a user's first successful directory sign-in,
Athena creates their local account automatically and keys it to the immutable
ExternalIdAttribute (objectGUID by default), so a later rename or OU move
still recognises the same person. On every subsequent login, Athena refreshes the account's
role, display name, and email from the current
directory state. A few rules keep this safe:
- Directory accounts never store a local password — they can only sign in through the directory.
- A directory login can never take over an existing local account (or a different provider's account) that already owns the same username — that login is refused rather than converting the account.
- An account an admin has disabled in Athena stays disabled — a valid directory bind will not re-enable it.
REST API#
All endpoints below require an Admin session. See the API Reference for authentication details.
| Method & path | Purpose |
|---|---|
GET api/settings/ldap | Read the current directory configuration (bind password masked). |
PUT api/settings/ldap | Update the directory configuration. Changes are audited with an old→new diff. |
POST api/settings/ldap/test-connection | Probe a (possibly unsaved) configuration; a failure is returned in the body, not as an HTTP error. |
GET api/settings/ldap/mappings | List group-to-role mappings (optional ?provider=Ldap). |
POST api/settings/ldap/mappings | Create a group-to-role mapping. |
PUT api/settings/ldap/mappings/{id} | Update a mapping. |
DELETE api/settings/ldap/mappings/{id} | Delete a mapping. |
PowerShell#
The Athena module exposes the whole workflow. All of these require an Admin session — connect first with Connect-Athena.
| Cmdlet | What it does |
|---|---|
Get-AthenaLdapSettings | Show the current directory settings (bind password masked). |
Set-AthenaLdapSettings | Update settings; only the parameters you pass change, and omitting -BindPassword keeps the stored secret. |
Test-AthenaLdapConnection | Probe saved or supplied settings; a failed probe is data (Success = $false), not a terminating error. |
Get-AthenaLdapMapping | List the group-to-role mappings. |
New-AthenaLdapMapping | Create a mapping (-GroupName, -Role). |
Set-AthenaLdapMapping | Update a mapping by -Id. |
Remove-AthenaLdapMapping | Delete a mapping by -Id (prompts for confirmation). |
A minimal end-to-end enablement, from a connected Admin session:
# 1) Configure the directory connection (LDAPS)
Set-AthenaLdapSettings -Enabled $true `
-Host "dc01.corp.example" -Port 636 `
-EncryptionMode "LDAPS" `
-BaseDn "DC=corp,DC=example" `
-BindDn "CN=svc-athena,OU=Service,DC=corp,DC=example" `
-BindPassword "<service-password>"
# 2) Verify it works before anyone relies on it
Test-AthenaLdapConnection
# 3) Grant roles by group
New-AthenaLdapMapping -GroupName "athena-admins" -Role Admin
New-AthenaLdapMapping -GroupName "athena-operators" -Role Operator
New-AthenaLdapMapping -GroupName "helpdesk" -Role Helpdesk
Auditing#
Directory configuration changes are written to the audit log as an authentication settings change, recording a per-field old→new diff (the bind secret is never included). Directory sign-ins, role refreshes, and denials are logged like any other login. See Audit & SIEM for how to review and forward these events.
Troubleshooting#
| Symptom | Likely cause & fix |
|---|---|
| Test connection fails on TLS / certificate | The directory's CA isn't trusted by the Athena server. Install it into the OS trust store, or set CaCertificatePath / CaCertificateThumbprint. Confirm the host matches the certificate name. |
| Test connection fails on bind | Wrong BindDn or BindPassword. Directory login also fails closed if the bind account is blank — Athena will not anonymous-bind. |
| Users can't sign in, but bind succeeds | The UserSearchFilter or BaseDn doesn't match. A search that returns zero or more than one entry is a failed login — tighten the filter for the directory type (AD vs OpenLDAP). |
| User signs in but gets the wrong role | Check the group mappings — the highest matching role wins. Confirm nested membership resolves (default AD in-chain rule) or set a direct filter for non-AD directories. |
| User signs in but is denied | Their groups match no mapping and DenyOnNoMatch is on — add a mapping or set a DefaultRole. A username that collides with a local account, or an account disabled in Athena, is also denied. |