# LDAP Inbound Security Module

The LDAP Inbound Security module can be used to delegate authentication decisions to an external user directory – such as a Microsoft Active Directory server or an OpenLDAP directory.

Unlike the [Local Inbound Security](/content/docs/security/local_inbound_security_module.html) module, the LDAP Inbound Security module authenticates against an external directory, and it does not store any passwords in the Smile CDR database.

This type of authentication is useful when deploying Smile CDR in an enterprise context since many organizations have a corporate user directory that allows users to use the same credentials across multiple servers.

Note that each user account that is successfully authenticated by the LDAP server will have a corresponding entry created in the Smile CDR User Database. This locally stored account will not store credentials and cannot be used directly for authentication but it is needed in order to provide a reference point for audit log entries, etc.

**Note:**

When configuring the [BaseDN for Groups](/content/docs/configuration_categories/ldap_authentication.html#property-base-dn-for-groups/index.html) property of the LDAP Inbound Security Module, point it at a small subset of the tree within the LDAP, and not at the root of the entire LDAP tree, or there could be performance problems. For example, if you know that there will only be 3 users who might need access to administer your Smile CDR deployment, then create a separate LDAP Group, add them to that Group, and point the BaseDN to that small LDAP subtree.

# Requirements

In order to connect to an LDAP server, Smile CDR requires [credentials](/content/docs/configuration_categories/ldap_authentication.html#property-system-user-dn/index.html) for a system account in the server that it will use to locate accounts, look up groups, etc.

## Mandatory Group

If only a subset of users in the LDAP server should have access to Smile CDR, you may wish to create a group in the directory for this purpose, and add all relevant users to this group. The CN for this group should then be listed in the [`authenticator.require_group_membership.dn`](/content/docs/configuration_categories/ldap_authentication.html#property-require-group-dn/index.html) configuration property.

In this scenario, any user who is not a member of the given group will not be permitted to authenticate via this module even if they supply correct credentials.

This feature is limited to static groups defined by a `member` attribute.

## LDAP Groups

LDAP groups define a collection of members (users, machines, etc.)
The LDAP Inbound Security Module can use group membership to restrict access, or define permissions.
LDAP groups can be static or dynamic.
Querying group membership depends on the type of group, and the LDAP server configuration.

**Static Groups**

Static groups (e.g. groupOfNames, groupOfUniqueNames, Group) are defined by a member attribute which lists the DNs of the member.
This member attribute is commonly `member` but can be `uniqueMember` or otherwise, depending on the configuration of the LDAP server.
Group membership can be queried using a simple filter, e.g. `(member=dn-of-the-user)`.
This query is exposed as `isMemberOfGroup()` in  [SecurityInLdapAuthenticationContext](/content/docs/javascript_execution_environment/callback_models.html#securityinldapauthenticationcontext/index.html) which uses `member` as the default attribute name, but allows other values.
The server may be configured to generate a corresponding `memberOf` backlink on the user entry as a dynamic attribute.

**Dynamic Groups**

Dynamic LDAP groups define membership by a query expression instead of a concrete list of members.
E.g. objectClass:groupOfUrls are configured by the memberURL (or MemberQueryURL, memberQuery) attribute which contains an LDAP query string.
Since the group does not contain an explicit member attribute, the simple static query will not work.
To query membership in a dynamic group, the server computes dynamic/operational attributes on the member entries.
These attributes (e.g. `memberOf` or `isMemberOf`) may not be present by default.
In that case, they must be explicitly requested. The list of attributes requested can be configured using  [user Attributes to query](/content/docs/configuration_categories/ldap_authentication.html#property-authentication-user-attributes-to-query/index.html).
By default, this is empty which will include all static attributes.
Alternatively, a dynamic attribute can be queried using `queryStringAttributes()` in [SecurityInLdapAuthenticationContext](/content/docs/javascript_execution_environment/callback_models.html#securityinldapauthenticationcontext/index.html) during the `onAuthenticateSuccess()` callback.

# Permissions

In most cases, simply authenticating is not sufficient to provide useful functionality. A user also requires permissions in order to perform actions within Smile CDR.

There are several ways that a user can be granted permissions:

- **Global Permissions** – Any permissions configured as [global permissions](/content/docs/configuration_categories/ldap_authentication.html#property-global-permissions/index.html) will be automatically granted to any users who authenticate via this module.
- **Native Permissions** – An LDAP user attribute may be declared in Smile CDR configuration to be a [native permission user attribute](/content/docs/configuration_categories/ldap_authentication.html#property-native-permission-user-attribute/index.html). With this setting, values in this attribute will be treated as Smile CDR permissions that should be granted to that user. For example, if the `smileCdrPermission` LDAP attribute is configured as a native permission attribute and a user in the LDAP server has a `smileCdrPermission` attribute with a value of `FHIR_ALL_READ`, that user will be granted the `FHIR_ALL_READ` permission.
- **Local Permissions** – After a user has successfully authenticated at least once, they will have an entry in the Smile CDR User Database. Permissions may be directly assigned to the user via the Web Admin Console or the JSON Admin API [User Management Endpoint](/content/docs/json_admin_endpoints/user_management_endpoint.html).
- **Callback Permissions** – After a user has successfully authenticated the `onAuthenticateSuccess()` callback (see below) can be used to transform LDAP data into additional permissions.

# Callback Scripts

When using an LDAP directory to perform user authentication, in a real-world scenario you will likely have a mapping of LDAP group memberships and/or user attributes to Smile CDR permissions.

For example, you might have a group in your LDAP for administrative superusers, and another group for FHIR Clients. Users who sign in with an account that is a member of the first group might be assigned one set of Smile CDR permissions, while other users who sign in with the second group would get different Smile CDR permissions.

The Smile CDR [Authentication Callback Scripts](/content/docs/security/callback_scripts.html) functionality can be used to programmatically supply these mappings.

## Function: onAuthenticateSuccess(theOutcome, theOutcomeFactory, theContext)

This function is called after the user has successfully authenticated against the LDAP directory (i.e. the credentials have been confirmed to be correct) but before Smile CDR has created a user session. The function can enhance the session (e.g. by adding authorities) or can even abort it.

**Parameters**

- **theOutcome** – This parameter is of type  [UserSessionDetails](/content/docs/javascript_execution_environment/callback_models.html#usersessiondetails/index.html). It will be pre-populated by the module with basic demographic details pulled from the authenticated user's LDAP entry, but may have no assigned authorities by default. The script will likely want to add some.

- **theOutcomeFactory** – This parameter is of type [ScriptAuthenticationOutcomeFactory](/content/docs/javascript_execution_environment/callback_models.html#scriptauthenticationoutcomefactory/index.html). This parameter can be used to create a failure object if you wish to abort the login from your script.

- **theContext** – This parameter is of type [SecurityInLdapAuthenticationContext](/content/docs/javascript_execution_environment/callback_models.html#securityinldapauthenticationcontext/index.html). It can be used to query the LDAP directory for details about the authenticated user.

**Example**

```javascript
function onAuthenticateSuccess(theOutcome, theOutcomeFactory, theContext) {

// Grant authorities based on whether the user has a specific attribute
   if (theContext.getStringAttributes("adminUser").includes("true")) {
      theOutcome.addAuthority('FHIR_ALL_READ');
      theOutcome.addAuthority('FHIR_ALL_WRITE');
   }

// Grant authorities based on group membership
   if (theContext.isMemberOfGroup("DC=FHIR-Admins,OU=Groups,O=example.com")) {
      theOutcome.addAuthority('ROLE_FHIR_CLIENT_SUPERUSER');
   }

// Grant authorities based on group membership using different membership attribute
   if (theContext.isMemberOfGroup("DC=Other-Group,OU=Groups,O=example.com", 'uniqueMember')) {
      theOutcome.addAuthority('ROLE_FHIR_CLIENT_SUPERUSER');
   }

// Grant authorities my querying for membership in a dynamic group.
   if (theContext.queryStringAttributes('isMemberOf').contains('DC=Dynamic-Group,OU=Groups,O=example.com')) {
      theOutcome.addAuthority('ROLE_FHIR_CLIENT_SUPERUSER');
   }

return theOutcome;
}
```

Copy

# Configuration

A complete reference of configuration items follows:

- [Authentication Callback Scripts](/content/docs/configuration_categories/auth_callback_scripts.html)

- [Credentials](/content/docs/configuration_categories/credentials.html)

- [JavaScript Execution Environment](/content/docs/configuration_categories/javascript_execution_environment.html)

- [LDAP Authentication](/content/docs/configuration_categories/ldap_authentication.html)

- [Two Factor Authentication](/content/docs/configuration_categories/tfa_security_settings.html)

[Local Inbound Security Module](/content/docs/security/local_inbound_security_module.html)

LDAP Inbound Security Module

Security

[Authentication Protocols](/content/docs/security/authentication_protocols.html)
[Authorization and Consent](/content/docs/security/authorization_and_consent.html)
[Inbound Security Module](/content/docs/security/inbound_security_module.html)
[Local Inbound Security Module](/content/docs/security/local_inbound_security_module.html)
[LDAP Inbound Security Module](/content/docs/security/ldap_inbound_security_module.html)
[Scripted Inbound Security Module](/content/docs/security/script_inbound_security_module.html)
[SAML Inbound Security Module](/content/docs/security/saml_inbound_security_module.html)
[Trusted Client Mode](/content/docs/security/trusted_client_mode.html)
[Roles and Permissions](/content/docs/security/roles_and_permissions.html)
[Callback Scripts](/content/docs/security/callback_scripts.html)
[Anonymous Access](/content/docs/security/anonymous_access.html)
[Consent Service](/content/docs/security/consent_service.html)
[Consent Service: JavaScript API](/content/docs/security/consent_service_javascript.html)
[Consent Service: Java API](/content/docs/security/consent_service_java.html)
[Security Recipes](/content/docs/security/security_recipes.html)
[Two Factor Authentication](/content/docs/security/two_factor_auth.html)
[Password Hashing Algorithms](/content/docs/security/password_hashing_algorithms.html)
[JWT Signature Algorithms](/content/docs/security/jwt_signature_algorithms.html)
[Troubleshooting Security](/content/docs/security/troubleshooting_security.html)

[Scripted Inbound Security Module](/content/docs/security/script_inbound_security_module.html)
