Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

[Ldap] LDAP authentication should return a meaningful error when the LDAP server is unavailable#44898

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged
fabpot merged 1 commit intosymfony:6.1fromJayfrown:ldap-server-unavailable
Mar 29, 2022

Conversation

@Jayfrown
Copy link
Contributor

QA
Branch?6.1
Bug fix?no
New feature?yes
Deprecations?no
TicketsFix#44089
LicenseMIT

Return a 500 ISE if the LDAP server is unreachable.

I have tested the following scenarios:

LDAP server unreachable

Adapter/ExtLdap/Connection.php throws aConnectionException which is not caught, and this results in a 500 ISE shown to the user. In development mode, you see a relevant trace and the correct error hinting to an unreachable LDAP server, and in production mode this wouldn't be shown to the user, and would be logged.

LDAP server reachable, with invalid search bind credentials

TheLdapUserProvider tries to search the LDAP directory for the provided user. To search, it tries to authenticate using the (invalid) bind credentials, resulting inAdapter/ExtLdap/Connection.php throwing anInvalidCredentialsException which is not caught. As this is indicative of a misconfiguration within the application (ie. the app's search bind credentials are wrong, and searching for any user will always fail) I believe a 500 ISE is appropriate.

We could opt to catch theInvalidCredentialsException inside theLdapUserProvider and throw something more specific, to indicate it is the applications search bind credentials that are invalid, as opposed to the credentials the user provided during authentication.

LDAP server reachable, with valid search bind credentials, authenticating as an unknown user

As the search bind credentials are valid, theLdapUserProvider searches the LDAP directory, finds no entries, and throws aUserNotFoundException which results in the authenticator returning{"code":401,"message":"Invalid credentials."}. I believe this is good / expected behavior.

LDAP server reachable, with valid search bind credentials, using known user with invalid password

Theldap/Adapter/ExtLdap/Connection.php throws anInvalidCredentialsException. Theldap/Security/CheckLdapCredentialsListener.php now catches theInvalidCredentialsException (instead of theConnectionException) and throws aBadCredentialsException such that the authenticator returns{"code":401,"message":"Invalid credentials."}

LDAP server reachable, with valid search bind credentials, using known user with valid password

The credentials are validated and the user is logged in, everything works as expected


throw$e;
}
$this->ldap->bind($this->searchDn,$this->searchPassword);
Copy link
ContributorAuthor

@JayfrownJayfrownJan 3, 2022
edited
Loading

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

We could opt to catchInvalidCredentialsException here in order to throw something more-specific that would indicate it is the search bind credentials (used during enumeration) that are invalid, as opposed to the credentials that the user has provided.

Copy link
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Same inCheckLdapCredentialsListener.php line 77

Point being that throwing theInvalidCredentialsException can be ambiguous in either meaning "user-provided credentials are invalid" or "configured search credentials are invalid"

Copy link
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

7ab0611 introduces anInvalidSearchCredentialsException which is thrown when binding fails when using the configured search credentials.

@Jayfrown
Copy link
ContributorAuthor

Jayfrown commentedJan 3, 2022
edited
Loading

@wouterj FWIW, I have the following docker-compose setup for a local LDAP:

docker-compose.yml:
services:openldap:image:osixia/openldap:1.5.0restart:unless-stoppedenvironment:LDAP_LOG_LEVEL:"256"LDAP_ORGANISATION:${LDAP_ORGANISATION:-Example Inc.}LDAP_DOMAIN:${LDAP_DOMAIN:-example.org}LDAP_BASE_DN:${LDAP_BASE_DN:-"dc=example,dc=org"}LDAP_ADMIN_PASSWORD:${LDAP_ADMIN_PASSWORD:-admin}LDAP_CONFIG_PASSWORD:${LDAP_CONFIG_PASSWORD:-config}LDAP_RFC2307BIS_SCHEMA:"false"LDAP_BACKEND:"mdb"LDAP_TLS:"true"LDAP_TLS_CRT_FILENAME:"ldap.crt"LDAP_TLS_KEY_FILENAME:"ldap.key"LDAP_TLS_DH_PARAM_FILENAME:"dhparam.pem"LDAP_TLS_CA_CRT_FILENAME:"ca.crt"LDAP_TLS_ENFORCE:"false"LDAP_TLS_CIPHER_SUITE:"SECURE256:-VERS-SSL3.0"LDAP_TLS_VERIFY_CLIENT:"demand"LDAP_REPLICATION:"false"KEEP_EXISTING_CONFIG:"false"LDAP_REMOVE_CONFIG_AFTER_SETUP:"true"LDAP_SSL_HELPER_PREFIX:"ldap"tty:truestdin_open:truevolumes:      -ldap_data:/var/lib/ldap      -ldap_config:/etc/ldap/slapd.d      -ldap_certs:/container/service/slapd/assets/certs/ports:      -"389:389"      -"636:636"phpldapadmin:image:osixia/phpldapadmin:latestenvironment:PHPLDAPADMIN_LDAP_HOSTS:"openldap"PHPLDAPADMIN_HTTPS:"false"ports:      -"8080:80"depends_on:      -openldapvolumes:ldap_data:ldap_config:ldap_certs:

And the following configuration in Symfony:

services.yaml:
Symfony\Component\Ldap\Ldap:arguments:['@Symfony\Component\Ldap\Adapter\ExtLdap\Adapter']tags:['ldap']Symfony\Component\Ldap\Adapter\ExtLdap\Adapter:arguments:            -host:'%env(resolve:LDAP_HOST)%'port:'%env(resolve:LDAP_PORT)%'encryption:'%env(resolve:LDAP_ENCRYPTION)%'options:protocol_version:3referrals:false
security.yaml:
providers:app_ldap:ldap:service:Symfony\Component\Ldap\Ldapbase_dn:'%env(resolve:LDAP_BASE_DN)%'search_dn:'%env(resolve:LDAP_SEARCH_DN)%'search_password:'%env(resolve:LDAP_SEARCH_PASSWORD)%'default_roles:ROLE_USERuid_key:uidfirewalls:main:provider:app_ldap
.env:
LDAP_HOST="openldap"LDAP_PORT="389"LDAP_ENCRYPTION="none"LDAP_SEARCH_DN="cn=admin,dc=example,dc=org"LDAP_SEARCH_PASSWORD="admin"LDAP_BASE_DN="ou=Users,dc=example,dc=org"

You'd have to create the rest of the schema by hand, if needed I can try to provide an LDIF.

@NyholmNyholm added the Ldap labelJan 4, 2022
@carsonbotcarsonbot changed the titleLDAP authentication should return a meaningful error when the LDAP server is unavailable[Ldap] LDAP authentication should return a meaningful error when the LDAP server is unavailableJan 4, 2022
@carsonbot
Copy link

Hey!

I think@karlshea has recently worked with this code. Maybe they can help review this?

Cheers!

Carsonbot

@Jayfrown
Copy link
ContributorAuthor

@wouterj if there's anything I can do to make reviewing easier, let me know

@stof
Copy link
Member

CheckLdapCredentialsListener has 2 modes. Your PR description lets me think that you tested only one of them.

@JayfrownJayfrownforce-pushed theldap-server-unavailable branch fromec7a0be to58716bbCompareMarch 22, 2022 19:07
@Jayfrown
Copy link
ContributorAuthor

CheckLdapCredentialsListener has 2 modes. Your PR description lets me think that you tested only one of them.

@stof Thanks. It is very possible I might have missed something, as I'm not familiar with the two modes you mention. Could you expand on this or send some documentation my way?

@stof
Copy link
Member

I'm not familiar with the ldap part either. But for those 2 modes, see the if/else inside the try/catch you changed

@Jayfrown
Copy link
ContributorAuthor

@stof Thanks. If I understand correctly the difference is whenquery_string is set, which, according to the documentation:

makes the user provider search for a user and then use the found DN for the bind process

Basically allowing the LDAP component to search for a given user in multiple OUs instead of simply interpolating the username into thedn_string.

Expand default behavior
  • Interpolate the user-provided username in thedn_string, eg.uid={username},dc=example,dc=com becomesuid=jayfrown,dc=example,dc=com
  • Use the user-provided password to bind as the interpolateddn_string
    • If the bind is successful, the credentials are accepted and log-in continues
    • If the bind is not successful, the credentials are rejected and log-in is prohibited
Expand query_string behavior
  • Interpolate the user-provided username in thequery_string, eg.(&(uid={username})) becomes(&(uid=jayfrown))
  • Bind with the configured search credentials
  • Perform an LDAP search inside thedn_string using thequery_string, eg. ifdn_string isdc=example,dc=com, this can returnuid=jayfrown,dc=companyA,dc=example,dc=com oruid=jayfrown,dc=companyB,dc=example,dc=com, etc.
    • If the search does not yield exactly one result, throw aBadCredentialsException indicating that the user-provided username is invalid
    • If the search yields exactly one result, use the user-provided password to bind as the found DN
      • If the bind is successful, the credentials are accepted and log-in continues
      • If the bind is not successful, the credentials are rejected and log-in is prohibited

Having said all that, my changes should not impact either scenario apart from what I've already described. However, when I have some more time I will set up a configuration usingquery_string and test with that as well.

@JayfrownJayfrownforce-pushed theldap-server-unavailable branch from58716bb to8452c7aCompareMarch 22, 2022 21:07
Jayfrown added a commit to Jayfrown/ldap that referenced this pull requestMar 23, 2022
Jayfrown added a commit to Jayfrown/symfony-ldap-example that referenced this pull requestMar 23, 2022
Jayfrown added a commit to Jayfrown/symfony-ldap-example that referenced this pull requestMar 23, 2022
@Jayfrown
Copy link
ContributorAuthor

I made anexample application to make it easier to test and verify behavior. The repository includes a docker-compose configuration that spins up an OpenLDAP container, seeds it with some users, and exposes the ports such that the local application can communicate with it.

There are a couple of branches to test all permutations (with/withoutquery_string as well as with/without this PR applied)

Branches with this PR applied requireJayfrown/ldap dev-ldap-server-unavailable which is a clone of thesymfony/ldap repository which includes the work in this PR.

Note that after switching to/from branches with this PR applied it is necessary to runcomposer install.


@stof I've tested the same scenarios as mentioned in the OP with thequery_string configuration and the behavior remains the same.

@JayfrownJayfrownforce-pushed theldap-server-unavailable branch from65aaf0c to7ab0611CompareMarch 23, 2022 02:31
@fabpotfabpotforce-pushed theldap-server-unavailable branch from7ab0611 toad2cc0eCompareMarch 29, 2022 06:21
@fabpot
Copy link
Member

Thank you@Jayfrown.

Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment

Reviewers

@stofstofstof left review comments

@fabpotfabpotfabpot approved these changes

@nicolas-grekasnicolas-grekasnicolas-grekas approved these changes

@chalasrchalasrAwaiting requested review from chalasrchalasr is a code owner

@wouterjwouterjAwaiting requested review from wouterjwouterj is a code owner

Assignees

No one assigned

Projects

None yet

Milestone

6.1

Development

Successfully merging this pull request may close these issues.

LDAP authentication should return a meaningful error when the LDAP server is unavailable

6 participants

@Jayfrown@carsonbot@stof@fabpot@nicolas-grekas@Nyholm

[8]ページ先頭

©2009-2025 Movatter.jp