sources/ldap: add ability to disable password write on login (#8377)
* sources/ldap: add ability to disable password write on login Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space> * reword docs Signed-off-by: Jens Langhammer <jens@goauthentik.io> --------- Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space> Signed-off-by: Jens Langhammer <jens@goauthentik.io> Co-authored-by: Jens Langhammer <jens@goauthentik.io>
This commit is contained in:
committed by
GitHub
parent
bf8c3078db
commit
06af8e3a35
@ -77,6 +77,7 @@ class LDAPSourceSerializer(SourceSerializer):
|
||||
"group_object_filter",
|
||||
"group_membership_field",
|
||||
"object_uniqueness_field",
|
||||
"password_login_update_internal_password",
|
||||
"sync_users",
|
||||
"sync_users_password",
|
||||
"sync_groups",
|
||||
@ -118,6 +119,7 @@ class LDAPSourceViewSet(UsedByMixin, ModelViewSet):
|
||||
"group_object_filter",
|
||||
"group_membership_field",
|
||||
"object_uniqueness_field",
|
||||
"password_login_update_internal_password",
|
||||
"sync_users",
|
||||
"sync_users_password",
|
||||
"sync_groups",
|
||||
|
||||
@ -41,6 +41,7 @@ class LDAPBackend(InbuiltBackend):
|
||||
# or has a password, but couldn't be authenticated by ModelBackend.
|
||||
# This means we check with a bind to see if the LDAP password has changed
|
||||
if self.auth_user_by_bind(source, user, password):
|
||||
if source.password_login_update_internal_password:
|
||||
# Password given successfully binds to LDAP, so we save it in our Database
|
||||
LOGGER.debug("Updating user's password in DB", user=user)
|
||||
user.set_password(password, signal=False)
|
||||
|
||||
@ -0,0 +1,29 @@
|
||||
# Generated by Django 5.0.1 on 2024-01-31 18:41
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("authentik_sources_ldap", "0003_ldapsource_client_certificate_ldapsource_sni_and_more"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name="ldapsource",
|
||||
name="password_login_update_internal_password",
|
||||
field=models.BooleanField(
|
||||
default=True,
|
||||
help_text="Update internal authentik password when login succeeds with LDAP",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="ldapsource",
|
||||
name="password_login_update_internal_password",
|
||||
field=models.BooleanField(
|
||||
default=False,
|
||||
help_text="Update internal authentik password when login succeeds with LDAP",
|
||||
),
|
||||
),
|
||||
]
|
||||
@ -98,6 +98,11 @@ class LDAPSource(Source):
|
||||
help_text=_("Property mappings used for group creation/updating."),
|
||||
)
|
||||
|
||||
password_login_update_internal_password = models.BooleanField(
|
||||
default=False,
|
||||
help_text=_("Update internal authentik password when login succeeds with LDAP"),
|
||||
)
|
||||
|
||||
sync_users = models.BooleanField(default=True)
|
||||
sync_users_password = models.BooleanField(
|
||||
default=True,
|
||||
|
||||
@ -4347,6 +4347,11 @@
|
||||
"title": "Object uniqueness field",
|
||||
"description": "Field which contains a unique Identifier."
|
||||
},
|
||||
"password_login_update_internal_password": {
|
||||
"type": "boolean",
|
||||
"title": "Password login update internal password",
|
||||
"description": "Update internal authentik password when login succeeds with LDAP"
|
||||
},
|
||||
"sync_users": {
|
||||
"type": "boolean",
|
||||
"title": "Sync users"
|
||||
|
||||
16
schema.yml
16
schema.yml
@ -19926,6 +19926,10 @@ paths:
|
||||
description: Number of results to return per page.
|
||||
schema:
|
||||
type: integer
|
||||
- in: query
|
||||
name: password_login_update_internal_password
|
||||
schema:
|
||||
type: boolean
|
||||
- in: query
|
||||
name: peer_certificate
|
||||
schema:
|
||||
@ -35225,6 +35229,10 @@ components:
|
||||
object_uniqueness_field:
|
||||
type: string
|
||||
description: Field which contains a unique Identifier.
|
||||
password_login_update_internal_password:
|
||||
type: boolean
|
||||
description: Update internal authentik password when login succeeds with
|
||||
LDAP
|
||||
sync_users:
|
||||
type: boolean
|
||||
sync_users_password:
|
||||
@ -35366,6 +35374,10 @@ components:
|
||||
type: string
|
||||
minLength: 1
|
||||
description: Field which contains a unique Identifier.
|
||||
password_login_update_internal_password:
|
||||
type: boolean
|
||||
description: Update internal authentik password when login succeeds with
|
||||
LDAP
|
||||
sync_users:
|
||||
type: boolean
|
||||
sync_users_password:
|
||||
@ -39440,6 +39452,10 @@ components:
|
||||
type: string
|
||||
minLength: 1
|
||||
description: Field which contains a unique Identifier.
|
||||
password_login_update_internal_password:
|
||||
type: boolean
|
||||
description: Update internal authentik password when login succeeds with
|
||||
LDAP
|
||||
sync_users:
|
||||
type: boolean
|
||||
sync_users_password:
|
||||
|
||||
@ -128,6 +128,7 @@ class TestSourceLDAPSamba(SeleniumTestCase):
|
||||
base_dn="dc=test,dc=goauthentik,dc=io",
|
||||
additional_user_dn="ou=users",
|
||||
additional_group_dn="ou=groups",
|
||||
password_login_update_internal_password=True,
|
||||
)
|
||||
source.property_mappings.set(
|
||||
LDAPPropertyMapping.objects.filter(
|
||||
|
||||
@ -86,6 +86,28 @@ export class LDAPSourceForm extends BaseSourceForm<LDAPSource> {
|
||||
<span class="pf-c-switch__label">${msg("Enabled")}</span>
|
||||
</label>
|
||||
</ak-form-element-horizontal>
|
||||
<ak-form-element-horizontal name="passwordLoginUpdateInternalPassword">
|
||||
<label class="pf-c-switch">
|
||||
<input
|
||||
class="pf-c-switch__input"
|
||||
type="checkbox"
|
||||
?checked=${first(this.instance?.passwordLoginUpdateInternalPassword, false)}
|
||||
/>
|
||||
<span class="pf-c-switch__toggle">
|
||||
<span class="pf-c-switch__toggle-icon">
|
||||
<i class="fas fa-check" aria-hidden="true"></i>
|
||||
</span>
|
||||
</span>
|
||||
<span class="pf-c-switch__label"
|
||||
>${msg("Update internal password on login")}</span
|
||||
>
|
||||
</label>
|
||||
<p class="pf-c-form__helper-text">
|
||||
${msg(
|
||||
"When the user logs in to authentik using this source password backend, update their credentials in authentik.",
|
||||
)}
|
||||
</p>
|
||||
</ak-form-element-horizontal>
|
||||
<ak-form-element-horizontal name="syncUsers">
|
||||
<label class="pf-c-switch">
|
||||
<input
|
||||
|
||||
@ -14,25 +14,25 @@ For Active Directory, follow the [Active Directory Integration](../active-direct
|
||||
For FreeIPA, follow the [FreeIPA Integration](../freeipa/)
|
||||
:::
|
||||
|
||||
- Server URI: URI to your LDAP server/Domain Controller.
|
||||
- **Server URI**: URI to your LDAP server/Domain Controller.
|
||||
|
||||
You can specify multiple servers by separating URIs with a comma, like `ldap://ldap1.company,ldap://ldap2.company`.
|
||||
|
||||
When using a DNS entry with multiple Records, authentik will select a random entry when first connecting.
|
||||
|
||||
- Bind CN: CN of the bind user. This can also be a UPN in the format of `user@domain.tld`.
|
||||
- Bind password: Password used during the bind process.
|
||||
- Enable StartTLS: Enables StartTLS functionality. To use LDAPS instead, use port `636`.
|
||||
- Base DN: Base DN used for all LDAP queries.
|
||||
- Addition User DN: Prepended to the base DN for user queries.
|
||||
- Addition Group DN: Prepended to the base DN for group queries.
|
||||
- User object filter: Consider objects matching this filter to be users.
|
||||
- Group object filter: Consider objects matching this filter to be groups.
|
||||
- User group membership field: This field contains the user's group memberships.
|
||||
- Object uniqueness field: This field contains a unique identifier.
|
||||
- Sync groups: Enable/disable group synchronization. Groups are synced in the background every 5 minutes.
|
||||
- Sync parent group: Optionally set this group as the parent group for all synced groups. An example use case of this would be to import Active Directory groups under a root `imported-from-ad` group.
|
||||
- Property mappings: Define which LDAP properties map to which authentik properties. The default set of property mappings is generated for Active Directory. See also [LDAP Property Mappings](../../../docs/property-mappings/#ldap-property-mapping)
|
||||
- **Bind CN**: CN of the bind user. This can also be a UPN in the format of `user@domain.tld`.
|
||||
- **Bind password**: Password used during the bind process.
|
||||
- **Enable StartTLS**: Enables StartTLS functionality. To use LDAPS instead, use port `636`.
|
||||
- **Base DN**: Base DN used for all LDAP queries.
|
||||
- **Addition User DN**: Prepended to the base DN for user queries.
|
||||
- **Addition Group DN**: Prepended to the base DN for group queries.
|
||||
- **User object filter**: Consider objects matching this filter to be users.
|
||||
- **Group object filter**: Consider objects matching this filter to be groups.
|
||||
- **User group membership field**: This field contains the user's group memberships.
|
||||
- **Object uniqueness field**: This field contains a unique identifier.
|
||||
- **Sync groups**: Enable/disable group synchronization. Groups are synced in the background every 5 minutes.
|
||||
- **Sync parent group**: Optionally set this group as the parent group for all synced groups. An example use case of this would be to import Active Directory groups under a root `imported-from-ad` group.
|
||||
- **Property mappings** and **Group Property Mappings**: Define which LDAP properties map to which authentik properties. The default set of property mappings is generated for Active Directory. See also [LDAP Property Mappings](../../../docs/property-mappings/#ldap-property-mapping)
|
||||
|
||||
## Property mappings
|
||||
|
||||
@ -42,6 +42,20 @@ By default, authentik ships with some pre-configured mappings for the most commo
|
||||
|
||||
You can assign the value of a mapping to any user attribute, or save it as a custom attribute by prefixing the object field with `attribute.` Keep in mind though, data types from the LDAP server will be carried over. This means that with some implementations, where fields are stored as array in LDAP, they will be saved as array in authentik. To prevent this, use the built-in `list_flatten` function.
|
||||
|
||||
## Password login
|
||||
|
||||
By default, authentik doesn't update the password it stores for a user when they log in using their LDAP credentials. That means that if the LDAP server is not reachable by authentik, users will not be able to log in. This behavior can be turned on with the **Update internal password on login** setting on the LDAP source.
|
||||
|
||||
:::note
|
||||
Sources created prior to the 2024.2 release have this setting turned on by default.
|
||||
:::
|
||||
|
||||
Be aware of the following security considerations when turning on this functionality:
|
||||
|
||||
- Updating the LDAP password does not invalid the password stored in authentik, however for LDAP Servers like FreeIPA and Active Directory, authentik will lock its internal password during the next LDAP sync. For other LDAP servers, the old passwords will still be valid indefinitely.
|
||||
- Logging in via LDAP credentials overwrites the password stored in authentik if users have different passwords in LDAP and authentik.
|
||||
- Custom security measures used to secure the password in LDAP may differ from the ones used in authentik. Depending on thread model and security requirements this could lead to unknowingly being non-compliant.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
To troubleshoot LDAP sources and their synchronization, see [LDAP Troubleshooting](../../../docs/troubleshooting/ldap_source)
|
||||
|
||||
Reference in New Issue
Block a user