Non-ldap models getting access to LDAP model info in mixed authentication with multiple guards
rummanrc opened this issue · 3 comments
- Laravel Version: 8.15.0
- Adldap2-Laravel Version: 6.1.4
- PHP Version: 7.4.11
- LDAP Type: OpenLDAP
Description:
I have three separate guards: admin, employee and trainer. Admin and Trainer login using eloquent driver and uses 'admin' and 'trainer' guard respectively. Employees login using ldap driver and uses 'employee' guard.
I'm using jwt-auth library for token based authentication.
When I login as admin, I get a token. I can use that token to access admin info. And if I use the same token on Trainer routes, I don't get access to them (as expected).
However, if I use the admin token on an Employee route, I can access the employee's information with the same id as the admin (e.g admin with id 2 can access employee with id 2's info).
Similarly, Trainer can access Employee info when the id's match. Which is a security flaw.
This only occurs with LDAP. I've noticed that the employee guard, which was only supposed to work on employee routes, gets assigned to Admin and Trainer also. Thus Admin has both 'admin' and 'employee' guards available to him, therefore he's able to access employee info.
Steps To Reproduce:
- This repo's new_role_test_ldap branch contains all my code related to this issue.
https://github.com/rummanrc/laravelguardissue8/tree/new_role_test_ldap
- This is the env config for the publicly available LDAP server I'm using to test:
LDAP_CONNECTION=default
LDAP_BASE_DN='dc=example,dc=com'
LDAP_LOGGING=true
LDAP_HOSTS=ldap.forumsys.com
LDAP_PORT=389
LDAP_TIMEOUT=5
LDAP_SSL=false
LDAP_TLS=false
LDAP_USERNAME=cn=read-only-admin,dc=example,dc=com
LDAP_PASSWORD=password
-
Migrate and seed, then login as employee with any username and password from here https://www.forumsys.com/tutorials/integration-how-to/ldap/online-ldap-test-server/
Then login as admin or trainer. -
Use the admin token as Bearer Token and make a post request on http://localhost:8000/api/employee/me
and you'll see that the employee info is visible
It seems like for every Auth::attempt or Auth::guard()->attempt() the AdldapAuthServiceProvider class is being used, regardless of the guard. I don't know why it's passing through though, without credentials.
No matter which guard I use, the Adldap2's DatabaseUserProvider is getting used. I think that might be causing this conflict? If yes, can I bypass this so that the DatabaseUserProvider will be used based on my current guard (or request parameter, or anything)
So I had to override the Adldap2-laravel's DatabaseUserProvider class and put a condition on the retrieveById function.
I added custom claims in the tokens of my models, and checked for the custom claim (which contains the role) to decide whether to return the model from that function or not.
This branch contains the code for this solution: https://github.com/rummanrc/laravelguardissue8/tree/bypass_ldap_auto_login
Let me know if there's a better solution for this... and please provide the feature for eloquent and ldap based separate auth methods to work side by side, if possible...