Thank you, Simon. I had started down a similar path and got stuck. I will use your code code as a basis to continue that work.
On Thursday, December 5, 2024 at 8:57:26 AM UTC-6 simon...@gmail.com wrote: > Hello Fred, > > I had a legacy web2py app until recently that worked with SAML2 > authentication and Azure AD as Identity Provider. In my particular case, > all users already existed in my app, only authentication was handled via > SAML2. > The following example code was working in my app. > I also recommend to enable python logging and use a browser plugin to > inspect saml2 requests for debugging. > > 1) setup saml2 as authentication method somewhere in the model (db.py in > my case). I also disabled some of the other actions. > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > *# > ---------------------------------------------------------------------------# > Enable SAML login# > ---------------------------------------------------------------------------from > > gluon.contrib.login_methods.saml2_auth import Saml2Authimport os# logging:# > https://docs.python.org/3/library/logging.html#levels > <https://docs.python.org/3/library/logging.html#levels>import logginglogger > = logging.getLogger('saml2')logger.setLevel(logging.DEBUG)# Session Cookies > is not passed in POST to SP after authenticatoin if samesite is not "none" > (must be combined with "secure")session.samesite('none')session.secure()if > not request.is_local: > auth.settings.actions_disabled.append('change_password') > auth.settings.actions_disabled.append('request_reset_password') > auth.settings.actions_disabled.append('reset_password') > auth.settings.actions_disabled.append('profile') > auth.settings.actions_disabled.append('logout') > auth.settings.actions_disabled.append('retrieve_username') > auth.settings.cas_create_user = False auth.settings.use_username = True > auth.settings.logout_next = '' auth.settings.login_form = Saml2Auth( > config_file=os.path.join(request.folder, 'private', 'sp_conf'), > maps=dict( username=lambda v: v['NameID'][0], > first_name=lambda v: v['First Name'][0], last_name=lambda v: v['Last > Name'][0], ), entityid='[entidyId of your security token service > provider]',)* > > 2) put the make_metadata.py in your private-folder > > 3) add a controller to view / create the metadata, in my case in > default.py: > > def metadata(): > import os.path > if os.path.exists(request.folder + '/private/sp.xml'): > f = open(request.folder + '/private/sp.xml', 'r') > response.headers['Content-Type']='application/xml' > return f.read() > else: > import subprocess > command = 'make_metadata.py ' + request.folder + > '/private/sp_conf.py > ' + request.folder + '/private/sp.xml' > #In production should be shell=False > p=subprocess.Popen(command, stdout=subprocess.PIPE, > stderr=subprocess.PIPE,shell=True) > stdout,stderr = p.communicate() > status = p.poll() > if status == 0: > f = open(request.folder + '/private/sp.xml', 'r') > response.headers['Content-Type']='application/xml' > return f.read() > return str(stderr) > > 4) add sp_conf.py to "private" folder for configuring the metadata. add > your specific hostnames, appname, certificate and path to federation > metadata (I had that stored locally): > > #!/usr/bin/env python > # -*- coding: utf-8 -*- > from saml2 import BINDING_HTTP_POST, BINDING_HTTP_REDIRECT > import os.path > import requests > import tempfile > > BASEDIR = os.path.abspath(os.path.dirname(__file__)) > > > def full_path(local_file): > return os.path.join(BASEDIR, local_file) > > > # Web2py SP url and application name > HOST = '[FQDN of your host]' > APP = '[web2py application name]' > # To load the IDP metadata... > IDP_METADATA = full_path('FederationMetadata.xml') # the name of the > FederationMEtadata of your STS > > CONFIG = { > # your entity id, usually your subdomain plus the url to the metadata > view. > 'entityid': '%s/%s/default/metadata' % (HOST, APP), > 'service': { > 'sp': { > 'name': '[name of your app]', > 'endpoints': { > 'assertion_consumer_service': [ > ('%s/%s/default/user/login' % (HOST, APP), > BINDING_HTTP_REDIRECT), > ('%s/%s/default/user/login' % (HOST, APP), > BINDING_HTTP_POST), > ], > }, > 'signing_algorithm': ' > http://www.w3.org/2001/04/xmldsig-more#rsa-sha256', > 'authn_requests_signed': True, > 'want_response_signed': False, > 'want_assertions_signed': True, > 'allow_unsolicited': False, > }, > }, > > # # Your private and public key, here in a subfolder of "private" > 'key_file': full_path('pki/privateKey.key'), > 'cert_file': full_path('pki/certificate.crt'), > > 'attribute_map_dir': full_path('attribute_map_dir'), > > # where the remote metadata is stored > 'metadata': { > 'local': [IDP_METADATA], > }, > } > > 5) add an "attribute_map_dir" folder with a "saml_unspecified.py" that > mapps the field names of your app to the field names of your identity > provider, e.g: > MAP = { > "identifier": > "urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified", > "fro": { > 'Last Name': 'last_name', > 'First Name': 'first_name', > 'NameID': 'username', > 'Email': 'email', > }, > "to": { > 'last_name': 'Last Name', > 'first_name': 'First Name', > 'username': 'NameID', > 'email': 'Email' > } > } > > 6) call the metadata-controller to create the sp.xml > > That should do it. > > Simon > > fre...@gmail.com schrieb am Mittwoch, 4. Dezember 2024 um 17:14:40 UTC+1: > >> I have a legacy web2py app that's been using LDAP since 2010 when I >> created it. We are changing our IT systems to use SAML2 via OneLogin.com >> for authentication where possible and so I'd like to convert my app from >> from LDAP to SAML2 authentication. Can anyone provide some examples of >> SAML2 auth in web2py? >> >> I've found a few examples but they are old and don't quite give me enough >> basis to get SAML2 working. I don't want to go through any intermediary >> like Jainrain. I've looked over gluon/contrib/login_methods/saml2_auth.py >> but haven't been able to work out all that I need to do to use it. >> >> I'm also concerned about how converting to SAML would work with all the >> auth_user records already created via the LDAP authentication. >> >> -Fred >> >> -- 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+unsubscr...@googlegroups.com. To view this discussion visit https://groups.google.com/d/msgid/web2py/de130107-f0a0-40d5-bfee-4008e56a073en%40googlegroups.com.