LDAP Auth provider¶
Description¶
This auth provider checks for user credentials in LDAP, and and then issues an access token.
All requests to backend should be made with passing this access token. If token is expired, then new auth token should be issued.
After successful auth, username is saved to backend database. It is then used for creating audit records for any object change, see changed_by field.
Warning
Until token is valid, no requests will be made to LDAP to check if user exists and not locked. So do not set access token expiration time for too long (e.g. longer than a day).
Strategies¶
Note
Basic LDAP terminology is explained here: LDAP Overview
There are 2 strategies to check for user in LDAP:
- Try to call
bindrequest in LDAP withDN(DistinguishedName) and user password.DNis generated usingbind_dn_template - First try to lookup for user (
searchrequest) in LDAP to get user'sDNusing some query, and then try to callbindusing thisDN. Seelookupsettings
By default, lookup strategy is used, as it can find user in a complex LDAP/ActiveDirectory environment. For example:
- search for user by
uid, e.g.(uid={login})or(sAMAccountName={login}) - search for user by several attributes, e.g.
(|(uid={login})(mail={login}@domain.com)) - filter for entries, like
(&(uid={login})(objectClass=person) - filter for users matching a specific group or some other condition, like
(&(uid={login})(memberOf=cn=MyPrettyGroup,ou=Groups,dc=mycompany,dc=com))
After user is found in LDAP, its uid_attribute is used for audit records.
Interaction schema¶
sequenceDiagram
participant "Client"
participant "Backend"
participant "LDAP"
activate "Client"
alt Successful case
"Client" ->> "Backend" : login + password
"Backend" ->> "Backend" : DN = bind_dn_template(login)
"Backend" ->> "LDAP" : Call bind(DN, password)
"LDAP" ->> "Backend" : Successful
"Backend" ->> "Backend" : Check user in internal backend database,\nusername = login
"Backend" ->> "Backend" : Create user if not exist
"Backend" ->> "Client" : Generate and return access_token
else Wrong credentials | User blocker in LDAP
"Client" ->> "Backend" : login + password
"Backend" ->> "Backend" : DN = bind_dn_template(login)
"Backend" ->> "LDAP" : Call bind(DN, password)
"LDAP" --x "Backend" : Bind error
"Backend" --x "Client" : 401 Unauthorized
else User is blocked in internal backend database
"Client" ->> "Backend" : login + password
"Backend" ->> "Backend" : DN = bind_dn_template(login)
"Backend" ->> "LDAP" : Call bind(DN, password)
"Backend" ->> "Backend" : Check user in internal backend database,\nusername = login
"Backend" --x "Client" : 404 Not found
else User is deleted in internal backend database
"Client" ->> "Backend" : login + password
"Backend" ->> "Backend" : DN = bind_dn_template(login)
"Backend" ->> "LDAP" : Call bind(DN, password)
"LDAP" ->> "Backend" : Return user info
"Backend" ->> "Backend" : Check user in internal backend database,\nusername = login
"Backend" --x "Client" : 404 Not found
else LDAP is unavailable
"Client" ->> "Backend" : login + password
"Backend" ->> "Backend" : DN = bind_dn_template(login)
"Backend" --x "LDAP" : Call bind(DN, password)
"Backend" --x "Client" : 503 Service unavailable
end
alt Successful case
"Client" ->> "Backend" : access_token
"Backend" ->> "Backend" : Validate token
"Backend" ->> "Backend" : Check user in internal backend database
"Backend" ->> "Backend" : Get data
"Backend" ->> "Client" : Return data
else Token is expired
"Client" ->> "Backend" : access_token
"Backend" ->> "Backend" : Validate token
"Backend" --x "Client" : 401 Unauthorized
else User is blocked
"Client" ->> "Backend" : access_token
"Backend" ->> "Backend" : Validate token
"Backend" ->> "Backend" : Check user in internal backend database
"Backend" --x "Client" : 401 Unauthorized
else
"Client" ->> "Backend" : access_token
"Backend" ->> "Backend" : Validate token
"Backend" ->> "Backend" : Check user in internal backend database
"Backend" --x "Client" : 404 Not found
end
deactivate "Client"
sequenceDiagram
participant "Client"
participant "Backend"
participant "LDAP"
"Backend" -> "LDAP" : bind(lookup.username, lookup.password)
activate "LDAP"
Note right of "LDAP" : Open connection \npool for\nsearch queries\n(optional, recommended)
activate "Client"
alt Successful case
"Client" ->> "Backend" : login + password
"Backend" ->> "Backend" : query = query_template(login)
"Backend" ->> "LDAP" : Call search(query, base_dn, attributes=*)
activate "LDAP"
"LDAP" ->> "Backend" : Return user DN and uid_attribute
deactivate "LDAP"
"Backend" ->> "LDAP" : Call bind(DN, password)
"LDAP" ->> "Backend" : Successful
"Backend" ->> "Backend" : Check user in internal backend database,\nusername = uid_attribute from LDAP response
"Backend" ->> "Backend" : Create user if not exist
"Backend" ->> "Client" : Generate and return access_token
else Wrong credentials | User blocker in LDAP
"Client" ->> "Backend" : login + password
"Backend" ->> "Backend" : query = query_template(login)
"Backend" ->> "LDAP" : Call search(query, base_dn, attributes=*)
activate "LDAP"
"LDAP" ->> "Backend" : Return user DN and uid_attribute
deactivate "LDAP"
"Backend" ->> "LDAP" : Call bind(DN, password)
"LDAP" --x "Backend" : Bind error
"Backend" --x "Client" : 401 Unauthorized
else User is blocked in internal backend database
"Client" ->> "Backend" : login + password
"Backend" ->> "Backend" : query = query_template(login)
"Backend" ->> "LDAP" : Call search(query, base_dn, attributes=*)
activate "LDAP"
"LDAP" ->> "Backend" : Return user DN and uid_attribute
deactivate "LDAP"
"Backend" ->> "LDAP" : Call bind(DN, password)
"LDAP" ->> "Backend" : Successful
"Backend" ->> "Backend" : Check user in internal backend database,\nusername = uid_attribute from LDAP response
"Backend" --x "Client" : 404 Not found
else User is deleted in internal backend database
"Client" ->> "Backend" : login + password
"Backend" ->> "Backend" : query = query_template(login)
"Backend" ->> "LDAP" : Call search(query, base_dn, attributes=*)
activate "LDAP"
"LDAP" ->> "Backend" : Return user DN and uid_attribute
deactivate "LDAP"
"Backend" ->> "LDAP" : Call bind(DN, password)
"LDAP" ->> "Backend" : Successful
"Backend" ->> "Backend" : Check user in internal backend database,\nusername = uid_attribute from LDAP response
"Backend" --x "Client" : 404 Not found
else LDAP is unavailable
"Client" ->> "Backend" : login + password
"Backend" ->> "Backend" : query = query_template(login)
"Backend" --x "LDAP" : Call search(query, base_dn, attributes=*)
"Backend" --x "Client" : 503 Service unavailable
end
alt Successful case
"Client" ->> "Backend" : access_token
"Backend" ->> "Backend" : Validate token
"Backend" ->> "Backend" : Check user in internal backend database
"Backend" ->> "Backend" : Get data
"Backend" ->> "Client" : Return data
else Token is expired
"Client" ->> "Backend" : access_token
"Backend" ->> "Backend" : Validate token
"Backend" --x "Client" : 401 Unauthorized
else User is blocked
"Client" ->> "Backend" : access_token
"Backend" ->> "Backend" : Validate token
"Backend" ->> "Backend" : Check user in internal backend database
"Backend" --x "Client" : 401 Unauthorized
else User is deleted
"Client" ->> "Backend" : access_token
"Backend" ->> "Backend" : Validate token
"Backend" ->> "Backend" : Check user in internal backend database
"Backend" --x "Client" : 404 Not found
end
deactivate "LDAP"
deactivate "Client"
Basic configuration¶
LDAPAuthProviderSettings
¶
Settings for LDAPAuthProvider.
Examples:
auth:
provider: horizon.backend.providers.auth.ldap.LDAPAuthProvider
access_token:
secret_key: secret
ldap:
url: ldap://ldap.domain.com:389
base_dn: ou=users,dc=example,dc=com
lookup:
enabled: true
pool:
enabled: true
credentials:
user: uid=techuser,ou=users,dc=example,dc=com
password: somepassword
Parameters:
-
(access_token¶JWTSettings) –Access-token related settings
-
(ldap¶LDAPSettings) –LDAP related settings
LDAPSettings
¶
Settings related to LDAP interaction.
Examples:
auth:
ldap:
url: ldap://ldap.domain.com:389
base_dn: ou=users,dc=example,dc=com
uid_attribute: sAMAccountName
Parameters:
-
(url¶AnyUrl) –LDAP URL to connect to
-
(timeout_seconds¶int | None, default:10) –LDAP request timeout, in seconds.
Nonemeans no timeout -
(auth_mechanism¶Literal['SIMPLE', 'DIGEST-MD5'], default:'SIMPLE') –LDAP auth mechanism, used for
bindrequest -
(base_dn¶str) –Organization DN, e.g.
ou=users,dc=example,dc=com -
(uid_attribute¶str, default:'uid') –Attribute containing username.
Usually
uid(LDAP) orsAMAccountName(ActiveDirectory). -
(bind_dn_template¶str, default:'{uid_attribute}={login},{base_dn}') –Template for building DN string, used for checking credentials in LDAP. You can pass any DN value supported by LDAP.
Supported substitution values:
{login}{uid_attribute}{base_dn}
-
(lookup¶LDAPLookupSettings, default:<dynamic>) –LDAP search options
JWTSettings
¶
Settings related to JWT tokens.
Examples:
auth:
access_token:
secret_key: somesecret
expire_seconds: 3600 # 1 hour
Parameters:
-
(secret_key¶SecretStr) –Secret key for signing JWT tokens.
Can be any string. It is recommended to generate random value for every application instance.
-
(security_algorithm¶str, default:'HS256') –Algorithm used for signing JWT tokens.
See authlib documentation.
-
(expire_seconds¶int, default:36000) –Token expiration time, in seconds
LDAPConnectionPoolSettings
¶
Settings related to LDAP connection pool.
Examples:
auth:
ldap:
lookup:
pool:
enabled: true
max: 10
Parameters:
Lookup-related configuration¶
LDAPLookupSettings
¶
Settings related to LDAP lookup.
Examples:
auth:
ldap:
lookup:
enabled: true
pool:
enabled: true
credentials:
user: uid=techuser,ou=users,dc=example,dc=com
password: somepassword
query_template: (uid={login})
Parameters:
-
(enabled¶bool, default:True) –Set to
Trueto enable lookup -
(check_on_startup¶bool, default:True) –If
True, and LDAP is not available during application start, abort application startup -
(pool¶LDAPConnectionPoolSettings, default:<dynamic>) –LDAP connection pool settings
-
(credentials¶LDAPCredentials | None, default:None) –Credentials used for connecting to LDAP while performing user lookup
-
(query_template¶str, default:'({uid_attribute}={login})') –LDAP query send in lookup request.
Usually lookup is performed against attributes
uid(LDAP) orsAMAccountName(ActiveDirectory). You can also pass any query string supported by LDAP. See Bonsai documentation.Supported substitution values:
{login}{uid_attribute}
-
(scope¶Literal['BASE', 'ONELEVEL', 'SUBTREE'], default:'ONELEVEL') –Lookup scope. Use
SUBTREEfor ActiveDirectory.See Bonsai documentation.
LDAPCredentials
¶
LDAP lookup query is executed using this credentials (instead of login and password provided by user).
Examples:
auth:
ldap:
lookup:
credentials:
user: uid=techuser,ou=users,dc=example,dc=com
password: somepassword
Parameters: