Active directory authentication

163 views
Skip to first unread message

urban....@gmail.com

unread,
Mar 2, 2022, 10:48:40 AM3/2/22
to web2py-users
We're looking into adding AD authentication to our app. We have an active directory account and an app registered on it.

In the documentation I found this example of enabling AD auth:

from gluon.contrib.login_methods.ldap_auth import ldap_auth  auth.settings.login_methods.append(
  ldap_auth( 
   mode='ad', 
   base_dn='ou=Users,dc=domain,dc=com'
  )
)

However I get this error when trying to login

DEBUG:web2py.auth.ldap_auth:Traceback (most recent call last):
  File "C:\urban\web2py_latest\web2py\gluon\contrib\login_methods\ldap_auth.py", line 236, in ldap_auth_aux
    con = init_ldap()
  File "C:\urban\web2py_latest\web2py\gluon\contrib\login_methods\ldap_auth.py", line 630, in init_ldap
    "ldap://" + ldap_server + ":" + str(ldap_port))
  File "C:\Python27\lib\site-packages\ldap\functions.py", line 92, in initialize
    uri, trace_level, trace_file, trace_stack_limit, bytes_mode, **kwargs)
  File "C:\Python27\lib\site-packages\ldap\ldapobject.py", line 106, in __init__
    self._l = ldap.functions._ldap_function_call(ldap._ldap_module_lock,_ldap.initialize,uri)
  File "C:\Python27\lib\site-packages\ldap\functions.py", line 55, in _ldap_function_call
    result = func(*args,**kwargs)
LDAPError: (0, 'Error')

Am I doing anything wrong on the web2py side or is the issue in the AD configuration?

Nico Zanferrari

unread,
Mar 2, 2022, 1:24:58 PM3/2/22
to web...@googlegroups.com
Hi,


Nico


--
Resources:
- http://web2py.com
- http://web2py.com/book (Documentation)
- http://github.com/web2py/web2py (Source code)
- https://code.google.com/p/web2py/issues/list (Report Issues)
---
You received this message because you are subscribed to the Google Groups "web2py-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to web2py+un...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/web2py/7d013980-154b-4b94-9365-4a64f9e32423n%40googlegroups.com.

urban....@gmail.com

unread,
Mar 3, 2022, 8:10:33 AM3/3/22
to web2py-users
No it's not on-premise. They said so explicitly. Apologise for the low info questions. Still trying to wade through the seemingly half outdated guides. Finally got the Flask demo that MS provides to work so that I know the Azure side of things is working at least. Now have to figure out how to implement it in Web2Py. Is the ldap_auth method only for on premise AD?

urban....@gmail.com

unread,
Mar 3, 2022, 9:31:25 AM3/3/22
to web2py-users
"Still trying to wade through the seemingly half outdated guides"
I'm referring to Azure guides not Web2Py.

Silvian “Top 10 Answers” Cedru

unread,
Feb 5, 2023, 10:25:41 PM2/5/23
to web2py-users
Did you figure it out in the end cause I am facing the same issue right now :) 

Davidiam

unread,
Feb 6, 2023, 12:05:52 AM2/6/23
to web...@googlegroups.com
We do AD authentication with Shibboleth as our service provider on IIS 10.  I don't know if that would be an option.  We couldn't find anything else that worked on Windows.


From: web...@googlegroups.com <web...@googlegroups.com> on behalf of Silvian “Top 10 Answers” Cedru <silvia...@gmail.com>
Sent: Monday, February 6, 2023 4:25:40 AM
To: web2py-users <web...@googlegroups.com>
Subject: Re: [web2py] Active directory authentication
 

urban....@gmail.com

unread,
Feb 6, 2023, 2:21:27 AM2/6/23
to web2py-users
"Did you figure it out in the end cause I am facing the same issue right now :)"

We didn't yet end up using AD auth in production, though I did eventually have a rudimentary working version. 

I ended up using the python msal library directly.




b2c_tenant = "some-uuid"
signupsignin_user_flow = "B2C_1_signupsignin1"
editprofile_user_flow = "B2C_1_profileediting1"
resetpassword_user_flow = "B2C_1_passwordreset1"  # Note: Legacy setting.
CLIENT_ID = "some-uuid"
CLIENT_SECRET = "some-uuid"

AUTHORITY = authority_template.format(
    tenant=b2c_tenant, user_flow=signupsignin_user_flow)
B2C_PROFILE_AUTHORITY = authority_template.format(
    tenant=b2c_tenant, user_flow=editprofile_user_flow)
B2C_RESET_PASSWORD_AUTHORITY = authority_template.format(
    tenant=b2c_tenant, user_flow=resetpassword_user_flow)
REDIRECT_PATH = "/getAToken"  # Used for forming an absolute URL to your redirect URI.
ENDPOINT = '' # Application ID URI of app registration in Azure portal
SCOPE = []  # Example with two exposed scopes: ["demo.read", "demo.write"]
SESSION_TYPE = "filesystem"  # Specifies the token cache should be stored in server-side session

def _load_cache():
    cache = msal.SerializableTokenCache()
    if session.get("token_cache"):
        cache.deserialize(session["token_cache"])
    return cache

def _save_cache(cache):
    if cache.has_state_changed:
        session["token_cache"] = cache.serialize()

def _build_msal_app(cache=None, authority=None):
    return msal.ConfidentialClientApplication(
        app_config.CLIENT_ID, authority=authority or app_config.AUTHORITY,
        client_credential=app_config.CLIENT_SECRET, token_cache=cache)

def _build_msal_app(cache=None, authority=None):
    return msal.ConfidentialClientApplication(
        CLIENT_ID, authority=authority or AUTHORITY,
        client_credential=CLIENT_SECRET, token_cache=cache)

def _build_auth_code_flow(authority=None, scopes=None):
    return _build_msal_app(authority=authority).initiate_auth_code_flow(
        scopes or [],
        redirect_uri=redirect_url)

Then I use these functions on the login page.

Something like this:
        session["flow"] = _build_auth_code_flow(scopes=SCOPE) if settings.enable_ad else None
        ad_login_url = session['flow']['auth_uri'] if session["flow"] else ''
        return dict(formLogin = formLogin, loggedIn = False, ad_login_url=ad_login_url)

Using the ad_login_url to redirect to with a button on the login page. Then there's the standard microsoft register/login form that redirects to the my "token" controller function referenced in the "redirect_url" at the top of the pasted code. This url needs to be configured where you register an azure app. 

In the token controller you recieve the token which you an then use for authentication - login/registration

Something like this:
def token():
  cache = _load_cache()
  result = _build_msal_app(cache=cache).acquire_token_by_auth_code_flow(
    session.get("flow", {}), request.vars
  )

  user = result['id_token_claims']

  if "error" in result:
    return dict()

  _save_cache(cache)
  session["user"] = result.get("id_token_claims")
  username = user['preferred_username']

I don't know how clear this is, hopefully it's at least a little bit helpful, but I'm a bit fuzzy on the details. 

Silvian “Top 10 Answers” Cedru

unread,
Feb 6, 2023, 4:05:33 AM2/6/23
to web2py-users
Thanks I will try that out cause the only thing that I got to work today was openid and I am not so sure if that is a good option for that .
Reply all
Reply to author
Forward
0 new messages