web2py / py4web

Other
263 stars 129 forks source link

problems with ldap #29

Closed advh67 closed 3 years ago

advh67 commented 5 years ago

I created a new py4web app using the dashboard. The scaffold template created the skeleton of the new app. Ok.

In the file settings.py, line 33, says: LDAP_SETTING={ It would must be: LDAP_SETTINGS={

Corrected this mispelling, the next error: File "/home/advh67/py4web/apps/mynewapp/common.py", line 47, in auth.register_plugin(LDAPPlugin(**LDAP_SETTINGS)) NameError: name 'LDAP_SETTINGS' is not defined

would must be(?): auth.register_plugin(LDAPPlugin(**settings.LDAP_SETTINGS))

Once corrected, the initialization fails again:

File "/home/advh67/py4web/apps/mynewapp/common.py", line 47, in auth.register_plugin(LDAPPlugin(**settings.LDAP_SETTINGS)) File "/usr/lib/python3.7/site-packages/py4web/utils/auth.py", line 106, in register_plugin self.plugins[plugin.name] = plugin AttributeError: 'LDAPPlugin' object has no attribute 'name'

I am stuck.

Py4web was installed using: python3 -m pip install --upgrade py4web an launched by typing: py4web-start apps as told in documentation.

My folder /home/advh67/py4web is empty of files. It only contains the apps folder.

mdipierro commented 5 years ago

Can you try again. Cannot promise is fixed. Do not have an easy way to fix but I will help debug. I want this to work.

advh67 commented 5 years ago

I have created a new app with last scaffold template. I later modified the file settings.py activating LDAP_SETTINGS. The app worked and showed the login screen. When I type any user/password it throws this error on console:

ERROR:root:Traceback (most recent call last): File "/usr/lib/python3.7/site-packages/py4web/core.py", line 469, in wrapper ret = func(*func_args, *func_kwargs) File "/usr/lib/python3.7/site-packages/py4web/core.py", line 435, in wrapper ret = func(args, **kwargs) File "/usr/lib/python3.7/site-packages/py4web/utils/auth.py", line 133, in responder return self.action(path, request.method, request.query, request.json) File "/usr/lib/python3.7/site-packages/py4web/utils/auth.py", line 164, in action if self.plugins['pam'].check_credentials(username, password): KeyError: 'pam'

I upgraded pyweb typing "pip install --upgrade py4web", and file /usr/lib/python3.7/site-packages/py4web/utils/auth_plugins/pam.py exists. /usr/lib/.../pam_plugin.py exists, too.

I have this in my file settings.py:

enable PAM

USE_PAM = False

enable LDAP

USE_LDAP = True LDAP_SETTINGS = { # corrected typing error SETTING -> SETTINGS 'mode': 'ad', 'server': 'mycorporateserver.intranet',
'base_dn': 'ou=Users,dc=domain,dc=com'}

By the way, my corporate ldap server accepts user names, not emails. How can I change it on py4web?

mdipierro commented 5 years ago

I posted a new version. Please check if it fixes it.

advh67 commented 5 years ago

It looks like it has been fixed. I have updated your modifications directly from github to my folder "site-packages". Updated the "assets" folder, deleted my app and re-created it using a updated dashboard. Then, I modified again the (corrected) settings.py with my settings. Now It shows login screen. When I type user/password and click "login", it throws an "Internal server error" about jwt:

traceback | Traceback (most recent call last):  
File "/usr/lib/python3.7/site-packages/jwt/api_jws.py", line 180, in _load     signing_input, crypto_segment = jwt.rsplit(b'.', 1) 
ValueError: not enough values to unpack (expected 2, got 1) 

During handling of the above exception, another exception occurred:  Traceback (most recent call last):   File "/usr/lib/python3.7/site-packages/py4web/core.py", line 469, in wrapper     ret = func(*func_args, **func_kwargs)   File "/usr/lib/python3.7/site-packages/py4web/core.py", line 434, in wrapper     [obj.on_request() for obj in fixtures]   File "/usr/lib/python3.7/site-packages/py4web/core.py", line 434, in      [obj.on_request() for obj in fixtures]   File "/usr/lib/python3.7/site-packages/py4web/core.py", line 348, in on_request     self.load()   File "/usr/lib/python3.7/site-packages/py4web/core.py", line 310, in load     token_data, self.secret, algorithms=[self.algorithm])   File "/usr/lib/python3.7/site-packages/jwt/api_jwt.py", line 84, in decode     payload, _, _, _ = self._load(jwt)   File "/usr/lib/python3.7/site-packages/jwt/api_jws.py", line 183, in _load     raise DecodeError('Not enough segments') jwt.exceptions.DecodeError: Not enough segments
-- | --
DecodeError
Not enough segments
file/usr/lib/python3.7/site-packages/py4web/core.pyfuncwrapperlnum469code            try:                 request.app_name = app_name                 ret = func(*func_args, **func_kwargs)                 if isinstance(ret, dict):                     response.headers['Content-Type'] = 'application/json' varsfunc_args()func_kwargs{}app_name'gestor'funcfile/usr/lib/python3.7/site-packages/py4web/core.pyfuncwrapperlnum434code            def wrapper(*args, **kwargs):                 try:                     [obj.on_request() for obj in fixtures]                     ret = func(*args, **kwargs)                     for obj in fixtures: varsargs()kwargs{}fixtures[, , , , , ]funcfile/usr/lib/python3.7/site-packages/py4web/core.pyfunclnum434code            def wrapper(*args, **kwargs):                 try:                     [obj.on_request() for obj in fixtures]                     ret = func(*args, **kwargs)                     for obj in fixtures: vars.0objfile/usr/lib/python3.7/site-packages/py4web/core.pyfuncon_requestlnum348code     def on_request(self):         self.load()      def on_error(self): varsselffile/usr/lib/python3.7/site-packages/py4web/core.pyfuncloadlnum310code                else:                     self.local.data = jwt.decode(                         token_data, self.secret, algorithms=[self.algorithm])                 if self.expiration is not None and self.storage is None:                     assert self.local.data[ varsselfraw_token'3f24065c-45d5-466f-bb0a-0a5664355b7a'token_datab'3f24065c-45d5-466f-bb0a-0a5664355b7a'file/usr/lib/python3.7/site-packages/jwt/api_jwt.pyfuncdecodelnum84code            )          payload, _, _, _ = self._load(jwt)          if options is None: varsselfjwtb'3f24065c-45d5-466f-bb0a-0a5664355b7a'key''verifyTruealgorithms['HS256']optionsNonekwargs{}file/usr/lib/python3.7/site-packages/jwt/api_jws.pyfunc_loadlnum183code            header_segment, payload_segment = signing_input.split(b'.', 1)         except ValueError:             raise DecodeError('Not enough segments')          try: varsselfjwtb'3f24065c-45d5-466f-bb0a-0a5664355b7a' | /usr/lib/python3.7/site-packages/py4web/core.py | wrapper | 469 | try:                 request.app_name = app_name                 ret = func(*func_args, **func_kwargs)                 if isinstance(ret, dict):                     response.headers['Content-Type'] = 'application/json' | func_args()func_kwargs{}app_name'gestor'func | () | {} | 'gestor' |   | /usr/lib/python3.7/site-packages/py4web/core.py | wrapper | 434 | def wrapper(*args, **kwargs):                 try:                     [obj.on_request() for obj in fixtures]                     ret = func(*args, **kwargs)                     for obj in fixtures: | args()kwargs{}fixtures[, , , , , ]func | () | {} | [, , , , , ] |   | /usr/lib/python3.7/site-packages/py4web/core.py |   | 434 | def wrapper(*args, **kwargs):                 try:                     [obj.on_request() for obj in fixtures]                     ret = func(*args, **kwargs)                     for obj in fixtures: | .0obj |   |   | /usr/lib/python3.7/site-packages/py4web/core.py | on_request | 348 | def on_request(self):         self.load()      def on_error(self): | self |   | /usr/lib/python3.7/site-packages/py4web/core.py | load | 310 | else:                     self.local.data = jwt.decode(                         token_data, self.secret, algorithms=[self.algorithm])                 if self.expiration is not None and self.storage is None:                     assert self.local.data[ | selfraw_token'3f24065c-45d5-466f-bb0a-0a5664355b7a'token_datab'3f24065c-45d5-466f-bb0a-0a5664355b7a' |   | '3f24065c-45d5-466f-bb0a-0a5664355b7a' | b'3f24065c-45d5-466f-bb0a-0a5664355b7a' | /usr/lib/python3.7/site-packages/jwt/api_jwt.py | decode | 84 | )          payload, _, _, _ = self._load(jwt)          if options is None: | selfjwtb'3f24065c-45d5-466f-bb0a-0a5664355b7a'key''verifyTruealgorithms['HS256']optionsNonekwargs{} |   | b'3f24065c-45d5-466f-bb0a-0a5664355b7a' | '' | True | ['HS256'] | None | {} | /usr/lib/python3.7/site-packages/jwt/api_jws.py | _load | 183 | header_segment, payload_segment = signing_input.split(b'.', 1)         except ValueError:             raise DecodeError('Not enough segments')          try: | selfjwtb'3f24065c-45d5-466f-bb0a-0a5664355b7a' |   | b'3f24065c-45d5-466f-bb0a-0a5664355b7a'
/usr/lib/python3.7/site-packages/py4web/core.py
wrapper
469
try:                 request.app_name = app_name                 ret = func(*func_args, **func_kwargs)                 if isinstance(ret, dict):                     response.headers['Content-Type'] = 'application/json'
func_args()func_kwargs{}app_name'gestor'func | () | {} | 'gestor' |  
()
{}
'gestor'
 
/usr/lib/python3.7/site-packages/py4web/core.py
wrapper
434
def wrapper(*args, **kwargs):                 try:                     [obj.on_request() for obj in fixtures]                     ret = func(*args, **kwargs)                     for obj in fixtures:
args()kwargs{}fixtures[, , , , , ]func | () | {} | [, , , , , ] |  
()
{}
[, , , , , ]
 
/usr/lib/python3.7/site-packages/py4web/core.py
 
434
def wrapper(*args, **kwargs):                 try:                     [obj.on_request() for obj in fixtures]                     ret = func(*args, **kwargs)                     for obj in fixtures:
.0obj |   |  
 
 
/usr/lib/python3.7/site-packages/py4web/core.py
on_request
348
def on_request(self):         self.load()      def on_error(self):
self |  
 
/usr/lib/python3.7/site-packages/py4web/core.py
load
310
else:                     self.local.data = jwt.decode(                         token_data, self.secret, algorithms=[self.algorithm])                 if self.expiration is not None and self.storage is None:                     assert self.local.data[
selfraw_token'3f24065c-45d5-466f-bb0a-0a5664355b7a'token_datab'3f24065c-45d5-466f-bb0a-0a5664355b7a' |   | '3f24065c-45d5-466f-bb0a-0a5664355b7a' | b'3f24065c-45d5-466f-bb0a-0a5664355b7a'
 
'3f24065c-45d5-466f-bb0a-0a5664355b7a'
b'3f24065c-45d5-466f-bb0a-0a5664355b7a'
/usr/lib/python3.7/site-packages/jwt/api_jwt.py
decode
84
)          payload, _, _, _ = self._load(jwt)          if options is None:
selfjwtb'3f24065c-45d5-466f-bb0a-0a5664355b7a'key''verifyTruealgorithms['HS256']optionsNonekwargs{} |   | b'3f24065c-45d5-466f-bb0a-0a5664355b7a' | '' | True | ['HS256'] | None | {}
 
b'3f24065c-45d5-466f-bb0a-0a5664355b7a'
''
True
['HS256']
None
{}
/usr/lib/python3.7/site-packages/jwt/api_jws.py
_load
183
header_segment, payload_segment = signing_input.split(b'.', 1)         except ValueError:             raise DecodeError('Not enough segments')          try:
selfjwtb'3f24065c-45d5-466f-bb0a-0a5664355b7a' |   | b'3f24065c-45d5-466f-bb0a-0a5664355b7a'
 
b'3f24065c-45d5-466f-bb0a-0a5664355b7a'
mdipierro commented 5 years ago

Try clear cookies

On Mon, Sep 23, 2019, 02:04 advh67 notifications@github.com wrote:

May be fixed. I have updated your modifications directly from github to my folder "site-packages". Updated the "assets" folder, deleted my app and re-created it with updated dashboard. Then, I modified again the (corrected) settings.py with my settings. Now It shows login screen. When I type user/password and click "login", it throws an "Internal server error" about jwt: traceback Traceback (most recent call last): File "/usr/lib/python3.7/site-packages/jwt/api_jws.py", line 180, in _load signing_input, crypto_segment = jwt.rsplit(b'.', 1) ValueError: not enough values to unpack (expected 2, got 1) During handling of the above exception, another exception occurred: Traceback (most recent call last): File "/usr/lib/python3.7/site-packages/py4web/core.py", line 469, in wrapper ret = func(*func_args, func_kwargs) File "/usr/lib/python3.7/site-packages/py4web/core.py", line 434, in wrapper [obj.on_request() for obj in fixtures] File "/usr/lib/python3.7/site-packages/py4web/core.py", line 434, in [obj.on_request() for obj in fixtures] File "/usr/lib/python3.7/site-packages/py4web/core.py", line 348, in on_request self.load() File "/usr/lib/python3.7/site-packages/py4web/core.py", line 310, in load token_data, self.secret, algorithms=[self.algorithm]) File "/usr/lib/python3.7/site-packages/jwt/apijwt.py", line 84, in decode payload, , , = self._load(jwt) File "/usr/lib/python3.7/site-packages/jwt/api_jws.py", line 183, in _load raise DecodeError('Not enough segments') jwt.exceptions.DecodeError: Not enough segments DecodeError Not enough segments file/usr/lib/python3.7/site-packages/py4web/core.pyfuncwrapperlnum469code try: request.app_name = app_name ret = func(*func_args, *func_kwargs) if isinstance(ret, dict): response.headers['Content-Type'] = 'application/json' varsfunc_args()func_kwargs{}app_name'gestor'funcfile/usr/lib/python3.7/site-packages/py4web/core.pyfuncwrapperlnum434code def wrapper(args, kwargs): try: [obj.on_request() for obj in fixtures] ret = func(*args, kwargs) for obj in fixtures: varsargs()kwargs{}fixtures[, , , , , ]funcfile/usr/lib/python3.7/site-packages/py4web/core.pyfunclnum434code def wrapper(*args, *kwargs): try: [obj.on_request() for obj in fixtures] ret = func(args, kwargs) for obj in fixtures: vars.0objfile/usr/lib/python3.7/site-packages/py4web/core.pyfuncon_requestlnum348code def on_request(self): self.load() def on_error(self): varsselffile/usr/lib/python3.7/site-packages/py4web/core.pyfuncloadlnum310code else: self.local.data = jwt.decode( token_data, self.secret, algorithms=[self.algorithm]) if self.expiration is not None and self.storage is None: assert self.local.data[ varsselfraw_token'3f24065c-45d5-466f-bb0a-0a5664355b7a'token_datab'3f24065c-45d5-466f-bb0a-0a5664355b7a'file/usr/lib/python3.7/site-packages/jwt/apijwt.pyfuncdecodelnum84code ) payload, , , = self._load(jwt) if options is None: varsselfjwtb'3f24065c-45d5-466f-bb0a-0a5664355b7a'key''verifyTruealgorithms['HS256']optionsNonekwargs{}file/usr/lib/python3.7/site-packages/jwt/api_jws.pyfunc_loadlnum183code header_segment, payload_segment = signing_input.split(b'.', 1) except ValueError: raise DecodeError('Not enough segments') try: varsselfjwtb'3f24065c-45d5-466f-bb0a-0a5664355b7a' /usr/lib/python3.7/site-packages/py4web/core.py /usr/lib/python3.7/site-packages/py4web/core.py wrapper 469 try: request.app_name = app_name ret = func(*func_args, **func_kwargs) if isinstance(ret, dict): response.headers['Content-Type'] = 'application/json' func_args()func_kwargs{}app_name'gestor'func () () {} 'gestor'

/usr/lib/python3.7/site-packages/py4web/core.py wrapper 434 def wrapper(*args, *kwargs): try: [obj.on_request() for obj in fixtures] ret = func(args, **kwargs) for obj in fixtures: args()kwargs{}fixtures[, , , , , ]func () () {} [, , , , , ]

/usr/lib/python3.7/site-packages/py4web/core.py

434 def wrapper(*args, *kwargs): try: [obj.on_request() for obj in fixtures] ret = func(args, **kwargs) for obj in fixtures: .0obj

/usr/lib/python3.7/site-packages/py4web/core.py on_request 348 def on_request(self): self.load() def on_error(self): self

/usr/lib/python3.7/site-packages/py4web/core.py load 310 else: self.local.data = jwt.decode( token_data, self.secret, algorithms=[self.algorithm]) if self.expiration is not None and self.storage is None: assert self.local.data[

selfraw_token'3f24065c-45d5-466f-bb0a-0a5664355b7a'token_datab'3f24065c-45d5-466f-bb0a-0a5664355b7a'

'3f24065c-45d5-466f-bb0a-0a5664355b7a' b'3f24065c-45d5-466f-bb0a-0a5664355b7a' /usr/lib/python3.7/site-packages/jwt/apijwt.py decode 84 ) payload, , , = self._load(jwt) if options is None:

selfjwtb'3f24065c-45d5-466f-bb0a-0a5664355b7a'key''verifyTruealgorithms['HS256']optionsNonekwargs{}

b'3f24065c-45d5-466f-bb0a-0a5664355b7a' '' True ['HS256'] None {} /usr/lib/python3.7/site-packages/jwt/api_jws.py _load 183 header_segment, payload_segment = signing_input.split(b'.', 1) except ValueError: raise DecodeError('Not enough segments') try: selfjwtb'3f24065c-45d5-466f-bb0a-0a5664355b7a'

b'3f24065c-45d5-466f-bb0a-0a5664355b7a'

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/web2py/py4web/issues/29?email_source=notifications&email_token=AAHLZT7EFNEA7IO4WUFEKQTQLCBBLA5CNFSM4ILICVT2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOD7KHCEQ#issuecomment-534016274, or mute the thread https://github.com/notifications/unsubscribe-auth/AAHLZTZ5IAUBWT5DAFZ6QWTQLCBBLANCNFSM4ILICVTQ .

advh67 commented 5 years ago

Cookies cleared.

Now, the error is:

ERROR:root:Traceback (most recent call last): File "/usr/lib/python3.7/site-packages/py4web/core.py", line 469, in wrapper ret = func(*func_args, *func_kwargs) File "/usr/lib/python3.7/site-packages/py4web/core.py", line 435, in wrapper ret = func(args, **kwargs) File "/usr/lib/python3.7/site-packages/py4web/utils/auth.py", line 133, in responder return self.action(path, request.method, request.query, request.json) File "/usr/lib/python3.7/site-packages/py4web/utils/auth.py", line 164, in action check = self.plugins[plugin_name].check_credentials(username, password) File "/usr/lib/python3.7/site-packages/py4web/utils/auth_plugins/ldap_plugin.py", line 189, in check_credentials logger.debug('mode: [%s] manage_user: [%s] custom_scope: [%s]' NameError: name 'logger' is not defined

mdipierro commented 5 years ago

Can you try again. I have a possible temporary fix

advh67 commented 5 years ago

ERROR:root:Traceback (most recent call last): File "/usr/lib/python3.7/site-packages/py4web/core.py", line 471, in wrapper ret = func(*func_args, *func_kwargs) File "/usr/lib/python3.7/site-packages/py4web/core.py", line 437, in wrapper ret = func(args, **kwargs) File "/usr/lib/python3.7/site-packages/py4web/utils/auth.py", line 133, in responder return self.action(path, request.method, request.query, request.json) File "/usr/lib/python3.7/site-packages/py4web/utils/auth.py", line 164, in action check = self.plugins[plugin_name].check_credentials(username, password) File "/usr/lib/python3.7/site-packages/py4web/utils/auth_plugins/ldap_plugin.py", line 186, in check_credentials exec("%s = %r" % (key, self.parameters[key])) File "", line 1 logger = <module 'logging' from '/usr/lib/python3.7/logging/init.py'> ^ SyntaxError: invalid syntax

mdipierro commented 5 years ago

one more try. I wish I had a way to test it myself.

On Wed, Sep 25, 2019 at 12:05 AM advh67 notifications@github.com wrote:

ERROR:root:Traceback (most recent call last): File "/usr/lib/python3.7/site-packages/py4web/core.py", line 471, in wrapper ret = func(*func_args, *func_kwargs) File "/usr/lib/python3.7/site-packages/py4web/core.py", line 437, in wrapper ret = func(args, *kwargs) File "/usr/lib/python3.7/site-packages/py4web/utils/auth.py", line 133, in responder return self.action(path, request.method, request.query, request.json) File "/usr/lib/python3.7/site-packages/py4web/utils/auth.py", line 164, in action check = self.plugins[plugin_name].check_credentials(username, password) File "/usr/lib/python3.7/site-packages/py4web/utils/auth_plugins/ldap_plugin.py", line 186, in check_credentials exec("%s = %r" % (key, self.parameters[key])) File "", line 1 logger = <module 'logging' from '/usr/lib/python3.7/logging/init*.py'> ^ SyntaxError: invalid syntax

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/web2py/py4web/issues/29?email_source=notifications&email_token=AAHLZT2KBKT5FLW3DXINREDQLMEUDA5CNFSM4ILICVT2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOD7Q3EKQ#issuecomment-534884906, or mute the thread https://github.com/notifications/unsubscribe-auth/AAHLZTZXQLPN4WWUBHS4ICTQLMEUDANCNFSM4ILICVTQ .

advh67 commented 5 years ago

Don't worry, "quien nunca trabaja, nunca yerra" "who never works, never fails"

The non-new error. I have erased cookies again and restarted py4web.


ERROR:root:Traceback (most recent call last): File "/usr/lib/python3.7/site-packages/py4web/core.py", line 471, in wrapper ret = func(*func_args, *func_kwargs) File "/usr/lib/python3.7/site-packages/py4web/core.py", line 437, in wrapper ret = func(args, **kwargs) File "/usr/lib/python3.7/site-packages/py4web/utils/auth.py", line 133, in responder return self.action(path, request.method, request.query, request.json) File "/usr/lib/python3.7/site-packages/py4web/utils/auth.py", line 164, in action check = self.plugins[plugin_name].check_credentials(username, password) File "/usr/lib/python3.7/site-packages/py4web/utils/auth_plugins/ldap_plugin.py", line 191, in check_credentials logger.debug('mode: [%s] manage_user: [%s] custom_scope: [%s] manage_groups: [%s]' % NameError: name 'logger' is not defined

Could be the mistake "logger.debug..." -> "self.logger.debug..."? There is only one line (162) "self.logger = args["logger"] " in ldap_plugin.py, but there are many lines referencing the plain "logger" variable.

mdipierro commented 5 years ago

yes, they should all be self.logger.

On Wed, Sep 25, 2019 at 12:53 AM advh67 notifications@github.com wrote:

Don't worry, "quien nunca trabaja, nunca yerra" "who never works, never fails"

The non-new error. I have erased cookies again and restarted py4web.

ERROR:root:Traceback (most recent call last): File "/usr/lib/python3.7/site-packages/py4web/core.py", line 471, in wrapper ret = func(*func_args, *func_kwargs) File "/usr/lib/python3.7/site-packages/py4web/core.py", line 437, in wrapper ret = func(args, **kwargs) File "/usr/lib/python3.7/site-packages/py4web/utils/auth.py", line 133, in responder return self.action(path, request.method, request.query, request.json) File "/usr/lib/python3.7/site-packages/py4web/utils/auth.py", line 164, in action check = self.plugins[plugin_name].check_credentials(username, password) File "/usr/lib/python3.7/site-packages/py4web/utils/auth_plugins/ldap_plugin.py", line 191, in check_credentials logger.debug('mode: [%s] manage_user: [%s] custom_scope: [%s] manage_groups: [%s]' % NameError: name 'logger' is not defined

Could be the mistake "logger.debug..." -> "self.logger.debug..."? There is only one line (162) "self.logger = args["logger"] ", but there are many lines referencing the plain "logger" variable.

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/web2py/py4web/issues/29?email_source=notifications&email_token=AAHLZT5P4WHBUIRTX53Z6NLQLMKGVA5CNFSM4ILICVT2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOD7Q6ZQI#issuecomment-534899905, or mute the thread https://github.com/notifications/unsubscribe-auth/AAHLZT6XRN5Y3AEFQMVUD6DQLMKGVANCNFSM4ILICVTQ .

advh67 commented 5 years ago

I replaced all the logger with self.logger.

The next error is "mode is not defined" in check_credentials. You put there a loop with a exec() function. I modified my ldap_plugin.py for showing the variables on my console:

   def check_credentials(self, username, password):
        for key in self.parameters:
            print("%s = %r" % (key, self.parameters[key])) # inserted by me
            exec("%s = %r" % (key, self.parameters[key])) # original
            exec("print(%s)" %key) # inserted by me, just prints the value of the new variable whose name is present in the keys of self.parameters
        if password == '':  # http://tools.ietf.org/html/rfc4513#section-5.1.2
            self.logger.warning('blank password not allowed')
            return False
        self.logger.debug('mode: [%s] manage_user: [%s] custom_scope: [%s] manage_groups: [%s]' % 
                          (str(mode), str(manage_user), str(custom_scope), str(manage_groups)))

The error thrown is:

mode = 'ad' ad server = 'myldap.intranet' myldap.intranet base_dn = 'ou=Users,dc=domain,dc=com' ou=Users,dc=domain,dc=com port = None None secure = False False self_signed_certificate = None None cert_path = None None cert_file = None None cacert_path = None None cacert_file = None None key_file = None None bind_dn = None None bind_pw = None None filterstr = 'objectClass=' objectClass= username_attrib = 'uid' uid custom_scope = 'subtree' subtree allowed_groups = None None manage_user = False False user_firstname_attrib = 'cn:1' ERROR:root:Traceback (most recent call last): File "/usr/lib/python3.7/site-packages/py4web/core.py", line 471, in wrapper ret = func(*func_args, *func_kwargs) File "/usr/lib/python3.7/site-packages/py4web/core.py", line 437, in wrapper ret = func(args, **kwargs) File "/usr/lib/python3.7/site-packages/py4web/utils/auth.py", line 133, in responder return self.action(path, request.method, request.query, request.json) File "/usr/lib/python3.7/site-packages/py4web/utils/auth.py", line 164, in action check = self.plugins[plugin_name].check_credentials(username, password) File "/usr/lib/python3.7/site-packages/py4web/utils/auth_plugins/ldap_plugin.py", line 189, in check_credentials exec("print(%s)" %key) File "", line 1, in NameError: name 'user_firstname_attrib' is not defined

?????

mdipierro commented 5 years ago

One more try please. :-)

advh67 commented 5 years ago

ldap_plugin.py needs to add a line: import ldap import ldap.filter # <--add this

Still testing :-)

Update:

The code is now doing successfully the basic ldap authentication :-D

           if bind_dn:
                # need to search directory with an admin account 1st
                con.simple_bind_s(bind_dn, bind_pw)
            else:
                # credentials should be in the form of username@domain.tld
                con.simple_bind_s(username, password) # does not throw errors like INVALID_CREDENTIALS when credentials are right
            # this will throw an index error if the account is not found
            # in the base_dn
            requested_attrs = ['sAMAccountName']
            if manage_user:
                requested_attrs.extend([user_firstname_attrib, user_lastname_attrib, user_mail_attrib])

Nothing throws error here

It goes OK upto line 300 of check_credentials() But, the lines:

result = con.search_ext_s( base_dn, ldap.SCOPE_SUBTREE, "(&(sAMAccountName=%s)(%s))" % (ldap.filter.escape_filter_chars(username_bare), filterstr), requested_attrs)[0][1]

throw an error: UnboundLocalError: local variable 'result' referenced before assignment

I have enclosed that con.search_ext_s() with a try..except, and returns this error: {'desc': 'Referral', 'info': 'Referral:\nldaps://mydomain/ou=users,dc=mydomain'}

I don't know if this error is about ldap or about MY company ldap implementation. My working web2py app only needs to check if username/passwords are valid. I don't need to search anything else on corporate ldap.

My settings in settings.py are: LDAP_SETTINGS = { 'mode': 'ad', 'server': 'myldapserver.intranet', # is ldaps 'base_dn': 'ou=users,dc=mydomain', 'secure':True, 'self_signed_certificate':True, 'manage_user':True }

MBfromOK commented 5 years ago

I will most likely be testing this soon, any idea's / recommendations for implementation?

Also any recommendations regarding login restrictions by group / user id (without having to create & maintain an access list)?

advh67 commented 5 years ago

Well, my company does not rely its grouping structure on ldap. My needs are just checking user/password and maintain groups by hand because in my company is the only way to do it for me. The ldap structure is only a mirror of our active employees.

Would be nice to have something like (very)"basic_ldap_auth" or so, and inserting/updating the user on py4web auth_user table. Web2py's style.

A nice add would be creating, by default, a membership table with two groups "administrator" and "anonymous" by default(*). I usually authenticate by ldap, but any app must have an administrator (usually me, a mate, a skilled boss,...) and any (ldap) logged user must would be assigned to "anonymous" by default. New groups would be assigned to every active user (by hand :-( ).

(*) I understand english, but is a better option if default names could be translated to local language.

mdipierro commented 5 years ago

@advh67 You can do all this already in py4web but need to write some examples. Anyway the discussion does not belong in this thread. I will create a page in the documentation. :-)

advh67 commented 5 years ago

OK. It will take a while for me to read and assimilate ;-) Thanks

nicozanf commented 3 years ago

I think this issue can be closed.

Basic LDAP authentication with AD works fine (but I've not tested LDAPS). Using TAGS for authorization is well documented on https://py4web.com/_documentation/static/en/chapter-13.html# , especially with the latest changes that you can preview on https://nicozanf.github.io/py4web-doc/en/master/chapter-13.html#

Please open another specific issue if there is something more to work on.