# LDAP Authentication

> Source: https://docs.synthesized.io/tdk/latest/user_guide/060_security_compliance/authentication/ldap_activedirectory
> For the complete documentation index, see [llms.txt](https://docs.synthesized.io/llms.txt).

LDAP (Lightweight Directory Access Protocol) is often used by organizations as a central repository for user information and as an authentication service. It can also be used to store role information for application users.

The LDAP integration is based on the [spring-security-ldap](https://docs.spring.io/spring-security/reference/servlet/authentication/passwords/ldap.html) module with useful extensions.

> **TIP**
> Before you start configuring the Governor LDAP integration, ensure that you have access to your organization’s LDAP server. Or you can try [ldap-sdk-tools](https://hub.docker.com/r/pingidentity/ldap-sdk-tools) to run LDAP locally as an alternative.

- `CN`: Common Name
- `OU`: Organizational Unit
- `DC`: Domain Component

## Configuration

### LDAP Connectivity

The URL of the LDAP server is specified using the `url` property. The URL should be in the format `ldap://myserver.example.com:389`. For SSL access, use the `ldaps` protocol and the appropriate port, e.g. `ldaps://myserver.example.com:636`.

It is possible to configure multiple alternate LDAP servers using the `urls` property. In this case, provide all server URLs in a String array for the `urls` property.

```properties
spring.ldap.urls=ldap://localhost:389
```

You can also specify the root context for all LDAP operations using the `base` property. When a value has been specified for this property, all Distinguished Names supplied to and received from LDAP operations will be relative to the LDAP path supplied. This can significantly simplify working with the LDAP tree; however, there are several occasions when you will need to have access to the base path.

```properties
spring.ldap.base=dc=synthesized,dc=io
```

### The LDAP user selection

It is possible to customize a user selection strategy according to the organization’s structure. Let’s consider the following example of a user definition:

```ldif
dn: uid=bob,ou=people,dc=synthesized,dc=io
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectclass: inetOrgPerson
cn: Bob Hamilton
sn: Hamilton
uid: bob
userPassword: bobspassword
```

To fetch this user, you need to specify two predicates:

```properties
ldap.user-details.user-search-base=ou=people (1)
ldap.user-details.user-search-filter=uid={0} (2)
```

<table><tbody><tr><td><i class="conum" data-value="1"></i><b>1</b></td><td>Define the predicate where users would be located. In this example, the user is located in the <code>people</code> unit.</td></tr><tr><td><i class="conum" data-value="2"></i><b>2</b></td><td>Define the predicate that extracts a user login from the <code>uid</code> variable.</td></tr></tbody></table>

> **TIP**
> The property values are set by default and do not require overriding in the base scenario.

### Authentication

The Governor’s LDAP supplies two authentication implementations:

1. [Using Password Authentication](#using_password_authentication)
2. [Using Bind Authentication](#using_bind_authentication)

Where `Password Authentication` is used by default.

#### Using Password Authentication

Password comparison involves comparing the password supplied by the user with the one stored in the LDAP Server. The password value is retrieved from an attribute and checked locally. This method is less secure than [Using Bind Authentication](#using_bind_authentication), and usually requires `SSL` access.

> **NOTE**
> An LDAP compare cannot be done when the password is properly hashed with a random salt.

The integration supports many password encoder formats: `SHA`, `SHA256`, `SHA384`, `SHA512`, `SSHA`, `SSHA256`, `SSHA384`, `SSHA512`, `MD5`, `SMD5`, `PKCS5S2`, `CRYPT`, `PLAIN TEXT` which are detected automatically.

You can specify the attribute name where the password is stored:

```properties
ldap.password-comparison-authenticator.password-attribute-name=userPassword (1)
```

<table><tbody><tr><td><i class="conum" data-value="1"></i><b>1</b></td><td>The attribute name where the password is stored.</td></tr></tbody></table>

#### Using Bind Authentication

[Bind Authentication](https://ldap.com/the-ldap-bind-operation/) is the most common mechanism for authenticating users with LDAP. In bind authentication, the user’s credentials (username and password) are submitted to the LDAP server, which authenticates them. The advantage of using bind authentication is that the user’s secrets (the password) do not need to be exposed to clients, which helps protect them from leaking.

To enable this type of authentication, set this property:

```properties
ldap.bind-authenticator.enabled=true
```

## Authorities

According to the Governor’s [Roles and Permissions](https://docs.synthesized.io/tdk/latest/user_guide/050_deployment_operations/administration/roles_and_permissions) model, the user must have one of the following roles:

- MEMBER
- ADMINISTRATOR
- OWNER

The Governor’s LDAP supports one of two methods of fetching the authorities:

1. [In-house Authority Policy](#in_house_authority_policy)
2. [LDAP Authority Policy](#ldap_authority_policy)

### In-house Authority Policy

In this case, role management is controlled at the Governor side by the `OWNER` or `ADMINISTRATOR` role. The first user that signs up for the system is granted the `OWNER` role, and subsequent users are granted the `MEMBER` role.

### LDAP Authority Policy

In this case, role management is controlled at the LDAP Server side. You need to create Governor’s [Authorities](#authorities) in any case and specify the method of extraction. Let’s consider the following example:

```ldif
dn: cn=administrators,ou=groups,dc=synthesized,dc=io
objectclass: top
objectclass: groupOfUniqueNames
cn: administrators
ou: administrator
uniqueMember: uid=bob,ou=people,dc=synthesized,dc=io
```

To activate authority retrieval from LDAP, set the following property:

```properties
ldap.authorities.enabled=true
```

For a more customizable search, you can override the default properties:

```properties
ldap.authorities.group-search-base="ou=groups" (1)
ldap.authorities.group-role-attribute="cn" (2)
ldap.authorities.search-subtree=false (3)
ldap.authorities.group-user-search-filter=false (4)
ldap.authorities.ignore-partial-result-exception=false (5)
ldap.authorities.default-role=MEMBER (6)
```

<table><tbody><tr><td><i class="conum" data-value="1"></i><b>1</b></td><td>The LDAP search predicate for extracting groups.</td></tr><tr><td><i class="conum" data-value="2"></i><b>2</b></td><td>The ID of the attribute that contains the role name for a group.</td></tr><tr><td><i class="conum" data-value="3"></i><b>3</b></td><td>If set to true, a subtree scope search will be performed. If set to false, a single-level search is used. Setting to true enables searching the entire tree below the <code>group-search-base</code>.</td></tr><tr><td><i class="conum" data-value="4"></i><b>4</b></td><td>The pattern to be used for the user search. <code>{0}</code> represents the user’s DN.</td></tr><tr><td><i class="conum" data-value="5"></i><b>5</b></td><td>Sets the corresponding property on the underlying template, avoiding specific issues with Active Directory. A true value specifies whether <code>PartialResultException</code> should be ignored in searches. Refer to <a href="https://docs.spring.io/spring-ldap/site/apidocs/org/springframework/ldap/core/LdapTemplate.html#setIgnoreNameNotFoundException(boolean)">LdapTemplate.setIgnoreNameNotFoundException</a></td></tr><tr><td><i class="conum" data-value="6"></i><b>6</b></td><td>The role set when another role is not found.</td></tr></tbody></table>

> **NOTE**
> A user must be a member of only one Governor’s role.

In cases where you can’t create Governor’s roles, you can use role aliases from your group names:

```properties
ldap.authorities.role-aliases.operators=member
ldap.authorities.role-aliases.developers=member
ldap.authorities.role-aliases.<ldap_group_name>=member
```

## Active directory

Governor supports a specialized LDAP authentication provider that uses Active Directory configuration conventions. It authenticates using the Active Directory [User-Principal-Name attribute](https://msdn.microsoft.com/en-us/library/ms680857%28VS.85%29.aspx).

To configure this provider, you can use the following properties:

```properties
activedirectory.urls=ldap://localhost:389 (1)
activedirectory.domain=synthesized.io (2)
activedirectory.root-dn=dc=synthesized,dc=io (3)
activedirectory.authorities.enabled=false (4)
```

<table><tbody><tr><td><i class="conum" data-value="1"></i><b>1</b></td><td>The LDAP URL (or multiple URLs).</td></tr><tr><td><i class="conum" data-value="2"></i><b>2</b></td><td>The domain name (may be null or empty).</td></tr><tr><td><i class="conum" data-value="3"></i><b>3</b></td><td>The root DN (may be null or empty).</td></tr><tr><td><i class="conum" data-value="4"></i><b>4</b></td><td>If set to false, it will manage authorities on the Governor side.</td></tr></tbody></table>

> **NOTE**
> The `activedirectory.domain` will be used when `activedirectory.root-dn` is empty. In cases where `activedirectory.domain` is empty too, the search starts from the root.
