Migrated SAML settings from app.config to Settings(), SAML exception catching

This commit is contained in:
vmarkop 2021-12-07 15:32:31 +02:00
parent 3255bc26d0
commit c08f9b1cfd
5 changed files with 72 additions and 36 deletions

View file

@ -112,10 +112,10 @@ class Setting(db.Model):
'oidc_oauth_account_description_property': '',
'saml_enabled': False,
'saml_debug': True,
'saml_metadata_url': 'https://md.aai.grnet.gr/aggregates/grnet-metadata.xml',#'https://md.aai.grnet.gr/aggregates/grnet-metadata.xml'
'saml_metadata_url': 'https://example.com/metadata.xml',
'saml_metadata_cache_lifetime': '1',
'saml_idp_sso_binding': 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect',#
'saml_idp_entity_id': 'https://idp.uoa.gr/idp/shibboleth',#'https://idp.uoa.gr/idp/shibboleth'
'saml_idp_sso_binding': 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect',
'saml_idp_entity_id': 'https://idp.example.com/idp/',
'saml_nameid_format': 'urn:oid:0.9.2342.19200300.100.1.1',
'saml_sp_requested_attributes': '[ \
{"name": "urn:oid:0.9.2342.19200300.100.1.3", "nameFormat": "urn:oasis:names:tc:SAML:2.0:attrname-format:uri", "isRequired": true, "friendlyName": "email"}, \

View file

@ -1020,7 +1020,9 @@ def setting_authentication():
'Must have at least one authentication method enabled.'
}
else:
Setting().set('saml_enabled', True)
Setting().set(
'saml_enabled',
True if request.form.get('saml_enabled') else False)
Setting().set('saml_metadata_url',
request.form.get('saml_metadata_url'))
Setting().set('saml_metadata_cache_lifetime',

View file

@ -593,19 +593,27 @@ def logout():
req = saml.prepare_flask_request(request)
auth = saml.init_saml_auth(req)
if Setting().get('saml_logout_url'):
try:
return redirect(
auth.logout(
name_id_format=
Setting().get('saml_nameid_format'),
return_to=Setting().get('saml_logout_url'),
session_index=session['samlSessionIndex'],
name_id=session['samlNameId']))
except:
current_app.logger.info(
"SAML: Your IDP does not support Single Logout.")
try:
return redirect(
auth.logout(
name_id_format=
"urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress",
return_to=Setting().get('saml_logout_url'),
Setting().get('saml_nameid_format'),
session_index=session['samlSessionIndex'],
name_id=session['samlNameId']))
return redirect(
auth.logout(
name_id_format=
"urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress",
session_index=session['samlSessionIndex'],
name_id=session['samlNameId']))
except:
current_app.logger.info(
"SAML: Your IDP does not support Single Logout.")
redirect_uri = url_for('index.login')
oidc_logout = Setting().get('oidc_oauth_logout_url')
@ -897,8 +905,16 @@ def dyndns_update():
def saml_login():
if not Setting().get('saml_enabled'):
abort(400)
global saml
req = saml.prepare_flask_request(request)
auth = saml.init_saml_auth(req)
try:
auth = saml.init_saml_auth(req)
except:
current_app.logger.info(
"SAML: IDP Metadata were not successfully initialized. Reinitializing...")
saml = SAML()
req = saml.prepare_flask_request(request)
auth = saml.init_saml_auth(req)
redirect_url = OneLogin_Saml2_Utils.get_self_url(req) + url_for(
'index.saml_authorized')
return redirect(auth.login(return_to=redirect_url))

View file

@ -21,42 +21,60 @@ class SAML(object):
self.idp_data = None
if Setting().get('saml_idp_entity_id'):
self.idp_data = OneLogin_Saml2_IdPMetadataParser.parse_remote(
Setting().get('saml_metadata_url'),
entity_id=Setting().get('saml_idp_entity_id'),
required_sso_binding=Setting().get('saml_idp_sso_binding'))
try:
self.idp_data = OneLogin_Saml2_IdPMetadataParser.parse_remote(
Setting().get('saml_metadata_url'),
entity_id=Setting().get('saml_idp_entity_id'),
required_sso_binding=Setting().get('saml_idp_sso_binding'))
except:
self.idp_data = None
else:
self.idp_data = OneLogin_Saml2_IdPMetadataParser.parse_remote(
Setting().get('saml_metadata_url'),
entity_id=None)
try:
self.idp_data = OneLogin_Saml2_IdPMetadataParser.parse_remote(
Setting().get('saml_metadata_url'),
entity_id=None)
except:
self.idp_data = None
if self.idp_data is None:
current_app.logger.info(
'SAML: IDP Metadata initial load failed')
exit(-1)
Setting().set('saml_enabled', False)
print("SAML EN1 ", Setting().get('saml_enabled'))
# exit(-1)
def get_idp_data(self):
lifetime = timedelta(
minutes=int(Setting().get('saml_metadata_cache_lifetime'))) # should be seconds instead of minutes?
if self.idp_timestamp + lifetime < datetime.now():
background_thread = Thread(target=self.retrieve_idp_data())
background_thread.start()
# lifetime = timedelta(
# minutes=int(Setting().get('saml_metadata_cache_lifetime'))) # should be seconds instead of minutes?
# Since SAML is now user-configurable, idp_data may change before the lifetime has ended,
# so metadata should not be cached at all, or outdated settings may be used.
try:
self.retrieve_idp_data()
except:
return None
# if self.idp_timestamp + lifetime < datetime.now():
background_thread = Thread(target=self.retrieve_idp_data())
background_thread.start()
return self.idp_data
def retrieve_idp_data(self):
if Setting().get('saml_idp_sso_binding'):
new_idp_data = self.OneLogin_Saml2_IdPMetadataParser.parse_remote(
Setting().get('saml_metadata_url'),
entity_id=Setting().get('saml_idp_entity_id'),
required_sso_binding=Setting().get('saml_idp_sso_binding')
)
try:
new_idp_data = self.OneLogin_Saml2_IdPMetadataParser.parse_remote(
Setting().get('saml_metadata_url'),
entity_id=Setting().get('saml_idp_entity_id'),
required_sso_binding=Setting().get('saml_idp_sso_binding'))
except:
new_idp_data = None
else:
new_idp_data = self.OneLogin_Saml2_IdPMetadataParser.parse_remote(
Setting().get('saml_metadata_url'),
entity_id=Setting().get('saml_idp_entity_id'))
try:
new_idp_data = self.OneLogin_Saml2_IdPMetadataParser.parse_remote(
Setting().get('saml_metadata_url'),
entity_id=Setting().get('saml_idp_entity_id'))
except:
new_idp_data = None
if new_idp_data is not None:
self.idp_data = new_idp_data
self.idp_timestamp = datetime.now()

View file

@ -829,7 +829,7 @@
<label for="saml_want_message_signed">Want Message Signed </label>
</div>
<div class="form-group">
<input type="checkbox" id="saml_sign_metadata" name="saml_sign_metadata" class="checkbox" {% if SETTING.get('saml_signed_metadata') %}checked{% endif %}>
<input type="checkbox" id="saml_sign_metadata" name="saml_sign_metadata" class="checkbox" {% if SETTING.get('saml_sign_metadata') %}checked{% endif %}>
<label for="saml_sign_metadata">Sign Metadata </label>
</div>
<div class="form-group">