Skip to content
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

Question: why is the password for an LDAP enabled account stored in MongoDB? #6144

Closed
TwizzyDizzy opened this issue Feb 23, 2017 · 23 comments · Fixed by #16949
Closed

Question: why is the password for an LDAP enabled account stored in MongoDB? #6144

TwizzyDizzy opened this issue Feb 23, 2017 · 23 comments · Fixed by #16949

Comments

@TwizzyDizzy
Copy link

Rocket.Chat Version: 0.52.0
Running Instances: 1
DB Replicaset OpLog: -
Node Version: v4.8.0

Hi folks,

I was wondering why we need to store the password in MongoDB, when a user is an LDAP-flagged user? Is the password that is stored in MongoDB even the real user password or some bogus string?

One would expect the authentication to go against the LDAP server and not against MongoDB. I think it's the case actually, but I don't see the reason for storing it in MongoDB.

Cheers
Thomas

@TwizzyDizzy TwizzyDizzy changed the title Question: why is the password stored in MongoDB for an LDAP enabled account Question: why is the password for an LDAP enabled account stored in MongoDB? Feb 23, 2017
@Rohlik
Copy link
Contributor

Rohlik commented Feb 23, 2017

LDAP settings in Rocket.Chat have option Login Fallback - If the login on LDAP is not successful try to login in default/local account system. Helps when the LDAP is down for some reason.
I think that is the reason why is password stored in MongoDB.

@TwizzyDizzy
Copy link
Author

TwizzyDizzy commented Feb 24, 2017

Hi @Rohlik,

thanks for your answer! :) Unfortunately, the passwords are also saved on importing new users (from LDAP) when this checkbox (fallback login) is set to false. I tested this as follows:

I deleted the user from Rocket.Chat and disabled the fallback login thereafter, logged in again as the user that has been deleted before and, again, the (hashed) password has been stored on importing the user from LDAP.

Cheers
Thomas

@localguru
Copy link
Contributor

localguru commented Feb 26, 2017

Hi,

I had the same thoughts when testing LDAP today. I was wondering that I was able to login with a user account, which was already removed from AD. The LDAP/AD passwords are stored in db.users. Run a db.users.find() and you can see the encrypted passwords. To my mind the passwords shouldn't be stored if LDAP_Login_Fallback is set to false, just for security reasons. If LDAP fails for some reasons one should be able to login with a local admin account. That should be sufficient to make changes on rocket.chat side. If the LDAP itself is the problem, rocket.chat users have to wait until it's fixed. ;)

But the important security problem is, that an user, which is removed from LDAP/AD, is able to login as long as LDAP_Login_Fallback is not set to "false", in other words: forever. Are there any automatically scripts to remove non existent LDAP/AD users from rocket.chat?

Ciao
Marcus

@rodrigok
Copy link
Member

rodrigok commented Mar 2, 2017

Hi @TwizzyDizzy

Yes, Rocket.Chat stores the user's password encrypted when the user does the login. That is only for fallback purpose. You can enable or disable the fallback, but it will store the password always if you decide to enable the fallback.

@photoninger
Copy link

After reading this issue, I disabled the fallback and after that my only admin user which is a local non-ldap user couldn't login anymore.
Fortunately I found the instructions to give one of my LDAP-Users admin role directly in mongodb to get a working admin account.
It would be nice if you could mix local and LDAP users without storing the LDAP users' passwords in mongodb.

@rodrigok
Copy link
Member

rodrigok commented Mar 2, 2017

Why you don't want the fallback enabled?

@photoninger
Copy link

photoninger commented Mar 2, 2017

Because of

But the important security problem is, that an user, which is removed from LDAP/AD, is able to login as long as LDAP_Login_Fallback is not set to "false", in other words: forever. Are there any automatically scripts to remove non existent LDAP/AD users from rocket.chat?

or is this wrong?

@localguru
Copy link
Contributor

localguru commented Mar 2, 2017

To my mind storing password locally of a central login point like LDAP is a security risk. One uses LDAP because of not keeping any passwords. There should be an option to disable keeping passwords locally of LDAP users. Passwords of local users with admin role can be stored to have fallback admin accounts.

@TwizzyDizzy
Copy link
Author

TwizzyDizzy commented Mar 7, 2017

So might I summarize what has been said so far and seems to be agreed upon:

  • We do NOT want passwords to be saved in MongoDB when LDAP is enabled (this might be made into an option in the backend, if not, they should not be saved by default)
    • unless fallback-login is activated
    • this means the passwords need to be erased (for LDAP-flagged accounts) on disabling fallback login and stored on next login, when this feature is enabled
  • We DO want local accounts to be able to log in when LDAP is down or disabled in ANY case.

I just did a matrix of how the behaviour on my Rocket.Chat instance (Version: 0.53.0) is (red = login NOT possible, green = login possible):

screen_ldap

At least the combination

local user + LDAP enabled + Fallback disabled = login NOT possible

is - in my opinion - an erroneous behaviour.

Cheers so far
Thomas

@TwizzyDizzy
Copy link
Author

Alright, let's get things straight: We do now have a fix for

We do NOT want passwords to be saved in MongoDB when LDAP is enabled (this might be made into an option in the backend, if not, they should not be saved by default)
unless fallback-login is activated
this means the passwords need to be erased (for LDAP-flagged accounts) on disabling fallback login and stored on next login, when this feature is enabled

But it's still a problem, that a local admin account is not able to log in if "LDAP enabled + Fallback disabled".

Cheers
Thomas

@localguru
Copy link
Contributor

@TwizzyDizzy what a about a secret login URL for local accounts, like possible for registration? This would be helpful in case of SAML too, where the local login mask is completely disabled.

@TwizzyDizzy
Copy link
Author

TwizzyDizzy commented Jun 22, 2017

Actually, I see no reason why there should be any hidden login-form. The key part is, that the backend works as expected...

The code behind the login has to check

  • is the user that is trying to login a local account or an LDAP account or, if that's not possible somehow:
  • first: try to authenticate against local user database
  • if that fails: try to authenticate against LDAP
  • if that fails, too: deny login.

Cheers
Thomas

@localguru
Copy link
Contributor

@TwizzyDizzy are you sure that there is a difference between a LDAP user and a local user? To my mind your "first" option will always be true, even if it's a LDAP user. That's why ldap fallback is working.

@TwizzyDizzy
Copy link
Author

Mhhh. I haven't actually had a look into the MongoDB but read in some other issue here on Github, that they are flagged as "LDAP users" or "Imported from LDAP". Otherwise, how would you try to authenticate against which backend, if you don't know what kind of user this is. You would have to start at step 2 (above) anyway.

You're right, in that my first step is not well written: I meant: "try to determine what kind of account this is and by that, find out what backend to authenticate against".

Cheers
Thomas

@mddvul22
Copy link

mddvul22 commented Jul 12, 2017

But it's still a problem, that a local admin account is not able to log in if "LDAP enabled + Fallback
disabled".

+1

@TwizzyDizzy
Copy link
Author

@TwizzyDizzy are you sure that there is a difference between a LDAP user and a local user? To my mind your "first" option will always be true, even if it's a LDAP user. That's why ldap fallback is working.

I just looked that up - see the following screenshot for the difference... Admin is, of course, a local account, but the account with the ID mFFfETbmt3gxcFk2G is an LDAP account and "flagged" as such. Also you can see the bcrypt hash of the password.

image

@AmShaegar13
Copy link
Contributor

AmShaegar13 commented Nov 3, 2017

API login is not possible with LDAP. Thus, you need the stored password to use the API. On the other hand, the password is never updated if the password in LDAP is changed. With login fallback ON, you have two valid passwords for the UI then.

@TwizzyDizzy
Copy link
Author

API login is not possible with LDAP.

Erm... what? Why? I would've assumed that both actions (login via web UI + login via API) would trigger the same passages of code.

On the other hand, the password is never updated if the password in LDAP is changed.

... which is even worse ...

It seems as though it seems to be a bit harder to solve this issue than I initially thought. I think this issue needs somebody from the Rocket.Chat team who has insight into all of API, LDAP / storing of passwords then...

Cheers
Thomas

@gregs007
Copy link

gregs007 commented Nov 3, 2017

This discussion is way off topic now, but there's a lot of confusion here so let me see if I can help.

API use is possible with any auth method. Using any API method only involves making sure you pass a valid auth token. The problem with the REST API is that the login method (i.e. the call you make to actually get that token) only supports username and password-- and though I haven't looked at the code it probably can only use the local mongo database. So programmatic API logins are POSSIBLE, just not easily done via the REST API in rocketchat becuase there's no login method for SAML/Oauth etc that will return a valid token. Again... All you need is a token... You get the token whenever you login via any method (SAML/Oauth, etc). Just thought I should clear that up.

Probably what we need is an improvement or addition to the login methods for REST API that will allow us to specify a SAML IDP or Oauth parameters or whatever people want to use. It's either that or use external libraries to login to rocketchat and capture that token and then go do your business via the native REST API.

@objarni
Copy link

objarni commented Sep 27, 2018

My opinion: Rocket chat should not store LDAP p/w (hashed or not) locally in MongoDB by default.

There could arguably be a configuration option to do so, but that is something you do to break out of the default behavior, on your own.

Even worse, if the "Fallback" is turned off, it seems R.C is still behaving like this?

@mtozlu
Copy link

mtozlu commented Nov 1, 2018

I think it is very basic concept.
An account has a "authentication system" property. If authentication system is LDAP; Rocket should authenticate against specific LDAP server. If authenticaton system is Local; Rocket should authenticate against its own mechanism.

If "authentication system" property of a user is set to LDAP, Rocket should not keep passwords in the db.

That's it.

Now;
1- There is no need for a "Fallback" mechanism which is not a standard in both security or web application designing aspects.
2- There could be multiple authentication types. (Multiple LDAP servers, Internal Authentication, Twitter, etc.) Each user can have their authentication property to any of the authentication types (User A is authenticated against LDAP Server A, User B is authenticated against LDAP Server B, User C is authenticated against internal password, etc.)

@scratttt
Copy link

I think that this request is the same that #4554.

@TwizzyDizzy
Copy link
Author

TwizzyDizzy commented May 4, 2020

Just wanted to leave this here: since at least Rocket.Chat 3.2.1, cell C2 in the image in comment #6144 (comment) is now also green, meaning that login of local users is now possible with disabled login fallback.

Cheers & Thanks
Thomas

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.