Skip to content

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

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 our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from

Conversation

Jayfrown
Copy link
Contributor

@Jayfrown Jayfrown commented Jan 3, 2022

Q A
Branch? 5.3 (?)
Bug fix? no (?)
New feature? no (?)
Deprecations? no
Tickets Fix #44089
License MIT

Return a 500 ISE if the LDAP server is unreachable.

Not sure if this is seen as a "bug fix" or a "new feature", or neither. It's not a bug per se, but it feels like wrong behavior to state that credentials are invalid if the LDAP server is unreachable.

I have tested the following scenarios:

LDAP server unreachable

Adapter/ExtLdap/Connection.php throws a ConnectionException 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

The LdapUserProvider tries to search the LDAP directory for the provided user. To search, it tries to authenticate using the (invalid) bind credentials, resulting in Adapter/ExtLdap/Connection.php throwing an InvalidCredentialsException 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 the InvalidCredentialsException inside the LdapUserProvider 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, the LdapUserProvider searches the LDAP directory, finds no entries, and throws a UserNotFoundException 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

The ldap/Adapter/ExtLdap/Connection.php throws an InvalidCredentialsException. The ldap/Security/CheckLdapCredentialsListener.php now catches the InvalidCredentialsException (instead of the ConnectionException) and throws a BadCredentialsException 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

- No longer catch ConnectionException so that it will result in a 500
  ISE

- Catch the InvalidCredentialsException so we can still throw a
  BadCredentialsException if the provided credentials are known to be
  invalid

ref: symfony#44089
- No longer catch ConnectionException so that it will result in a 500
  ISE

- Expect a ConnectionException instead of a UserNotFoundException if the
  LDAP server is unreachable

ref: symfony#44089
@carsonbot carsonbot added this to the 5.3 milestone Jan 3, 2022
@carsonbot
Copy link

Hey!

I see that this is your first PR. That is great! Welcome!

Symfony has a contribution guide which I suggest you to read.

In short:

  • Always add tests
  • Keep backward compatibility (see https://symfony.com/bc).
  • Bug fixes must be submitted against the lowest maintained branch where they apply (see https://symfony.com/releases)
  • Features and deprecations must be submitted against the 6.1 branch.

Review the GitHub status checks of your pull request and try to solve the reported issues. If some tests are failing, try to see if they are failing because of this change.

When two Symfony core team members approve this change, it will be merged and you will become an official Symfony contributor!
If this PR is merged in a lower version branch, it will be merged up to all maintained branches within a few days.

I am going to sit back now and wait for the reviews.

Cheers!

Carsonbot

@Jayfrown Jayfrown changed the title 5.3 LDAP authentication should return a meaningful error when the LDAP server is unavailable Jan 3, 2022

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

Choose a reason for hiding this comment

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

We could opt to catch InvalidCredentialsException 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.

@wouterj
Copy link
Member

wouterj commented Jan 3, 2022

Thanks for your investigation on this issue and potential fix, @Jayfrown! I'll try to set-up a test LDAP docker container to experiment with the changes in this PR (probably on Wednesday). For now, to answer your question:

Not sure if this is seen as a "bug fix" or a "new feature", or neither. It's not a bug per se, but it feels like wrong behavior to state that credentials are invalid if the LDAP server is unreachable.

Generally, we want to be very stable with released versions. Expected wrong behavior is often better than unexpected errors. So when in doubt, we tend to lean on the safe side and call "distinguishing connection errors from invalid password errors" a feature (thus 6.1).

Generally, you should be able to use git rebase --onto origin/6.1 origin/5.3 to rebase the current branch (and thus PR) onto the other version. However, I see that you didn't create a specific branch for this PR, which means you loose a correct 5.3 when doing this. It might be better to close this PR and create a new one, this time with a specific branch (as outlined in the contributing guide).

# create a new branch named "ldap-server-unavailable", based on 6.1
git checkout -b ldap-server-unavailable upstream/6.1

# cherry pick the 2 commits of this PR in the new branch (and maybe resolve some conflicts)
git cherry-pick 88049260a72b632d6673fe02877ed807e1b012c5 c59fe19803b462d37cab386af8077a2dbac70dc0

# push the new branch to your fork (& then create a new PR with this branch on 6.1)
git push origin

@Jayfrown
Copy link
Contributor Author

Jayfrown commented Jan 3, 2022

Thanks @wouterj, closing this in favor of #44898

@Jayfrown Jayfrown closed this Jan 3, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants