. . .

LDAP Module

Introduction

This module synchronizes users from LDAP sources into ApiOmat LDAPUsers and LDAPGroups. LDAPUser is a subclass of a User and can be used to authenticate within an application or via REST. For authorization purposes, these users may be members of LDAPGroups, an inherited class of Role, The authentication is done directly against the LDAP directory.

Configuration

Server Hostname

Hostname(s) of the LDAP server(s), comma separated

Server Port

Port(s) of the LDAP server(s), comma separated, defaults to 389

Bind DN

User for bind operation, leave empty for anomyous

Bind DN password

User password for bind operation

Base DN

Root node of Directory

User filter

Filter to get all Users

User ID

LDAP attribute name which contains a user ID, this field will be used for the userName, defaults is set to sAMAccountName

Module of User class (optional)

If you want to inherit the LDAPUser model, insert your modules name here to sync users to it.

User class name (optional)

If you want to inherit the LDAPUser model, insert your classname here to sync users to it.

Activate sync LDAP groups

If set to true, the synchronisation will include LDAP groups

Group filter

Filter to get all groups

Group name attribute

The attributes that identifies a group's name. Default is 'cn'

Attributes holding member information

Attributes holding distinguished names of members, separated by comma

Module of Role class (optional)

If you want to inherit the LDAPGroup model, insert your module's name here to sync groups to it.

Role class name (optional)

If you want to inherit the LDAPGroup model, insert your classname here to sync groups to it.

Write user attributes map

If set to true, all attributes will be written to the "userAttributes" map of the LDAPUser (additionally to the fields that match the attribute names)

Overwrite missing attributes

If set to true (defaults to false), fields on the class will be set to null, if the related attribute does not exist (or is empty) in LDAP.
This does not apply for the general attributes (like allowedRolesRead) and all attributes which the User and LDAPUser class has. It does only apply to the values of the userAttributes-map of the LDAPUser and custom attributes of classes that inherit from LDAPUser.
If set to false, additional values (or values that existed on an LDAP entry and have been removed) will stay on the object in ApiOmat. This can be used to enrich the data of the synchronized users with additional values, f.i. from other systems.

Disable auth for the sync

If set to true (default), no auth checks will be done during user-synchronization. This increases the synchronization speed.
As the internal actions in a native module (findBy, save and delete) are usually done with backend owner permissions, this should not be harmful.
There may be a special case, if you use custom role and auth check methods and explicitly want that these methods are called during the synchronization, then you have to set this flag to false.

Log all messages async

If set to true, all messages of the synchronization process will be logged asynchronously.

Module setup

Fill in the values fitting to your directory. An example would be:

Server Hostname

ldap.example.com

Server Port

389

Bind DN

uid=admin,ou=system

Bind DN password

123456

Base DN

OU=com,DC=mycompany,DC=local

User filter

(objectCategory=Person)

User ID

uid

Group filter

(objectClass=group)

Group name attribute

cn

Attributes holding member information

uniquemember,member

Custom user class

You can set a custom user class where the LDAP users get synced to. Therefore, you have to create a class that inherits from the LDAPUser in the LDAP module and then set the module name and class name in the module configuration for the properties Module of User class and User class name.

You can add additional attributes that match the attribute names for your entities on the LDAP server. The values of these attributes will automatically get mapped on the synchronized objects. If you only need the attributes that exist on your class and don't want to have all attributes stored in the userAttributes attribute of the LDAPUser, you can set the Write user attributes map flag to false in your module configuration. This may speed up the synchronization process a bit and saves bandwith when retrieving the users whithin a frontend.

Custom role class

As done for LDAP users, you can define a custom LDAP group subclass with creating a class inheriting from LDAPGroup and configuring its class name and module name using the configuration properties Role class name and Module of Role class.

The name attribute of the respective objects will be populated with the value of the attribute whose name can be configured with the property Group name attribute.

Synchronization

The synchronization process splits up into four parts.

In the first part, all users that exist on the LDAP server will be imported as LDAPUser (or whichever class you've set in your configuration). Users that already exist as the configured class instance will be updated if there are changes on the object. Otherwise the existing ApiOmat Object won't get touched.

In the second part, the existing ApiOmat users of the configured class will get checked whether they still exist on the LDAP server. If they do not exist anymore, they will be deleted from ApiOmat.

In the third part, if the module configuration property Activate sync LDAP groups is set to true, groups from the LDAP server are imported as LDAP groups in the same manner as users. Further, using the configuration provided with the property Attributes holding member information names of users imported in the predecessing parts are added to the members list of the respective LDAPGroup.

In the fourth part, if the module configuration property Activate sync LDAP groups is set to true, the existing ApiOmat groups of the configured class are checked whether they still exist on the LDAP server. If they do not exist anymore, they are deleted from ApiOmat.

If your LDAP server is not available at time of sync, the sync will be aborted and the data on ApiOmat remain unchanged. If there is an error during the creation, update or deletion of a single user (e.g. through an already existing user with the same user name in another class) the error will be logged and the synchronization will proceed with the next user.

If more than one LDAP server is configured, the module tries to connect to each server until it finds a working connection. The first working connection is then used for synchonization. The list of ports are related to the hostnames. If no ports are given, port 389 will always be used. Otherwise, you have to write the ports in the corresponding order of the hostnames. For instance, if you have one ldap server on ldap1.yourcompany.com listening on port 489 and another serverldap2.yourcompany.com on port 589, you have to enter "ldap1.yourcompany.com,ldap2.yourcompany.com" in the hosts configuration and "489,589" in the ports configuration field.

Use

All you have to do is configure the directory and wait until the next synchronization, which is done every hour. You can also manually start the synchronization via the MyModule page in dashboard or via REST:

  curl -v $HOST/modules/ldap/spec/$APPNAME/sync/$APPNAME -u $USER:$PASSWORD

After a successful synchronization, you have to set the LDAPUser class (or if you configured another class for synchronization) as Authentication class in your backend configuration to authenticate to your LDAP server. Please note that we cannot synchronize the passwords of the users. Therefore you have to set the class as authentication class. We will then check the credentials against your LDAP server.

Your imported LDAPGroups' names may then be used in ApiOmat's access control lists of any class.

User Authentication via OAuth2 Tokens

The synchronized users are objects of the class LDAPUser, which inherits from the User class in the Basics module. So you can facilitate the OAuth2 functionality that already exists and for example send a request to "YOURHOST/yambas/oauth/token" to receive an access token for the user. For more info about how this works in ApiOmat, see this: ApiOmat and OAuth2.

In the case of LDAP, you might want to force the user to authenticate against the LDAP as soon as the access token is expired, instead of allowing them to use the previously received refresh token. To do this, just change the value yambas.oAuth2TokenValiditySeconds.standard.refresh in the apiomat.yaml to 0, or if you generally want refresh tokens to work and only not for LDAP, you can manually set the refresh token expiry in every request when fetching a token.