diff --git a/MANIFEST.in b/MANIFEST.in
index 7fcee19f9..90e28ab2f 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -15,7 +15,6 @@ recursive-include authentic2/auth2_auth/auth2_ssl/templates *.html *.txt *.xml
recursive-include authentic2/auth2_auth/templates *.html *.txt *.xml
recursive-include authentic2/auth2_auth/auth2_oath/templates *.html *.txt *.xml
recursive-include authentic2/auth2_auth/auth2_openid/templates *.html *.txt *.xml
-recursive-include authentic2/authsaml2/templates *.html *.txt *.xml
recursive-include authentic2/vendor/totp_js/js *.js
recursive-include authentic2/saml/fixtures *.json
@@ -27,7 +26,6 @@ recursive-include authentic2/auth2_auth/locale *.po *.mo
recursive-include authentic2/auth2_auth/auth2_ssl/locale *.po *.mo
recursive-include authentic2/auth2_auth/auth2_oath/locale *.po *.mo
recursive-include authentic2/auth2_auth/auth2_openid/locale *.po *.mo
-recursive-include authentic2/authsaml2/locale *.po *.mo
recursive-include authentic2/attribute_aggregator/locale *.po *.mo
recursive-include authentic2/disco_service/locale *.po *.mo
recursive-include authentic2 README xrds.xml *.txt yadis.xrdf
diff --git a/authentic2/authsaml2/README b/authentic2/authsaml2/README
deleted file mode 100644
index 188796d14..000000000
--- a/authentic2/authsaml2/README
+++ /dev/null
@@ -1,110 +0,0 @@
-= Add to settings =
-
-SAML_SIGNATURE_PRIVATE_KEY = *your_key*
-INSTALLED_APPS += ('*project*.authsaml2', '*project*.authsaml2.saml',)
-AUTHENTICATION_BACKENDS = (
- 'django.contrib.auth.backends.ModelBackend',
- '*project*.authsaml2.backends.SAML2AuthBackend',
-)
-
-When login_required() with registration and you want to add on the login page the login with a federated account:
-- the template is directly called: use a context processor to pass a variable
-TEMPLATE_CONTEXT_PROCESSORS += (
- 'spsaml.views.idp_list',
-)
-spsaml.views.idp_list:
-def idp_list(request):
- return {'providers_list': authsaml2.saml.common.get_idp_list()}
-- modify LOGIN_URL
-LOGIN_URL = '/login/'
-url(r'^login/', spsaml.views.login)
-Pass {'providers_list': authsaml2.saml.common.get_idp_list()} to the template
-
-Then configure in the admin part your SP
-
-= Target URL =
-
-After logout, the parameter 'Back url' is used. If empty, authsaml2 returns to the root.
-
-After login, authsaml2 will redirect in a parameter you have to register,
-authsaml2 returns to the root of the site.
-To register a url, if a fonction is called with the next parameter in the url,
-as it is the case usually with a login page, just call:
- authsaml2.saml2_endpoints.register_next_target(request)
-If there is no next parameter call this function giving the target url
- authsaml2.saml2_endpoints.register_next_target(request, target_url)
-
-After defederation, by default the local session is not sesion is not ended
-and the back url is the one of calling of the defederation function.
-
-= Call AuthSAML2 from your login page =
-
-* Views:
-from django.shortcuts import render_to_response
-from django.template import RequestContext
-from django.contrib.auth import views as auth_views
-import authentic2.authsaml2.saml2_endpoints
-
-def login(request):
- authsaml2.saml2_endpoints.register_next_target(request)
- return auth_views.login(request)
-
-* Template:
-
-{% if providers_list %}
-{% trans "Log in with a federated account?" %}
-
-{% endif %}
-
-= Call AuthSAML2 into the application for user account management =
-
-* Views:
-from django.shortcuts import render_to_response
-from django.template import RequestContext
-from django.contrib.auth import views as auth_views
-import authentic2.authsaml2.saml2_endpoints
-import authentic2.authsaml2.saml.common
-
-def inside(request):
- authsaml2.saml2_endpoints.register_next_target(request, '/in')
- return render_to_response('in.html', {'providers_list_federated': authsaml2.saml.common.get_idp_user_federated_list(request),
- 'providers_list_not_federated': authsaml2.saml.common.get_idp_user_not_federated_list(request),
- 'provider_active_session': authsaml2.saml.common.get_provider_of_active_session(request)},
- context_instance=RequestContext(request))
-
-* Template:
-{% if providers_list_not_federated %}
-{% trans "Federate your identity" %}
-
-{% endif %}
-{% if providers_list_federated %}
-{% trans "Defederate your identity" %}
-
-{% endif %}
-{% if provider_active_session %}
-{% trans "Logout" %}
-
-{% else %}
-{% trans "Log out" %}
-{% endif %}
-
-Now in idp/__init__.py
-
- tpl_parameters['providers_list_federated'] = authentic.saml.common.get_idp_user_federated_list(request)
- tpl_parameters['providers_list_not_federated'] = authentic.saml.common.get_idp_user_not_federated_list(request)
-
diff --git a/authentic2/authsaml2/__init__.py b/authentic2/authsaml2/__init__.py
deleted file mode 100644
index e69de29bb..000000000
diff --git a/authentic2/authsaml2/backends.py b/authentic2/authsaml2/backends.py
deleted file mode 100644
index 50f199a7b..000000000
--- a/authentic2/authsaml2/backends.py
+++ /dev/null
@@ -1,135 +0,0 @@
-import string
-import random
-import logging
-import lasso
-
-from django.db import transaction
-from django.core.urlresolvers import reverse
-from django.utils.translation import ugettext as _
-
-from authentic2.compat import get_user_model
-from authentic2.saml.common import \
- lookup_federation_by_name_id_and_provider_id, add_federation, \
- get_idp_options_policy
-from authentic2.saml.models import LIBERTY_SESSION_DUMP_KIND_SP, \
- LibertySessionDump, LibertyProvider
-from authentic2.authsaml2.models import SAML2TransientUser
-
-logger = logging.getLogger('authentic2.authsaml2.backends')
-
-
-class AuthenticationError(Exception):
- pass
-
-
-class AuthSAML2Backend:
- def logout_list(self, request):
- pid = None
- q = LibertySessionDump. \
- objects.filter(django_session_key=request.session.session_key,
- kind=LIBERTY_SESSION_DUMP_KIND_SP)
- if not q:
- logger.debug('logout_list: no LibertySessionDump found')
- return []
- '''
- We deal with a single IdP session
- '''
- try:
- provider_id = lasso.Session(). \
- newFromDump(q[0].session_dump.encode('utf-8')). \
- get_assertions().keys()[0]
- except:
- return []
- if not provider_id:
- return []
- logger.debug('logout_list: Found session for %s' % provider_id)
- name = provider_id
- provider = None
- try:
- provider = LibertyProvider.objects.get(entity_id=provider_id)
- name = provider.name
- except LibertyProvider.DoesNotExist:
- logger.error('logout_list: session found for unknown provider %s' \
- % provider_id)
- return []
-
- policy = get_idp_options_policy(provider)
- if not policy:
- logger.error('logout_list: No policy found for %s' % provider_id)
- return []
- elif not policy.forward_slo:
- logger.info('logout_list: %s configured to not reveive slo' \
- % provider_id)
- return []
- else:
- import saml2_endpoints
- code = ''
- code += _('Sending logout to %(pid)s....') % { 'pid': name or provider_id }
- code += '''
''' \
- % (reverse(saml2_endpoints.sp_slo,
- args=[provider_id]), provider_id)
- return [ code ]
-
-
-class AuthSAML2PersistentBackend:
- supports_object_permissions = False
- supports_anonymous_user = False
-
- def authenticate(self, name_id=None, provider_id=None):
- '''Authenticate persistent NameID'''
- if not name_id or not provider_id:# or not name_id.nameQualifier:
- return None
- #fed = lookup_federation_by_name_identifier(name_id=name_id)
- fed = lookup_federation_by_name_id_and_provider_id(name_id, provider_id)
- if fed is None:
- return None
- fed.user.backend = '%s.%s' % (__name__, self.__class__.__name__)
- return fed.user
-
- def get_user(self, user_id):
- User = get_user_model()
- try:
- return User.objects.get(id=user_id)
- except User.DoesNotExist:
- return None
-
- @transaction.commit_on_success
- def create_user(self, username=None, name_id=None, provider_id=None):
- '''Create a new user mapping to the given NameID'''
- if not name_id or \
- name_id.format != \
- lasso.SAML2_NAME_IDENTIFIER_FORMAT_PERSISTENT or \
- not name_id.nameQualifier:
- raise ValueError('Invalid NameID')
- if not username:
- # FIXME: maybe keep more information in the forged username
- username = 'saml2-%s' % ''. \
- join([random.SystemRandom().choice(string.letters) for x in range(10)])
- User = get_user_model()
- user = User()
- user.username = username
- if hasattr(User, 'set_unusable_password'):
- user.set_unusable_password()
- user.is_active = True
- user.save()
- add_federation(user, name_id=name_id, provider_id=provider_id)
- return user
-
-class AuthSAML2TransientBackend:
- supports_object_permissions = False
- supports_anonymous_user = False
-
- def authenticate(self, name_id=None):
- '''Create temporary user for transient NameID'''
- if not name_id or \
- name_id.format != \
- lasso.SAML2_NAME_IDENTIFIER_FORMAT_TRANSIENT or \
- not name_id.content:
- return None
- user = SAML2TransientUser(id=name_id.content)
- return user
-
- def get_user(self, user_id):
- '''Create temporary user for transient NameID'''
- return SAML2TransientUser(id=user_id)
diff --git a/authentic2/authsaml2/frontend.py b/authentic2/authsaml2/frontend.py
deleted file mode 100644
index 1c4190778..000000000
--- a/authentic2/authsaml2/frontend.py
+++ /dev/null
@@ -1,54 +0,0 @@
-import urllib
-import functools
-import django.forms as forms
-import authentic2.saml.common as saml_common
-
-from django.utils.translation import gettext_noop
-from django.http import HttpResponseRedirect
-from django.contrib.auth import REDIRECT_FIELD_NAME
-from django.utils.translation import ugettext as _
-
-from . import saml2_endpoints
-
-class AuthSAML2Form(forms.Form):
- def __init__(self, *args, **kwargs):
- idp_list = kwargs.pop('idp_list')
- super(AuthSAML2Form, self).__init__(*args, **kwargs)
- self.fields['provider_id'].choices = \
- [(p['entity_id'], p['name']) for p in idp_list]
-
- provider_id = forms.ChoiceField(label=_('Choose your identity provider'),
- choices=())
-
-class AuthSAML2Frontend(object):
- def __init__(self):
- self.idp_list = saml_common.get_idp_list_sorted()
-
- def enabled(self):
- return bool(self.idp_list)
-
- def id(self):
- return 'saml2'
-
- def name(self):
- return gettext_noop('SAML 2.0')
-
- def form(self):
- return functools.partial(AuthSAML2Form, idp_list=self.idp_list)
-
- def post(self, request, form, nonce, next):
- provider_id = form.cleaned_data['provider_id']
- return HttpResponseRedirect('/authsaml2/sso?entity_id=%s&%s=%s' %
- (urllib.quote(provider_id),
- REDIRECT_FIELD_NAME,
- urllib.quote(next)))
-
- def get_context(self):
- '''Specific context variable used by the specific template'''
- return { 'idp_providers': self.idp_list }
-
- def template(self):
- return 'auth/saml2/login_form.html'
-
- def profile(self, request):
- return saml2_endpoints.profile(request)
diff --git a/authentic2/authsaml2/locale/fr/LC_MESSAGES/django.po b/authentic2/authsaml2/locale/fr/LC_MESSAGES/django.po
deleted file mode 100644
index 68b65dc77..000000000
--- a/authentic2/authsaml2/locale/fr/LC_MESSAGES/django.po
+++ /dev/null
@@ -1,410 +0,0 @@
-# French translation of Authentic
-# Copyright (C) 2010, 2011 Entr'ouvert
-# This file is distributed under the same license as the Authentic package.
-# Frederic Peters , 2010.
-#
-msgid ""
-msgstr ""
-"Project-Id-Version: Authentic\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2013-07-23 16:39+0200\n"
-"PO-Revision-Date: 2013-07-23 16:39+0200\n"
-"Last-Translator: Mikaël Ates \n"
-"Language-Team: None\n"
-"Language: fr\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Plural-Forms: nplurals=2; plural=n>1;\n"
-
-#: backends.py:67
-#, python-format
-msgid "Sending logout to %(pid)s...."
-msgstr "Envoi de la deconnesion a %(pid)s...."
-
-#: frontend.py:20
-msgid "Choose your identity provider"
-msgstr "Choisissez votre fournisseur d'identité"
-
-#: frontend.py:34
-msgid "SAML 2.0"
-msgstr "SAML 2.0"
-
-#: models.py:90
-msgid "Anonymous"
-msgstr "Anonyme"
-
-#: saml2_endpoints.py:128
-msgid "redirect_to_disco: unable to build disco request"
-msgstr ""
-
-#: saml2_endpoints.py:135
-#, python-format
-msgid "disco_response: HTTP request not supported %s"
-msgstr ""
-
-#: saml2_endpoints.py:176 saml2_endpoints.py:182
-msgid "sso: Service provider not configured"
-msgstr ""
-
-#: saml2_endpoints.py:188
-msgid "sso: No SAML2 identity provider selected"
-msgstr ""
-
-#: saml2_endpoints.py:196
-msgid "sso: The provider does not exist"
-msgstr ""
-
-#: saml2_endpoints.py:201
-msgid "sso: Unable to create Login object"
-msgstr ""
-
-#: saml2_endpoints.py:210
-#, python-format
-msgid "sso: %s does not have any supported SingleSignOn endpoint"
-msgstr ""
-
-#: saml2_endpoints.py:216
-#, python-format
-msgid "sso: initAuthnRequest %s"
-msgstr ""
-
-#: saml2_endpoints.py:222
-msgid "sso: No IdP policy defined"
-msgstr ""
-
-#: saml2_endpoints.py:228
-#, python-format
-msgid "SSO: buildAuthnRequestMsg %s"
-msgstr ""
-
-#: saml2_endpoints.py:255
-msgid "singleSignOnArtifact: Service provider not configured"
-msgstr ""
-
-#: saml2_endpoints.py:273
-msgid "singleSignOnArtifact: Unable to create Login object"
-msgstr ""
-
-#: saml2_endpoints.py:279
-msgid "singleSignOnArtifact: No message given."
-msgstr ""
-
-#: saml2_endpoints.py:300
-#, python-format
-msgid "singleSignOnArtifact: provider %r unknown"
-msgstr ""
-
-#: saml2_endpoints.py:309
-#, python-format
-msgid "singleSignOnArtifact: initRequest %s"
-msgstr ""
-
-#: saml2_endpoints.py:317
-#, python-format
-msgid "singleSignOnArtifact: buildRequestMsg %s"
-msgstr ""
-
-#: saml2_endpoints.py:329
-#, python-format
-msgid ""
-"singleSignOnArtifact: Failure to communicate with artifact "
-"resolver %r"
-msgstr ""
-
-#: saml2_endpoints.py:334
-#, python-format
-msgid ""
-"singleSignOnArtifact: Artifact resolver at %r returned an empty "
-"response"
-msgstr ""
-
-#: saml2_endpoints.py:350
-#, python-format
-msgid "singleSignOnArtifact: processResponseMsg raised %s"
-msgstr ""
-
-#: saml2_endpoints.py:365
-msgid "singleSignOnPost: Service provider not configured"
-msgstr ""
-
-#: saml2_endpoints.py:371
-msgid "singleSignOnPost: Unable to create Login object"
-msgstr ""
-
-#: saml2_endpoints.py:380
-msgid "singleSignOnPost: No message given."
-msgstr ""
-
-#: saml2_endpoints.py:407
-#, python-format
-msgid "singleSignOnPost: provider %r unknown"
-msgstr ""
-
-#: saml2_endpoints.py:418
-#, python-format
-msgid "singleSignOnPost: %s"
-msgstr ""
-
-#: saml2_endpoints.py:441
-msgid "sso_after_response: error checking authn response"
-msgstr ""
-
-#: saml2_endpoints.py:447
-#, python-format
-msgid "sso_after_response: acceptSso raised %s"
-msgstr ""
-
-#: saml2_endpoints.py:583
-msgid "sso_after_response: No IdP policy defined"
-msgstr ""
-
-#: saml2_endpoints.py:632
-msgid ""
-"sso_after_response: No backend for temporary federation "
-"is configured"
-msgstr ""
-
-#: saml2_endpoints.py:653
-msgid ""
-"sso_after_response: Transient access policy: Configuration error"
-msgstr ""
-
-#: saml2_endpoints.py:703
-msgid ""
-"sso_after_response: You were not asked your consent for "
-"account linking"
-msgstr ""
-
-#: saml2_endpoints.py:720
-msgid ""
-"sso_after_response: Persistent Account policy: Configuration "
-"error"
-msgstr ""
-
-#: saml2_endpoints.py:724
-msgid ""
-"sso_after_response: Transient access policy: NameId format not "
-"supported"
-msgstr ""
-
-#: saml2_endpoints.py:747
-msgid "finish_federation: Service provider not configured"
-msgstr ""
-
-#: saml2_endpoints.py:753
-msgid "finish_federation: Unable to create Login object"
-msgstr ""
-
-#: saml2_endpoints.py:760
-msgid "finish_federation: Error loading session."
-msgstr ""
-
-#: saml2_endpoints.py:777
-msgid ""
-"SSO/finish_federation: Error adding new federation for "
-"this user"
-msgstr ""
-
-#: saml2_endpoints.py:816
-msgid "finish_federation: Unable to perform federation"
-msgstr ""
-
-#: saml2_endpoints.py:958
-msgid "logout: not a logged in user"
-msgstr ""
-
-#: saml2_endpoints.py:963
-msgid "logout: Service provider not configured"
-msgstr ""
-
-#: saml2_endpoints.py:968
-msgid "logout: Unable to create Login object"
-msgstr ""
-
-#: saml2_endpoints.py:976
-msgid "logout: No session for global logout."
-msgstr ""
-
-#: saml2_endpoints.py:984
-msgid "logout: Session malformed."
-msgstr ""
-
-#: saml2_endpoints.py:990
-msgid "logout: Error loading provider."
-msgstr ""
-
-#: saml2_endpoints.py:1018
-msgid "logout: SOAP error - Only local logout performed."
-msgstr ""
-
-#: saml2_endpoints.py:1066
-msgid "logout: Unknown HTTP method."
-msgstr ""
-
-#: saml2_endpoints.py:1076
-#, python-format
-msgid ""
-"localLogout: SOAP error with %s - Only local logout performed."
-msgstr ""
-
-#: saml2_endpoints.py:1080
-#, python-format
-msgid "localLogout: %s - Only local logout performed."
-msgstr ""
-
-#: saml2_endpoints.py:1092
-msgid "singleLogoutReturn: Service provider not configured"
-msgstr ""
-
-#: saml2_endpoints.py:1098
-msgid ""
-"singleLogoutReturn: Unable to handle Single Logout by Redirect "
-"without request"
-msgstr ""
-
-#: saml2_endpoints.py:1105
-msgid "singleLogoutReturn: Unable to create Login object"
-msgstr ""
-
-#: saml2_endpoints.py:1391
-#, python-format
-msgid "singleLogout: provider %r unknown"
-msgstr ""
-
-#: saml2_endpoints.py:1469
-msgid "fedTerm/SP UI: No provider for defederation"
-msgstr ""
-
-#: saml2_endpoints.py:1474
-msgid "fedTerm/SP UI: Unable to defederate a not logged user!"
-msgstr ""
-
-#: saml2_endpoints.py:1480
-msgid "fedTerm/SP UI: Service provider not configured"
-msgstr ""
-
-#: saml2_endpoints.py:1487
-msgid "fedTerm/SP UI: No such identity provider."
-msgstr ""
-
-#: saml2_endpoints.py:1497
-msgid "fedTerm/SP UI: Not a valid federation"
-msgstr ""
-
-#: saml2_endpoints.py:1513
-#, python-format
-msgid "fedTerm/SP UI: %s"
-msgstr ""
-
-#: saml2_endpoints.py:1521 saml2_endpoints.py:1552
-#, python-format
-msgid "fedTerm/SP SOAP: %s"
-msgstr ""
-
-#: saml2_endpoints.py:1530
-msgid ""
-"fedTerm/SP SOAP: Unable to perform SOAP defederation "
-"request"
-msgstr ""
-
-#: saml2_endpoints.py:1539 saml2_endpoints.py:1573
-#, python-format
-msgid "fedTerm/SP Redirect: %s"
-msgstr ""
-
-#: saml2_endpoints.py:1561
-msgid ""
-"fedTerm/SP SOAP: Unable to perform SOAP defederation request"
-msgstr ""
-
-#: saml2_endpoints.py:1578
-msgid "Unknown HTTP method."
-msgstr ""
-
-#: saml2_endpoints.py:1591
-msgid "fedTerm/SP Redirect: Service provider not configured"
-msgstr ""
-
-#: saml2_endpoints.py:1599
-msgid "fedTerm/SP Redirect: Error managing manage dump"
-msgstr ""
-
-#: saml2_endpoints.py:1614
-msgid "fedTerm/SP Redirect: Defederation failed"
-msgstr ""
-
-#: saml2_endpoints.py:1640
-#, python-format
-msgid "fedTerm/Return: provider %r unknown"
-msgstr ""
-
-#: saml2_endpoints.py:1647
-#, python-format
-msgid "fedTerm/manage_name_id_return: %s"
-msgstr ""
-
-#: saml2_endpoints.py:1695
-#, python-format
-msgid "fedTerm/SOAP: provider %r unknown"
-msgstr ""
-
-#: saml2_endpoints.py:1888
-msgid "Successful federation deletion."
-msgstr ""
-
-#: utils.py:42
-#, python-format
-msgid "An error happened. Report this %s to the administrator."
-msgstr ""
-
-#: templates/error_authsaml2.html:8
-msgid "Back"
-msgstr "Retour"
-
-#: templates/profile.html:3
-msgid "SAML2 Federations"
-msgstr "Fédérations SAML2"
-
-#: templates/profile.html:9
-msgid "Delete a federation?"
-msgstr "Supprimer une fédération ?"
-
-#: templates/profile.html:15
-msgid "Delete"
-msgstr "Supprimer"
-
-#: templates/profile.html:23
-msgid "Add a federation?"
-msgstr "Ajouter une fédération ?"
-
-#: templates/profile.html:27 templates/auth/saml2/account_linking.html:32
-#: templates/auth/saml2/login_form.html:6
-msgid "Log in"
-msgstr "S'identifier"
-
-#: templates/auth/saml2/account_linking.html:5
-msgid "Log in to link your account"
-msgstr "Connectez-vous pour lier vos comptes"
-
-#: templates/auth/saml2/account_linking.html:9
-msgid "Log in to link with your existing account"
-msgstr "Connectez-vous pour lier avec un compte existant"
-
-#: templates/auth/saml2/account_linking.html:17
-#: templates/auth/saml2/account_linking.html:24
-msgid "Username:"
-msgstr "Nom d'utilisateur :"
-
-#: templates/auth/saml2/account_linking.html:20
-#: templates/auth/saml2/account_linking.html:28
-msgid "Password:"
-msgstr "Mot de passe :"
-
-#: templates/auth/saml2/logout.html:5
-msgid "Logout"
-msgstr "Déconnexion"
-
-#: templates/auth/saml2/logout.html:18
-msgid "Continue logout"
-msgstr "Continuer la déconnexion"
diff --git a/authentic2/authsaml2/migrations/0001_initial.py b/authentic2/authsaml2/migrations/0001_initial.py
deleted file mode 100644
index 0fcad4fff..000000000
--- a/authentic2/authsaml2/migrations/0001_initial.py
+++ /dev/null
@@ -1,122 +0,0 @@
-# encoding: utf-8
-import datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-class Migration(SchemaMigration):
-
- def forwards(self, orm):
-
- # Adding model 'AuthorizationAttributeMap'
- db.create_table('authsaml2_authorizationattributemap', (
- ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
- ('name', self.gf('django.db.models.fields.CharField')(unique=True, max_length=40)),
- ))
- db.send_create_signal('authsaml2', ['AuthorizationAttributeMap'])
-
- # Adding model 'AttributeMapping'
- db.create_table('authsaml2_attributemapping', (
- ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
- ('source_attribute_name', self.gf('django.db.models.fields.CharField')(max_length=40)),
- ('attribute_value_format', self.gf('django.db.models.fields.CharField')(max_length=40)),
- ('attribute_name', self.gf('django.db.models.fields.CharField')(max_length=40)),
- ('attribute_value', self.gf('django.db.models.fields.CharField')(max_length=40)),
- ('map', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['authsaml2.AuthorizationAttributeMap'])),
- ))
- db.send_create_signal('authsaml2', ['AttributeMapping'])
-
- # Adding model 'IdPOptionsPolicy'
- db.create_table('authsaml2_idpoptionspolicy', (
- ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
- ('name', self.gf('django.db.models.fields.CharField')(unique=True, max_length=80)),
- ('enabled', self.gf('django.db.models.fields.BooleanField')(default=False)),
- ('no_nameid_policy', self.gf('django.db.models.fields.BooleanField')(default=False)),
- ('requested_name_id_format', self.gf('django.db.models.fields.CharField')(default='none', max_length=20)),
- ('transient_is_persistent', self.gf('django.db.models.fields.BooleanField')(default=False)),
- ('allow_create', self.gf('django.db.models.fields.BooleanField')(default=False)),
- ('enable_binding_for_sso_response', self.gf('django.db.models.fields.BooleanField')(default=False)),
- ('binding_for_sso_response', self.gf('django.db.models.fields.CharField')(default='urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact', max_length=60)),
- ('enable_http_method_for_slo_request', self.gf('django.db.models.fields.BooleanField')(default=False)),
- ('http_method_for_slo_request', self.gf('django.db.models.fields.IntegerField')(default=4, max_length=60)),
- ('enable_http_method_for_defederation_request', self.gf('django.db.models.fields.BooleanField')(default=False)),
- ('http_method_for_defederation_request', self.gf('django.db.models.fields.IntegerField')(default=5, max_length=60)),
- ('user_consent', self.gf('django.db.models.fields.CharField')(default='urn:oasis:names:tc:SAML:2.0:consent:current-implicit', max_length=60)),
- ('want_force_authn_request', self.gf('django.db.models.fields.BooleanField')(default=False)),
- ('want_is_passive_authn_request', self.gf('django.db.models.fields.BooleanField')(default=False)),
- ('want_authn_request_signed', self.gf('django.db.models.fields.BooleanField')(default=False)),
- ('attribute_map', self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='authorization_attributes', null=True, to=orm['authsaml2.AuthorizationAttributeMap'])),
- ))
- db.send_create_signal('authsaml2', ['IdPOptionsPolicy'])
-
- # Adding model 'MyServiceProvider'
- db.create_table('authsaml2_myserviceprovider', (
- ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
- ('handle_persistent', self.gf('django.db.models.fields.CharField')(max_length=80)),
- ('handle_transient', self.gf('django.db.models.fields.CharField')(max_length=80)),
- ('back_url', self.gf('django.db.models.fields.CharField')(max_length=80)),
- ))
- db.send_create_signal('authsaml2', ['MyServiceProvider'])
-
-
- def backwards(self, orm):
-
- # Deleting model 'AuthorizationAttributeMap'
- db.delete_table('authsaml2_authorizationattributemap')
-
- # Deleting model 'AttributeMapping'
- db.delete_table('authsaml2_attributemapping')
-
- # Deleting model 'IdPOptionsPolicy'
- db.delete_table('authsaml2_idpoptionspolicy')
-
- # Deleting model 'MyServiceProvider'
- db.delete_table('authsaml2_myserviceprovider')
-
-
- models = {
- 'authsaml2.attributemapping': {
- 'Meta': {'object_name': 'AttributeMapping'},
- 'attribute_name': ('django.db.models.fields.CharField', [], {'max_length': '40'}),
- 'attribute_value': ('django.db.models.fields.CharField', [], {'max_length': '40'}),
- 'attribute_value_format': ('django.db.models.fields.CharField', [], {'max_length': '40'}),
- 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'map': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['authsaml2.AuthorizationAttributeMap']"}),
- 'source_attribute_name': ('django.db.models.fields.CharField', [], {'max_length': '40'})
- },
- 'authsaml2.authorizationattributemap': {
- 'Meta': {'object_name': 'AuthorizationAttributeMap'},
- 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '40'})
- },
- 'authsaml2.idpoptionspolicy': {
- 'Meta': {'object_name': 'IdPOptionsPolicy'},
- 'allow_create': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'attribute_map': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'authorization_attributes'", 'null': 'True', 'to': "orm['authsaml2.AuthorizationAttributeMap']"}),
- 'binding_for_sso_response': ('django.db.models.fields.CharField', [], {'default': "'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact'", 'max_length': '60'}),
- 'enable_binding_for_sso_response': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'enable_http_method_for_defederation_request': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'enable_http_method_for_slo_request': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'enabled': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'http_method_for_defederation_request': ('django.db.models.fields.IntegerField', [], {'default': '5', 'max_length': '60'}),
- 'http_method_for_slo_request': ('django.db.models.fields.IntegerField', [], {'default': '4', 'max_length': '60'}),
- 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
- 'no_nameid_policy': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'requested_name_id_format': ('django.db.models.fields.CharField', [], {'default': "'none'", 'max_length': '20'}),
- 'transient_is_persistent': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'user_consent': ('django.db.models.fields.CharField', [], {'default': "'urn:oasis:names:tc:SAML:2.0:consent:current-implicit'", 'max_length': '60'}),
- 'want_authn_request_signed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'want_force_authn_request': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'want_is_passive_authn_request': ('django.db.models.fields.BooleanField', [], {'default': 'False'})
- },
- 'authsaml2.myserviceprovider': {
- 'Meta': {'object_name': 'MyServiceProvider'},
- 'back_url': ('django.db.models.fields.CharField', [], {'max_length': '80'}),
- 'handle_persistent': ('django.db.models.fields.CharField', [], {'max_length': '80'}),
- 'handle_transient': ('django.db.models.fields.CharField', [], {'max_length': '80'}),
- 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
- }
- }
-
- complete_apps = ['authsaml2']
diff --git a/authentic2/authsaml2/migrations/0002_auto__del_authorizationattributemap__del_idpoptionspolicy__del_attribu.py b/authentic2/authsaml2/migrations/0002_auto__del_authorizationattributemap__del_idpoptionspolicy__del_attribu.py
deleted file mode 100644
index 20c0e0dc2..000000000
--- a/authentic2/authsaml2/migrations/0002_auto__del_authorizationattributemap__del_idpoptionspolicy__del_attribu.py
+++ /dev/null
@@ -1,75 +0,0 @@
-# encoding: utf-8
-import datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-class Migration(SchemaMigration):
-
- def forwards(self, orm):
-
- # Deleting model 'AuthorizationAttributeMap'
- db.delete_table('authsaml2_authorizationattributemap')
-
- # Deleting model 'IdPOptionsPolicy'
- db.delete_table('authsaml2_idpoptionspolicy')
-
- # Deleting model 'AttributeMapping'
- db.delete_table('authsaml2_attributemapping')
-
-
- def backwards(self, orm):
-
- # Adding model 'AuthorizationAttributeMap'
- db.create_table('authsaml2_authorizationattributemap', (
- ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
- ('name', self.gf('django.db.models.fields.CharField')(max_length=40, unique=True)),
- ))
- db.send_create_signal('authsaml2', ['AuthorizationAttributeMap'])
-
- # Adding model 'IdPOptionsPolicy'
- db.create_table('authsaml2_idpoptionspolicy', (
- ('enable_http_method_for_defederation_request', self.gf('django.db.models.fields.BooleanField')(default=False)),
- ('name', self.gf('django.db.models.fields.CharField')(max_length=80, unique=True)),
- ('http_method_for_defederation_request', self.gf('django.db.models.fields.IntegerField')(default=5, max_length=60)),
- ('binding_for_sso_response', self.gf('django.db.models.fields.CharField')(default='urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact', max_length=60)),
- ('enabled', self.gf('django.db.models.fields.BooleanField')(default=False)),
- ('allow_create', self.gf('django.db.models.fields.BooleanField')(default=False)),
- ('enable_http_method_for_slo_request', self.gf('django.db.models.fields.BooleanField')(default=False)),
- ('http_method_for_slo_request', self.gf('django.db.models.fields.IntegerField')(default=4, max_length=60)),
- ('requested_name_id_format', self.gf('django.db.models.fields.CharField')(default='none', max_length=20)),
- ('attribute_map', self.gf('django.db.models.fields.related.ForeignKey')(related_name='authorization_attributes', null=True, to=orm['authsaml2.AuthorizationAttributeMap'], blank=True)),
- ('user_consent', self.gf('django.db.models.fields.CharField')(default='urn:oasis:names:tc:SAML:2.0:consent:current-implicit', max_length=60)),
- ('no_nameid_policy', self.gf('django.db.models.fields.BooleanField')(default=False)),
- ('transient_is_persistent', self.gf('django.db.models.fields.BooleanField')(default=False)),
- ('want_authn_request_signed', self.gf('django.db.models.fields.BooleanField')(default=False)),
- ('want_is_passive_authn_request', self.gf('django.db.models.fields.BooleanField')(default=False)),
- ('enable_binding_for_sso_response', self.gf('django.db.models.fields.BooleanField')(default=False)),
- ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
- ('want_force_authn_request', self.gf('django.db.models.fields.BooleanField')(default=False)),
- ))
- db.send_create_signal('authsaml2', ['IdPOptionsPolicy'])
-
- # Adding model 'AttributeMapping'
- db.create_table('authsaml2_attributemapping', (
- ('map', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['authsaml2.AuthorizationAttributeMap'])),
- ('attribute_name', self.gf('django.db.models.fields.CharField')(max_length=40)),
- ('source_attribute_name', self.gf('django.db.models.fields.CharField')(max_length=40)),
- ('attribute_value_format', self.gf('django.db.models.fields.CharField')(max_length=40)),
- ('attribute_value', self.gf('django.db.models.fields.CharField')(max_length=40)),
- ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
- ))
- db.send_create_signal('authsaml2', ['AttributeMapping'])
-
-
- models = {
- 'authsaml2.myserviceprovider': {
- 'Meta': {'object_name': 'MyServiceProvider'},
- 'back_url': ('django.db.models.fields.CharField', [], {'max_length': '80'}),
- 'handle_persistent': ('django.db.models.fields.CharField', [], {'max_length': '80'}),
- 'handle_transient': ('django.db.models.fields.CharField', [], {'max_length': '80'}),
- 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
- }
- }
-
- complete_apps = ['authsaml2']
diff --git a/authentic2/authsaml2/migrations/0003_auto__del_myserviceprovider.py b/authentic2/authsaml2/migrations/0003_auto__del_myserviceprovider.py
deleted file mode 100644
index 55425950f..000000000
--- a/authentic2/authsaml2/migrations/0003_auto__del_myserviceprovider.py
+++ /dev/null
@@ -1,31 +0,0 @@
-# encoding: utf-8
-import datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-class Migration(SchemaMigration):
-
- def forwards(self, orm):
-
- # Deleting model 'MyServiceProvider'
- db.delete_table('authsaml2_myserviceprovider')
-
-
- def backwards(self, orm):
-
- # Adding model 'MyServiceProvider'
- db.create_table('authsaml2_myserviceprovider', (
- ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
- ('handle_persistent', self.gf('django.db.models.fields.CharField')(max_length=80)),
- ('handle_transient', self.gf('django.db.models.fields.CharField')(max_length=80)),
- ('back_url', self.gf('django.db.models.fields.CharField')(max_length=80)),
- ))
- db.send_create_signal('authsaml2', ['MyServiceProvider'])
-
-
- models = {
-
- }
-
- complete_apps = ['authsaml2']
diff --git a/authentic2/authsaml2/migrations/__init__.py b/authentic2/authsaml2/migrations/__init__.py
deleted file mode 100644
index e69de29bb..000000000
diff --git a/authentic2/authsaml2/models.py b/authentic2/authsaml2/models.py
deleted file mode 100644
index 24672e9a4..000000000
--- a/authentic2/authsaml2/models.py
+++ /dev/null
@@ -1,92 +0,0 @@
-from django.db import models
-from django.utils.translation import ugettext_lazy as _
-from django.db.models.manager import EmptyManager
-from django.contrib.auth.models import _user_get_all_permissions, _user_has_perm, _user_has_module_perms
-
-
-class FakePk:
- name = 'pk'
-
-class FakeMeta:
- pk = FakePk()
-
-class SAML2TransientUser(object):
- '''Class compatible with django.contrib.auth.models.User
- which represent an user authenticated using a Transient
- federation'''
- id = None
- pk = None
- is_staff = False
- is_active = False
- is_superuser = False
- _groups = EmptyManager()
- _user_permissions = EmptyManager()
- _meta = FakeMeta()
-
- def __init__(self, id):
- self.id = id
- self.pk = id
-
- def __unicode__(self):
- return 'AnonymousUser'
-
- def __str__(self):
- return unicode(self).encode('utf-8')
-
- def __eq__(self, other):
- return isinstance(other, self.__class__)
-
- def __ne__(self, other):
- return not self.__eq__(other)
-
- def __hash__(self):
- return 1 # instances always return the same hash value
-
- def save(self, **kwargs):
- pass
-
- def delete(self):
- raise NotImplementedError
-
- def set_password(self, raw_password):
- raise NotImplementedError
-
- def check_password(self, raw_password):
- raise NotImplementedError
-
- def _get_groups(self):
- return self._groups
- groups = property(_get_groups)
-
- def _get_user_permissions(self):
- return self._user_permissions
- user_permissions = property(_get_user_permissions)
-
- def get_group_permissions(self, obj=None):
- return set()
-
- def get_all_permissions(self, obj=None):
- return _user_get_all_permissions(self, obj=obj)
-
- def has_perm(self, perm, obj=None):
- return _user_has_perm(self, perm, obj=obj)
-
- def has_perms(self, perm_list, obj=None):
- for perm in perm_list:
- if not self.has_perm(perm, obj):
- return False
- return True
-
- def has_module_perms(self, module):
- return _user_has_module_perms(self, module)
-
- def is_anonymous(self):
- #XXX: Should return True
- return False
-
- def is_authenticated(self):
- return True
-
- def get_username(self):
- return _('Anonymous')
- username = property(get_username)
diff --git a/authentic2/authsaml2/saml2_endpoints.py b/authentic2/authsaml2/saml2_endpoints.py
deleted file mode 100644
index 5abbc3d29..000000000
--- a/authentic2/authsaml2/saml2_endpoints.py
+++ /dev/null
@@ -1,1745 +0,0 @@
-"""SAML2.0 SP implementation"""
-
-import logging
-import urlparse
-import urllib
-
-import lasso
-
-import authentic2.idp.views as idp_views
-
-from django.conf import settings
-from django.core.urlresolvers import reverse
-from django.shortcuts import render_to_response
-from django.http import HttpResponse, HttpResponseRedirect, \
- HttpResponseBadRequest, HttpResponseForbidden
-from django.views.decorators.csrf import csrf_exempt
-from django.template import RequestContext
-from django.template.loader import render_to_string
-from django.contrib.auth import login as auth_login, authenticate
-from django.contrib.auth import logout as auth_logout
-from django.contrib.auth import REDIRECT_FIELD_NAME
-from django.contrib.auth.forms import AuthenticationForm
-from django.contrib.auth.decorators import login_required
-from django.contrib import messages
-from django.utils.translation import ugettext as _
-from django.utils.http import urlquote
-
-from authentic2.saml.common import get_idp_list, load_provider, \
- return_saml2_request, get_saml2_request_message, get_saml2_query_request, \
- get_saml2_post_response, soap_call, \
- lookup_federation_by_name_identifier, get_authorization_policy, \
- get_idp_options_policy, save_session, \
- add_federation, load_session, send_soap_request, \
- redirect_next, delete_session, SOAPException, \
- remove_liberty_session_sp, get_session_index, get_soap_message, \
- load_federation, save_manage, lookup_federation_by_user, \
- get_manage_dump, get_saml2_metadata, create_saml2_server, \
- maintain_liberty_session_on_service_provider, \
- get_session_not_on_or_after, \
- AUTHENTIC_STATUS_CODE_UNKNOWN_PROVIDER, \
- AUTHENTIC_STATUS_CODE_INTERNAL_SERVER_ERROR, \
- AUTHENTIC_STATUS_CODE_UNAUTHORIZED, \
- get_sp_options_policy, get_entity_id
-from authentic2.saml.models import LibertyProvider, LibertyFederation, \
- LibertySessionSP, LibertySessionDump, LIBERTY_SESSION_DUMP_KIND_SP, \
- save_key_values, NAME_ID_FORMATS, LibertySession, \
- get_and_delete_key_values
-from authentic2.saml.saml2utils import authnresponse_checking, \
- get_attributes_from_assertion
-from authentic2.idp.saml.saml2_endpoints import return_logout_error
-from authentic2.authsaml2.utils import error_page, register_next_target, \
- register_request_id, get_registered_url, save_federation_temp, \
- load_federation_temp
-from authentic2.authsaml2 import signals
-from authentic2.authsaml2.backends import AuthSAML2PersistentBackend
-from authentic2.utils import cache_and_validate, flush_django_session
-
-__logout_redirection_timeout = getattr(settings, 'IDP_LOGOUT_TIMEOUT', 600)
-
-logger = logging.getLogger(__name__)
-
-metadata_map = (
- ('AssertionConsumerService',
- lasso.SAML2_METADATA_BINDING_ARTIFACT,
- '/singleSignOnArtifact'),
- ('AssertionConsumerService',
- lasso.SAML2_METADATA_BINDING_POST,
- '/singleSignOnPost'),
- ('SingleLogoutService',
- lasso.SAML2_METADATA_BINDING_REDIRECT,
- '/singleLogout', '/singleLogoutReturn'),
- ('SingleLogoutService',
- lasso.SAML2_METADATA_BINDING_SOAP,
- '/singleLogoutSOAP'),
- ('ManageNameIDService',
- lasso.SAML2_METADATA_BINDING_SOAP,
- '/manageNameIdSOAP'),
- ('ManageNameIDService',
- lasso.SAML2_METADATA_BINDING_REDIRECT,
- '/manageNameId', '/manageNameIdReturn'),
-)
-metadata_options = {'key': settings.SAML_SIGNATURE_PUBLIC_KEY}
-try:
- if settings.SHOW_DISCO_IN_MD:
- metadata_options['disco'] = ('/discoveryReturn', )
-except:
- pass
-
-@cache_and_validate(settings.LOCAL_METADATA_CACHE_TIMEOUT)
-def metadata(request):
- '''Endpoint to retrieve the metadata file'''
- logger.info('metadata: return metadata')
- return HttpResponse(get_metadata(request, request.path),
- mimetype='text/xml')
-
-
-##############################################################
-#
-# Discovery service Requester
-# See Identity Provider Discovery Service Protocol and Profile
-# OASIS Committee Specification 01
-# 27 March 2008
-#
-##############################################################
-def build_discovery_url(request):
- target = None
- returnIDParam = None
- try:
- target = settings.DISCO_SERVICE_NAME
- returnIDParam = settings.DISCO_RETURN_ID_PARAM
- except:
- logger.error('build_discovery_url: missing parameter in settings')
- return None
- _return = urlquote(request.build_absolute_uri(reverse(disco_response)))
- query = 'entityID=%s&return=%s&returnIDParam=%s' \
- % (urlquote(request.build_absolute_uri(reverse(metadata))),
- _return, returnIDParam)
- try:
- scheme, netloc, path, params, query, fragment = urlparse.urlparse(target)
- return urlparse.urlunparse((scheme, netloc, path, params, query,
- fragment))
- except Exception, e:
- logger.error('build_discovery_url: Exception %s' % str(e))
- return None
-
-
-def redirect_to_disco(request):
- register_next_target(request)
- url = build_discovery_url(request)
- if not url:
- return error_page(request,
- _('redirect_to_disco: unable to build disco request'),
- logger=logger)
- return HttpResponseRedirect(url)
-
-
-def disco_response(request):
- if not request.method == "GET":
- message = _('disco_response: HTTP request not supported %s' \
- % request.method)
- return error_page(request, message, logger=logger)
- provider = request.GET.get(settings.DISCO_RETURN_ID_PARAM, '')
- if provider:
- request.session['prefered_idp'] = provider
- logger.info('disco_response: discovered %s' % provider)
- else:
- logger.warn('disco_response: No provider discovered')
- return HttpResponseRedirect(get_registered_url(request))
-
-
-###
- # sso
- # @request
- # @entity_id: Provider ID to request
- #
- # Single SignOn request initiated from SP UI
- # Binding supported: Redirect
- ###
-def sso(request, is_passive=None, force_authn=None, http_method=None):
- '''Django view initiating an AuthnRequesst toward an identity provider.
-
- Keyword arguments:
- entity_id -- the SAMLv2 entity id identifier targeted by the
- AuthnRequest, it should be resolvable to a metadata document.
- is_passive -- whether to let the identity provider passively, i.e.
- without user interaction, authenticate the user.
- force_authn -- whether to ask the identity provider to authenticate the
- user even if it is already authenticated.
- '''
- entity_id = request.REQUEST.get('entity_id')
- # 1. Save the target page
- logger.info('sso: save next url in session %s' \
- % request.session.session_key)
- register_next_target(request)
-
- # 2. Init the server object
- server = build_service_provider(request)
- if not server:
- return error_page(request,
- _('sso: Service provider not configured'), logger=logger)
- # 3. Define the provider or ask the user
- if not entity_id:
- providers_list = get_idp_list()
- if not providers_list:
- return error_page(request,
- _('sso: Service provider not configured'), logger=logger)
- if providers_list.count() == 1:
- p = providers_list[0]
- else:
- logger.error('sso: No SAML2 identity provider selected')
- return error_page(request,
- _('sso: No SAML2 identity provider selected'),
- logger=logger)
- else:
- logger.info('sso: sso with provider %s' % entity_id)
- p = load_provider(request, entity_id, server=server, sp_or_idp='idp',
- autoload=True)
- if not p:
- return error_page(request,
- _('sso: The provider does not exist'), logger=logger)
- # 4. Build authn request
- login = lasso.Login(server)
- if not login:
- return error_page(request,
- _('sso: Unable to create Login object'), logger=logger)
- # Only redirect is necessary for the authnrequest
- if not http_method:
- http_method = server.getFirstHttpMethod(server.providers[p.entity_id],
- lasso.MD_PROTOCOL_TYPE_SINGLE_SIGN_ON)
- logger.debug('sso: \
- No http method given. Method infered: %s' % http_method)
- if http_method == lasso.HTTP_METHOD_NONE:
- return error_page(request,
- _('sso: %s does not have any supported SingleSignOn endpoint') \
- % entity_id, logger=logger)
- try:
- login.initAuthnRequest(p.entity_id, http_method)
- except lasso.Error, error:
- return error_page(request,
- _('sso: initAuthnRequest %s') % lasso.strError(error[0]),
- logger=logger)
-
- # 5. Request setting
- if not setAuthnrequestOptions(p, login, force_authn, is_passive):
- logger.error('sso: No policy defined')
- return error_page(request, _('sso: No IdP policy defined'),
- logger=logger)
- try:
- login.buildAuthnRequestMsg()
- except lasso.Error, error:
- return error_page(request,
- _('SSO: buildAuthnRequestMsg %s') % lasso.strError(error[0]),
- logger=logger)
-
- # 6. Save the request ID (association with the target page)
- logger.debug('sso: Authnrequest ID: %s' % login.request.iD)
- logger.debug('sso: Save request id in the session %s' \
- % request.session.session_key)
- register_request_id(request, login.request.iD)
-
- # 7. Redirect the user
- logger.debug('sso: user redirection')
- return return_saml2_request(request, login,
- title=('AuthnRequest for %s' % entity_id))
-
-
-###
- # singleSignOnArtifact, singleSignOnPostOrRedirect
- # @request
- #
- # Single SignOn Response
- # Binding supported: Artifact, POST
- ###
-def singleSignOnArtifact(request):
- logger.info('singleSignOnArtifact: Binding Artifact processing begins...')
- server = build_service_provider(request)
- if not server:
- return error_page(request,
- _('singleSignOnArtifact: Service provider not configured'),
- logger=logger)
-
- # Load the provider metadata using the artifact
- if request.method == 'GET':
- logger.debug('singleSignOnArtifact: GET')
- artifact = request.REQUEST.get('SAMLart')
- else:
- logger.debug('singleSignOnArtifact: POST')
- artifact = request.POST.get('SAMLart')
- logger.debug('singleSignOnArtifact: artifact %s' % artifact)
- p = LibertyProvider.get_provider_by_samlv2_artifact(artifact)
- p = load_provider(request, p.entity_id, server=server, sp_or_idp='idp')
- logger.info('singleSignOnArtifact: provider %s loaded' % p.entity_id)
-
- login = lasso.Login(server)
- if not login:
- return error_page(request,
- _('singleSignOnArtifact: Unable to create Login object'),
- logger=logger)
-
- message = get_saml2_request_message(request)
- if not message:
- return error_page(request,
- _('singleSignOnArtifact: No message given.'), logger=logger)
- #logger.debug('singleSignOnArtifact: message %s' % message)
-
- while True:
- logger.debug('singleSignOnArtifact: Authnresponse processing')
- try:
- if request.method == 'GET':
- login.initRequest(get_saml2_query_request(request),
- lasso.HTTP_METHOD_ARTIFACT_GET)
- else:
- login.initRequest(artifact, lasso.HTTP_METHOD_ARTIFACT_POST)
- break
- except (lasso.ServerProviderNotFoundError,
- lasso.ProfileUnknownProviderError):
- logger.debug('singleSignOnArtifact: Unable to process \
- Authnresponse -load another provider')
- provider_id = login.remoteProviderId
- provider_loaded = load_provider(request, provider_id,
- server=server, sp_or_idp='idp')
-
- if not provider_loaded:
- message = _('singleSignOnArtifact: provider %r unknown') \
- % provider_id
- return error_page(request, message, logger=logger)
- else:
- logger.info('singleSignOnArtifact: \
- provider %s loaded' % provider_id)
- continue
- except lasso.Error, error:
- return error_page(request,
- _('singleSignOnArtifact: initRequest %s') \
- % lasso.strError(error[0]),
- logger=logger)
-
- try:
- login.buildRequestMsg()
- except lasso.Error, error:
- return error_page(request,
- _('singleSignOnArtifact: buildRequestMsg %s') \
- % lasso.strError(error[0]), logger=logger)
-
- # TODO: Client certificate
- client_cert = None
- try:
- logger.info('singleSignOnArtifact: soap call to %s' % login.msgUrl)
- logger.debug('singleSignOnArtifact: soap message %s' % login.msgBody)
- soap_answer = soap_call(login.msgUrl,
- login.msgBody, client_cert=client_cert)
- except Exception:
- return error_page(request,
- _('singleSignOnArtifact: Failure to communicate \
- with artifact resolver %r') % login.msgUrl,
- logger=logger)
- if not soap_answer:
- return error_page(request,
- _('singleSignOnArtifact: Artifact resolver at %r returned \
- an empty response') % login.msgUrl,
- logger=logger)
-
- logger.debug('singleSignOnArtifact: soap answer %s' % soap_answer)
-
- # If connexion over HTTPS, do not check signature?!
- if login.msgUrl.startswith('https'):
- logger.debug('singleSignOnArtifact: \
- artifact solved over HTTPS - Signature Hint forbidden')
- login.setSignatureVerifyHint(lasso.PROFILE_SIGNATURE_HINT_FORBID)
-
- try:
- login.processResponseMsg(soap_answer)
- except lasso.Error, error:
- return error_page(request,
- _('singleSignOnArtifact: processResponseMsg raised %s') \
- % lasso.strError(error[0]), logger=logger)
-
- # TODO: Relay State
-
- logger.info('singleSignOnArtifact: Binding artifact treatment terminated')
- return sso_after_response(request, login, provider=p)
-
-
-@csrf_exempt
-def singleSignOnPost(request):
- logger.info('singleSignOnPost: Binding POST processing begins...')
- server = build_service_provider(request)
- if not server:
- return error_page(request,
- _('singleSignOnPost: Service provider not configured'),
- logger=logger)
-
- login = lasso.Login(server)
- if not login:
- return error_page(request,
- _('singleSignOnPost: Unable to create Login object'),
- logger=logger)
-
- # TODO: check messages = get_saml2_request_message(request)
-
- # Binding POST
- message = get_saml2_post_response(request)
- if not message:
- return error_page(request,
- _('singleSignOnPost: No message given.'), logger=logger)
- logger.debug('singleSignOnPost: message %s' % message)
-
- ''' Binding REDIRECT
-
- According to: saml-profiles-2.0-os
- The HTTP Redirect binding MUST NOT be used,
- as the response will typically exceed the
- URL length permitted by most user agents.
- '''
- # if not message:
- # message = request.META.get('QUERY_STRING', '')
-
- while True:
- logger.debug('singleSignOnPost: Authnresponse processing')
- try:
- login.processAuthnResponseMsg(message)
- break
- except (lasso.ServerProviderNotFoundError,
- lasso.ProfileUnknownProviderError):
- logger.debug('singleSignOnPost: \
- Unable to process Authnresponse - load another provider')
- provider_id = login.remoteProviderId
- provider_loaded = load_provider(request, provider_id,
- server=server, sp_or_idp='idp')
-
- if not provider_loaded:
- message = _('singleSignOnPost: provider %r unknown' \
- % provider_id)
- return error_page(request, message, logger=logger)
- else:
- logger.info('singleSignOnPost: \
- provider %s loaded' % provider_id)
- continue
- except lasso.Error, error:
- logger.debug('singleSignOnPost: lasso error, login dump is %s' \
- % login.dump())
- return error_page(request,
- _('singleSignOnPost: %s') % lasso.strError(error[0]),
- logger=logger)
-
- logger.info('singleSignOnPost: Binding POST treatment terminated')
- return sso_after_response(request, login, provider=provider_loaded)
-
-
-###
- # sso_after_response
- # @request
- # @login
- # @relay_state
- #
- # Post-authnrequest processing
- ###
-def sso_after_response(request, login, relay_state=None, provider=None):
- logger.info('sso_after_response: Authnresponse processing begins...')
-
- subject_confirmation = request.build_absolute_uri().partition('?')[0]
- saml_request_id = request.session.get('saml_request_id')
- check = authnresponse_checking(login, subject_confirmation, logger, saml_request_id=saml_request_id)
- if not check:
- return error_page(request,
- _('sso_after_response: error checking authn response'), logger=logger)
-
- try:
- login.acceptSso()
- except lasso.Error, error:
- return error_page(request,
- _('sso_after_response: acceptSso raised %s') \
- % lasso.strError(error[0]), logger=logger)
-
- logger.info('sso_after_response: \
- Assertion processing terminated with success')
-
- attributes = get_attributes_from_assertion(login.assertion, logger)
- # Register attributes in session for other applications
- request.session['attributes'] = attributes
-
- attrs = {}
-
- for att_statement in login.assertion.attributeStatement:
- for attribute in att_statement.attribute:
- name = None
- format = lasso.SAML2_ATTRIBUTE_NAME_FORMAT_BASIC
- nickname = None
- try:
- name = attribute.name.decode('ascii')
- except:
- logger.warning('sso_after_response: error decoding name of \
- attribute %s' % attribute.dump())
- else:
- try:
- if attribute.nameFormat:
- format = attribute.nameFormat.decode('ascii')
- if attribute.friendlyName:
- nickname = attribute.friendlyName
- except Exception, e:
- message = 'sso_after_response: name or format of an \
- attribute failed to decode as ascii: %s due to %s'
- logger.warning(message % (attribute.dump(), str(e)))
- try:
- if name:
- if format:
- if nickname:
- key = (name, format, nickname)
- else:
- key = (name, format)
- else:
- key = (name)
- attrs[key] = list()
- for value in attribute.attributeValue:
- content = [any.exportToXml() for any in value.any]
- content = ''.join(content)
- attrs[key].append(content.decode('utf8'))
- except Exception, e:
- message = 'sso_after_response: value of an \
- attribute failed to decode as ascii: %s due to %s'
- logger.warning(message % (attribute.dump(), str(e)))
-
- if not 'multisource_attributes' in request.session:
- request.session['multisource_attributes'] = dict()
- request.\
- session['multisource_attributes'][login.assertion.issuer.content] = \
- list()
- a8n = dict()
- a8n['certificate_type'] = 'SAML2_assertion'
- try:
- a8n['nameid'] = \
- login.assertion.subject.nameID.content
- except:
- pass
- try:
- a8n['subject_confirmation_method'] = \
- login.assertion.subject.subjectConfirmation.method
- except:
- pass
- try:
- a8n['not_before'] = \
- login.assertion.subject. \
- subjectConfirmation.subjectConfirmationData.notBefore
- except:
- pass
- try:
- a8n['not_on_or_after'] = \
- login.assertion.subject.subjectConfirmation. \
- subjectConfirmationData.notOnOrAfter
- except:
- pass
- try:
- a8n['authn_context'] = \
- login.assertion.authnStatement[0]. \
- authnContext.authnContextClassRef
- except:
- pass
- try:
- a8n['authn_instant'] = \
- login.assertion.authnStatement[0].authnInstant
- except:
- pass
- a8n['attributes'] = attrs
- request.\
- session['multisource_attributes'][login.assertion.issuer.content].\
- append(a8n)
- logger.debug('sso_after_response: \
- attributes in assertion %s from %s' \
- % (str(attrs), login.assertion.issuer.content))
- #authncontext
-
- #Access control processing
- decisions = signals.authz_decision.send(sender=None,
- request=request, attributes=attributes, provider=provider)
- if not decisions:
- logger.debug('sso_after_response: No authorization function \
- connected')
-
- access_granted = True
- one_message = False
- for decision in decisions:
- logger.debug('sso_after_response: authorization function %s' \
- % decision[0].__name__)
- dic = decision[1]
- logger.debug('sso_after_response: decision is %s' % dic['authz'])
- if 'message' in dic:
- logger.debug('sso_after_response: with message %s' \
- % dic['message'])
- if not dic['authz']:
- access_granted = False
- if 'message' in dic:
- one_message = True
- messages.add_message(request, messages.ERROR, dic['message'])
-
- if not access_granted:
- if not one_message:
- p = get_authorization_policy(provider)
- messages.add_message(request, messages.ERROR,
- p.default_denial_message)
- return error_page(request,
- logger=logger, default_message=False, timer=True)
-
- #Access granted, now we deal with session management
- policy = get_idp_options_policy(provider)
- if not policy:
- logger.error('sso_after_response: No policy defined')
- return error_page(request,
- _('sso_after_response: No IdP policy defined'), logger=logger)
-
- user = request.user
-
- url = get_registered_url(request)
- if not 'saml_request_id' in request.session:
- #IdP initiated
- url = policy.back_url
- if login.nameIdentifier.format == \
- lasso.SAML2_NAME_IDENTIFIER_FORMAT_TRANSIENT \
- and (policy is None \
- or not policy.transient_is_persistent):
- logger.info('sso_after_response: Transient nameID')
- if policy.handle_transient == 'AUTHSAML2_UNAUTH_TRANSIENT_ASK_AUTH':
- if not request.user.is_authenticated():
- #XXX: To test!
- logger.info('sso_after_response: Account linking required')
- save_session(request, login,
- kind=LIBERTY_SESSION_DUMP_KIND_SP)
- logger.debug('sso_after_response: \
- Register identity dump in session')
- save_federation_temp(request, login, attributes=attributes)
- maintain_liberty_session_on_service_provider(request, login)
- return render_to_response('auth/saml2/account_linking.html',
- context_instance=RequestContext(request))
- logger.debug('sso_after_response: django session opened')
- session_not_on_or_after = \
- get_session_not_on_or_after(login.assertion)
- if session_not_on_or_after:
- request.session.set_expiry(session_not_on_or_after)
- logger.debug('sso_after_response: session set to expire on \
- %s by SessionNotOnOrAfter attribute',
- session_not_on_or_after)
- if request.session.test_cookie_worked():
- request.session.delete_test_cookie()
- save_session(request, login, kind=LIBERTY_SESSION_DUMP_KIND_SP)
- logger.info('sso_after_response: \
- login processing ended with success - redirect to target')
- return HttpResponseRedirect(url)
-
- if policy.handle_transient == \
- 'AUTHSAML2_UNAUTH_TRANSIENT_OPEN_SESSION':
- logger.info('sso_after_response: \
- Opening session for transient with nameID')
- logger.debug('sso_after_response: nameID %s' \
- % login.nameIdentifier.dump())
- user = authenticate(name_id=login.nameIdentifier)
- if not user:
- return error_page(request,
- _('sso_after_response: \
- No backend for temporary federation is configured'),
- logger=logger)
- auth_login(request, user)
- logger.debug('sso_after_response: django session opened')
- session_not_on_or_after = \
- get_session_not_on_or_after(login.assertion)
- if session_not_on_or_after:
- request.session.set_expiry(session_not_on_or_after)
- logger.debug('sso_after_response: session set to expire on \
- %s by SessionNotOnOrAfter attribute',
- session_not_on_or_after)
- signals.auth_login.send(sender=None,
- request=request, attributes=attributes)
- logger.debug('sso_after_response: successful login signal sent')
- if request.session.test_cookie_worked():
- request.session.delete_test_cookie()
- save_session(request, login, kind=LIBERTY_SESSION_DUMP_KIND_SP)
- logger.info('sso_after_response: \
- login processing ended with success - redirect to target')
- return HttpResponseRedirect(url)
- return error_page(request, _('sso_after_response: \
- Transient access policy: Configuration error'),
- logger=logger)
-
- elif login.nameIdentifier.format != \
- lasso.SAML2_NAME_IDENTIFIER_FORMAT_TRANSIENT \
- or (policy is not None and policy.transient_is_persistent):
- #Consider that all kinds of nameId not transient are persistent.
- logger.info('sso_after_response: persistent federation processing')
- if policy is not None and policy.transient_is_persistent and \
- login.nameIdentifier.format == \
- lasso.SAML2_NAME_IDENTIFIER_FORMAT_TRANSIENT:
- logger.info('sso_after_response: \
- the nameId %s is transient the but option persistent '
- 'federation processing is selected' \
- % login.nameIdentifier.dump())
- if policy.persistent_identifier_attribute:
- logger.info('sso_after_response: '
- '%s is used as persistent identifier for federation' % \
- policy.persistent_identifier_attribute)
- identifier = None
- for key in attributes:
- if policy.persistent_identifier_attribute in key \
- and attributes[key]:
- identifier = attributes[key][0]
- break
- if identifier:
- logger.info('sso_after_response: '
- '%s value is %s' % \
- (policy.persistent_identifier_attribute, identifier))
- login.nameIdentifier.content = identifier
- else:
- logger.warn('sso_after_response: '
- '%s not provided by the identity provider, '
- 'we continue with the nameID.' % \
- policy.persistent_identifier_attribute)
- else:
- logger.info('sso_after_response: '
- 'No attribute declared as persistent identifier '
- 'NameID is used.')
- login.nameIdentifier.format = \
- lasso.SAML2_NAME_IDENTIFIER_FORMAT_PERSISTENT
- login.nameIdentifier.nameQualifier = provider.entity_id
-
- user = AuthSAML2PersistentBackend(). \
- authenticate(name_id=login.nameIdentifier,
- provider_id=login.remoteProviderId)
- if not user and \
- policy.handle_persistent == \
- 'AUTHSAML2_UNAUTH_PERSISTENT_CREATE_USER_PSEUDONYMOUS':
- # Auto-create an user then do the authentication again
- logger.info('sso_after_response: Account creation')
- AuthSAML2PersistentBackend(). \
- create_user(name_id=login.nameIdentifier,
- provider_id=provider.entity_id)
- user = AuthSAML2PersistentBackend(). \
- authenticate(name_id=login.nameIdentifier,
- provider_id=login.remoteProviderId)
- if user:
- auth_login(request, user)
- logger.debug('sso_after_response: session opened')
- signals.auth_login.send(sender=None,
- request=request, attributes=attributes)
- logger.debug('sso_after_response: \
- signal sent that the session is opened')
- if request.session.test_cookie_worked():
- request.session.delete_test_cookie()
- save_session(request, login, kind=LIBERTY_SESSION_DUMP_KIND_SP)
- maintain_liberty_session_on_service_provider(request, login)
- logger.info('sso_after_response: \
- Login processing ended with success - redirect to target')
- return HttpResponseRedirect(url)
- elif policy.handle_persistent == \
- 'AUTHSAML2_UNAUTH_PERSISTENT_ACCOUNT_LINKING_BY_AUTH':
- '''Check if the user consent for federation has been given'''
- if policy.force_user_consent \
- and not login.response.consent in \
- ('urn:oasis:names:tc:SAML:2.0:consent:obtained',
- 'urn:oasis:names:tc:SAML:2.0:consent:prior',
- 'urn:oasis:names:tc:SAML:2.0:consent:current-explicit',
- 'urn:oasis:names:tc:SAML:2.0:consent:current-implicit'):
- return error_page(request, _('sso_after_response: You were \
- not asked your consent for account linking'),
- logger=logger)
- if request.user.is_authenticated():
- logger.info('sso_after_response: Add federation')
- add_federation(request.user, name_id=login.nameIdentifier,
- provider_id=login.remoteProviderId)
- return HttpResponseRedirect(url)
- logger.info('sso_after_response: Account linking required')
- save_session(request, login, kind=LIBERTY_SESSION_DUMP_KIND_SP)
- logger.debug('sso_after_response: \
- Register identity dump in session')
- save_federation_temp(request, login, attributes=attributes)
- maintain_liberty_session_on_service_provider(request, login)
- return render_to_response('auth/saml2/account_linking.html',
- context_instance=RequestContext(request))
- return error_page(request,
- _('sso_after_response: \
- Persistent Account policy: Configuration error'), logger=logger)
-
- return error_page(request,
- _('sso_after_response: \
- Transient access policy: NameId format not supported'), logger=logger)
- #TODO: Relay state
-
-
-###
- # finish_federation
- # @request
- #
- # Called after an account linking.
- # TODO: add checkbox, create new account (settings option, user can choose)
- # Create pseudonymous or user choose or only account linking
- ###
-@csrf_exempt
-def finish_federation(request):
- logger.info('finish_federation: Return after account linking form filled')
- if request.method == "POST":
- form = AuthenticationForm(data=request.POST)
- if form.is_valid():
- logger.info('finish_federation: form valid')
- server = build_service_provider(request)
- if not server:
- return error_page(request,
- _('finish_federation: \
- Service provider not configured'), logger=logger)
-
- login = lasso.Login(server)
- if not login:
- return error_page(request,
- _('finish_federation: \
- Unable to create Login object'), logger=logger)
-
- s = load_session(request, login, kind=LIBERTY_SESSION_DUMP_KIND_SP)
- load_federation_temp(request, login)
- if not login.session:
- return error_page(request,
- _('finish_federation: Error loading session.'),
- logger=logger)
-
- login.nameIdentifier = request.session['nameId']
-
- logger.debug('finish_federation: nameID %s' % \
- login.nameIdentifier.dump())
-
- provider_id = None
- if 'remoteProviderId' in request.session:
- provider_id = request.session['remoteProviderId']
- fed = add_federation(form.get_user(),
- name_id=login.nameIdentifier,
- provider_id=provider_id)
- if not fed:
- return error_page(request,
- _('SSO/finish_federation: \
- Error adding new federation for this user'),
- logger=logger)
-
- logger.info('finish_federation: federation added')
-
- url = get_registered_url(request)
- auth_login(request, form.get_user())
- if request.session.test_cookie_worked():
- request.session.delete_test_cookie()
- logger.debug('finish_federation: session opened')
-
- attributes = []
- if 'attributes' in request.session:
- attributes = request.session['attributes']
- signals.auth_login.send(sender=None,
- request=request, attributes=attributes)
- logger.debug('finish_federation: \
- signal sent that the session is opened')
-
- if s:
- s.delete()
- if login.session:
- login.session.isDirty = True
- if login.identity:
- login.identity.isDirty = True
- save_session(request, login, kind=LIBERTY_SESSION_DUMP_KIND_SP)
- maintain_liberty_session_on_service_provider(request, login)
- logger.info('finish_federation: \
- Login processing ended with success - redirect to target')
- return HttpResponseRedirect(url)
- else:
- # TODO: Error: login failed: message and count 3 attemps
- logger.warning('finish_federation: \
- form not valid - Try again! (Brute force?)')
- return render_to_response('auth/saml2/account_linking.html',
- context_instance=RequestContext(request))
- else:
- return error_page(request,
- _('finish_federation: Unable to perform federation'),
- logger=logger)
-
-
-'''
- Single Logout (SLO)
-
- Initiated by SP or by IdP with SOAP or with Redirect
-'''
-
-
-def ko_icon(request):
- return HttpResponseRedirect('%s/authentic2/images/ko.png' \
- % settings.STATIC_URL)
-
-
-def ok_icon(request):
- return HttpResponseRedirect('%s/authentic2/images/ok.png' \
- % settings.STATIC_URL)
-
-
-def sp_slo(request, provider_id=None):
- '''
- To make another module call the SLO function.
- Does not deal with the local django session.
- '''
- next = request.REQUEST.get('next')
-
- logger.debug('sp_slo: provider_id in parameter %s' % str(provider_id))
-
- if request.method == 'GET' and 'provider_id' in request.GET:
- provider_id = request.GET.get('provider_id')
- logger.debug('sp_slo: provider_id from GET %s' % str(provider_id))
- if request.method == 'POST' and 'provider_id' in request.POST:
- provider_id = request.POST.get('provider_id')
- logger.debug('sp_slo: provider_id from POST %s' % str(provider_id))
- if not provider_id:
- logger.info('sp_slo: to initiate a slo we need a provider_id')
- return redirect_next(request, next) or ko_icon(request)
- logger.info('sp_slo: slo initiated with %(provider_id)s' \
- % {'provider_id': provider_id})
-
- server = create_server(request)
- logout = lasso.Logout(server)
- logger.info('sp_slo: sp_slo for %s' % provider_id)
- load_session(request, logout, kind=LIBERTY_SESSION_DUMP_KIND_SP)
- provider = load_provider(request, provider_id,
- server=server, sp_or_idp='idp')
- if not provider:
- logger.error('sp_slo: sp_slo failed to load provider')
- return redirect_next(request, next) or ko_icon(request)
- policy = get_idp_options_policy(provider)
- if not policy:
- logger.error('sp_slo: No policy found for %s'\
- % provider_id)
- return redirect_next(request, next) or ko_icon(request)
- if not policy.forward_slo:
- logger.warn('sp_slo: slo asked for %s configured to not receive slo' \
- % provider_id)
- return redirect_next(request, next) or ko_icon(request)
- if policy.enable_http_method_for_slo_request \
- and policy.http_method_for_slo_request:
- if policy.http_method_for_slo_request == lasso.HTTP_METHOD_SOAP:
- logger.info('sp_slo: sp_slo by SOAP')
- try:
- logout.initRequest(None, lasso.HTTP_METHOD_SOAP)
- except:
- logger.exception('sp_slo: sp_slo init error')
- return redirect_next(request, next) or ko_icon(request)
- try:
- logout.buildRequestMsg()
- except:
- logger.exception('sp_slo: sp_slo build error')
- return redirect_next(request, next) or ko_icon(request)
- try:
- soap_response = send_soap_request(request, logout)
- except:
- logger.exception('sp_slo: sp_slo SOAP failure')
- return redirect_next(request, next) or ko_icon(request)
- logger.info('sp_slo: successful soap call')
- return process_logout_response(request,
- logout, soap_response, next)
- else:
- try:
- logout.initRequest(None, lasso.HTTP_METHOD_REDIRECT)
- except:
- logger.exception('sp_slo: sp_slo init error')
- return redirect_next(request, next) or ko_icon(request)
- logout.msgRelayState = logout.request.id
- try:
- logout.buildRequestMsg()
- except:
- logger.exception('sp_slo: sp_slo build error')
- return redirect_next(request, next) or ko_icon(request)
- logger.info('sp_slo: sp_slo by redirect')
- save_key_values(logout.request.id,
- logout.dump(), provider_id, next)
- return HttpResponseRedirect(logout.msgUrl)
- try:
- logout.initRequest(provider_id)
- except lasso.ProfileMissingAssertionError:
- logger.error('sp_slo: \
- sp_slo failed because no sessions exists for %r' % provider_id)
- return redirect_next(request, next) or ko_icon(request)
- logout.msgRelayState = logout.request.id
- try:
- logout.buildRequestMsg()
- except:
- logger.exception('sp_slo: sp_slo misc error')
- return redirect_next(request, next) or ko_icon(request)
- # SOAP case
- if logout.msgBody:
- logger.info('sp_slo: sp_slo by SOAP')
- try:
- soap_response = send_soap_request(request, logout)
- except:
- logger.exception('sp_slo: sp_slo SOAP failure')
- return redirect_next(request, next) or ko_icon(request)
- return process_logout_response(request, logout, soap_response, next)
- else:
- logger.info('sp_slo: sp_slo by redirect')
- save_key_values(logout.request.id, logout.dump(), provider_id, next)
- return HttpResponseRedirect(logout.msgUrl)
-
-
-def process_logout_response(request, logout, soap_response, next):
- try:
- logout.processResponseMsg(soap_response)
- except:
- logger.exception('process_logout_response: \
- processResponseMsg raised an exception')
- return redirect_next(request, next) or ko_icon(request)
- else:
- delete_session(request)
- return redirect_next(request, next) or ok_icon(request)
-
-
-def singleLogoutReturn(request):
- '''
- IdP response to a SLO SP initiated by redirect
- '''
- server = build_service_provider(request)
- if not server:
- logger.warn('singleLogoutReturn: Service provider not configured')
- return ko_icon(request)
- query = get_saml2_query_request(request)
- if not query:
- logger.warn('singleLogoutReturn: \
- Unable to handle SLO by Redirect return without LogoutResponse')
- return ko_icon(request)
- logout = lasso.Logout(server)
- if not logout:
- logger.warn('singleLogoutReturn: Unable to create Login object')
- return ko_icon(request)
- load_session(request, logout, kind=LIBERTY_SESSION_DUMP_KIND_SP)
- id = request.REQUEST.get('RelayState', None)
- if not id:
- logger.error('singleLogoutReturn: missing id argument')
- return ko_icon(request)
- logout_dump, provider_id_saved, next = get_and_delete_key_values(id)
- provider_loaded = None
- provider_id = None
- while True:
- try:
- logout.processResponseMsg(query)
- break
- except (lasso.ServerProviderNotFoundError,
- lasso.ProfileUnknownProviderError):
- provider_id = logout.remoteProviderId
- provider_loaded = load_provider(request, provider_id,
- server=server, sp_or_idp='idp')
- if not provider_loaded:
- logger.warn('singleLogoutReturn: provider %r unknown' \
- % provider_id)
- return redirect_next(request, next) or ko_icon(request)
- else:
- continue
- except lasso.Error, error:
- return redirect_next(request, next) or ko_icon(request)
- if provider_id != provider_id_saved:
- logger.warn('singleLogoutReturn: provider mistmatch between %s and %s' \
- % (provider_id, provider_id_saved))
- return redirect_next(request, next) or ko_icon(request)
- if logout.isSessionDirty:
- if logout.session:
- save_session(request, logout, kind=LIBERTY_SESSION_DUMP_KIND_SP)
- else:
- delete_session(request)
- remove_liberty_session_sp(request)
- return redirect_next(request, next) or ok_icon(request)
-
-
-def slo_soap_as_idp(request, logout, session=None):
- logger.debug('slo_soap_as_idp: start slo proxying to sp processing')
- from authentic2.idp.saml import saml2_endpoints
- error = saml2_endpoints. \
- validate_logout_request(request, logout, idp=False)
- if error:
- return error
- if not session:
- key = request.session.session_key
- else:
- key = session.django_session_key
- lib_sessions = LibertySession.objects.filter(
- django_session_key=key)
- if not lib_sessions:
- logger.debug('slo_soap_as_idp: no sp session')
- else:
- server = saml2_endpoints.create_server(request)
- logout2 = lasso.Logout(server)
- for lib_session in lib_sessions:
- logger.info('slo_soap_as_idp: logout to provider %s' \
- % lib_session.provider_id)
- p = load_provider(request, lib_session.provider_id,
- server=server)
- if p:
- policy = get_sp_options_policy(p)
- if not policy:
- logger.error('slo_soap_as_idp: No policy found for %s' \
- % lib_session.provider_id)
- elif not policy.forward_slo:
- logger.info('slo_soap_as_idp: %s configured to not \
- reveive slo' % lib_session.provider_id)
- else:
- try:
- session_dump = saml2_endpoints.build_session_dump([lib_session])
- logout2.setSessionFromDump(session_dump.encode('utf8'))
- logout2.initRequest(None, lasso.HTTP_METHOD_SOAP)
- logout2.buildRequestMsg()
- soap_response = send_soap_request(request, logout2)
- except Exception, e:
- logger.error('slo_soap_as_idp: error building \
- request to provider %s due to %s' \
- % (lib_session.provider_id, str(e)))
- else:
- try:
- logout2.processResponseMsg(soap_response)
- except Exception, e:
- logger.error('slo_soap_as_idp: error received \
- from provider %s due to %s' \
- % (lib_session.provider_id, str(e)))
- else:
- logger.error('slo_soap_as_idp: unable to load provider %s' \
- % lib_session.provider_id)
- logger.debug('slo_soap_as_idp: end slo proxying to sp processing')
-
-
-def common_processing_slo_idp_init_bindings(request, message):
- server = build_service_provider(request)
- if not server:
- return http_response_forbidden_request('common_processing: '
- 'Service provider not configured'), None, None
-
- logout = lasso.Logout(server)
- if not logout:
- return http_response_forbidden_request('common_processing: '
- 'Unable to create Logout object'), None, None
-
- provider_loaded = None
- while True:
- try:
- logout.processRequestMsg(message)
- break
- except (lasso.ServerProviderNotFoundError,
- lasso.ProfileUnknownProviderError):
- provider_id = logout.remoteProviderId
- provider_loaded = load_provider(request, provider_id,
- server=server, sp_or_idp='idp')
-
- if not provider_loaded:
- logger.warn('common_processing: provider %r unknown' \
- % provider_id)
- return return_logout_error(request, logout,
- AUTHENTIC_STATUS_CODE_UNKNOWN_PROVIDER), None, None
- else:
- continue
- except lasso.Error, error:
- return return_logout_error(request, logout,
- AUTHENTIC_STATUS_CODE_INTERNAL_SERVER_ERROR), None, None
-
- policy = get_idp_options_policy(provider_loaded)
- if not policy:
- logger.error('common_processing: No policy found for %s'\
- % logout.remoteProviderId)
- return return_logout_error(request, logout,
- AUTHENTIC_STATUS_CODE_UNAUTHORIZED), None, None
- if not policy.accept_slo:
- logger.warn('common_processing: received slo from %s not authorized'\
- % logout.remoteProviderId)
- return return_logout_error(request, logout,
- AUTHENTIC_STATUS_CODE_UNAUTHORIZED), None, None
-
- # Look for a session index
- try:
- session_index = logout.request.sessionIndex
- except:
- pass
-
- fed = lookup_federation_by_name_identifier(profile=logout)
- if not fed:
- logger.warning('common_processing: unknown user for %s' \
- % logout.request.dump())
- return return_logout_error(request, logout,
- lasso.SAML2_STATUS_CODE_UNKNOWN_PRINCIPAL), None, None
-
- session = None
- try:
- session = LibertySessionSP. \
- objects.get(federation=fed, session_index=session_index)
- except LibertySessionSP.DoesNotExist:
- logger.warning('common_processing: No Liberty session found')
- return return_logout_error(request, logout,
- lasso.SAML2_STATUS_CODE_UNKNOWN_PRINCIPAL), None, None
-
- q = LibertySessionDump. \
- objects.filter(django_session_key=session.django_session_key)
- if not q:
- logger.warning('common_processing: \
- No session dump for this session')
- return return_logout_error(request, logout,
- lasso.SAML2_STATUS_CODE_UNKNOWN_PRINCIPAL), None, None
- logger.info('common_processing: from %s, \
- for session index %s and session %s' % \
- (logout.remoteProviderId, session_index, session.id))
- logout.setSessionFromDump(q[0].session_dump.encode('utf8'))
- q.delete()
-
- try:
- logout.validateRequest()
- except lasso.Error, error:
- msg = 'common_processing: error validateRequest: %s' \
- % lasso.strError(error[0])
- logger.info(msg)
- # We continue the process
- return None, session, logout
-
-
-@csrf_exempt
-def singleLogoutSOAP(request):
- '''
- Single Logout IdP initiated by SOAP
- '''
- message = None
- try:
- message = get_soap_message(request)
- except:
- return http_response_bad_request('singleLogoutSOAP: Bad SOAP message')
-
- if not message:
- return http_response_bad_request('singleLogoutSOAP: Bad SOAP message')
-
- request_type = lasso.getRequestTypeFromSoapMsg(message)
- if request_type != lasso.REQUEST_TYPE_LOGOUT:
- return http_response_bad_request('singleLogoutSOAP: \
- SOAP message is not a slo message')
-
- error, session, logout = \
- common_processing_slo_idp_init_bindings(request, message)
- if error:
- return error
-
- '''
- Play the role of IdP sending a SLO to all SP
- '''
- slo_soap_as_idp(request, logout, session)
-
- '''Break local session and respond to the IdP initiating the SLO'''
- try:
- flush_django_session(session.django_session_key)
- session.delete()
- except Exception, e:
- logger.error('singleLogoutSOAP: Error at session deletion due to %s' \
- % str(e))
- return finishSingleLogoutSOAP(logout)
- return finishSingleLogoutSOAP(logout)
-
-
-def finishSingleLogoutSOAP(logout):
- try:
- logout.buildResponseMsg()
- except lasso.Error, error:
- message = 'singleLogoutSOAP \
- buildResponseMsg: %s' % lasso.strError(error[0])
- return http_response_forbidden_request(message)
- django_response = HttpResponse()
- django_response.status_code = 200
- django_response.content_type = 'text/xml'
- django_response.content = logout.msgBody
- return django_response
-
-
-def finish_slo(request):
- id = request.REQUEST.get('id')
- if not id:
- logger.error('finish_slo: missing id argument')
- return HttpResponseBadRequest('finish_slo: missing id argument')
- logout_dump, session_key, provider_id = get_and_delete_key_values(id)
- server = create_server(request)
- logout = lasso.Logout.newFromDump(server, logout_dump)
- load_provider(request, provider_id, server=logout.server,
- sp_or_idp='idp')
- #Break local session and respond to the IdP initiating the SLO
- if logout.isSessionDirty:
- if logout.session:
- save_session(request, logout, session_key=session_key,
- kind=LIBERTY_SESSION_DUMP_KIND_SP)
- else:
- delete_session(request, session_key=session_key)
- remove_liberty_session_sp(request, session_key=session_key)
- return slo_return_response(logout)
-
-
-def singleLogout(request):
- '''
- Single Logout IdP initiated by Redirect
- '''
- message = get_saml2_query_request(request)
- if not message:
- return http_response_forbidden_request('singleLogout: \
- Unable to handle Single Logout by Redirect without request')
-
- error, session, logout = \
- common_processing_slo_idp_init_bindings(request, message)
- if error:
- return error
-
- if settings.IDP_SAML2:
- save_key_values(logout.request.id, logout.dump(),
- request.session.session_key, logout.remoteProviderId)
- return idp_views.redirect_to_logout(request, next_page='%s?id=%s' %
- (reverse(finish_slo), urllib.quote(logout.request.id)))
-
- try:
- flush_django_session(request.session.session_key)
- session.delete()
- except Exception, e:
- logger.error('singleLogout: Error at session deletion due to %s' \
- % str(e))
- return slo_return_response(logout)
- return slo_return_response(logout)
-
-
-def slo_return_response(logout):
- try:
- logout.buildResponseMsg()
- except lasso.Error, error:
- return http_response_forbidden_request('slo_return_response: %s' \
- % lasso.strError(error[0]))
- else:
- logger.info('slo_return_response: redirect to %s' % logout.msgUrl)
- return HttpResponseRedirect(logout.msgUrl)
-
-
-###
- # federationTermination
- # @request
- # @method
- # @entity_id
- #
- # Name Identifier Management
- # Federation termination: request from user interface
- # Profile supported: Redirect, SOAP
- # For response, if the requester uses a (a)synchronous binding,
- # the responder uses the same.
- # Else, the grabs the preferred method from the metadata.
- # By default we do not break the session.
- # TODO: Define in admin a parameter to indicate if the
- # federation termination implies a local logout (IDP and SP initiated)
- # -> Should not logout.
- # TODO: Clean tables of all dumps about this user
- ###
-def federationTermination(request):
- entity_id = request.REQUEST.get('entity_id')
- if not entity_id:
- return error_page(request,
- _('fedTerm/SP UI: No provider for defederation'),
- logger=logger)
-
- if request.user.is_anonymous():
- return error_page(request,
- _('fedTerm/SP UI: Unable to defederate a not logged user!'),
- logger=logger)
-
- server = build_service_provider(request)
- if not server:
- error_page(request,
- _('fedTerm/SP UI: Service provider not configured'),
- logger=logger)
-
- # Lookup for the Identity provider
- p = load_provider(request, entity_id, server=server, sp_or_idp='idp')
- if not p:
- return error_page(request,
- _('fedTerm/SP UI: No such identity provider.'),
- logger=logger)
-
- manage = lasso.NameIdManagement(server)
-
- load_session(request, manage, kind=LIBERTY_SESSION_DUMP_KIND_SP)
- load_federation(request, get_entity_id(request, reverse(metadata)), manage)
- fed = lookup_federation_by_user(request.user, p.entity_id)
- if not fed:
- return error_page(request,
- _('fedTerm/SP UI: Not a valid federation'),
- logger=logger)
-
- # The user asks a defederation,
- # we perform without knowing if the IdP can handle
- fed.delete()
-
- # TODO: Deal with identity provider configuration in policies
-
- # If not defined in the metadata,
- # put ANY to let lasso do its job from metadata
- if not p.identity_provider.enable_http_method_for_defederation_request:
- try:
- manage.initRequest(entity_id, None, lasso.HTTP_METHOD_ANY)
- except lasso.Error, error:
- return error_page(request,
- _('fedTerm/SP UI: %s') % lasso.strError(error[0]),
- logger=logger)
-
- if manage.msgBody:
- try:
- manage.buildRequestMsg()
- except lasso.Error, error:
- return error_page(request,
- _('fedTerm/SP SOAP: %s') % lasso.strError(error[0]),
- logger=logger)
- # TODO: Client cert
- client_cert = None
- try:
- soap_answer = soap_call(manage.msgUrl,
- manage.msgBody, client_cert=client_cert)
- except SOAPException:
- return error_page(request,
- _('fedTerm/SP SOAP: \
- Unable to perform SOAP defederation request'),
- logger=logger)
- return manage_name_id_return(request, manage, soap_answer)
- else:
- try:
- manage.buildRequestMsg()
- except lasso.Error, error:
- return error_page(request,
- _('fedTerm/SP Redirect: %s') % \
- lasso.strError(error[0]), logger=logger)
- save_manage(request, manage)
- return HttpResponseRedirect(manage.msgUrl)
-
- # Else, taken from config
- if p.identity_provider.http_method_for_defederation_request == \
- lasso.HTTP_METHOD_SOAP:
- try:
- manage.initRequest(entity_id, None, lasso.HTTP_METHOD_SOAP)
- manage.buildRequestMsg()
- except lasso.Error, error:
- return error_page(request,
- _('fedTerm/SP SOAP: %s') % lasso.strError(error[0]),
- logger=logger)
- # TODO: Client cert
- client_cert = None
- try:
- soap_answer = soap_call(manage.msgUrl,
- manage.msgBody, client_cert=client_cert)
- except SOAPException:
- return error_page(request,
- _('fedTerm/SP SOAP: \
- Unable to perform SOAP defederation request'),
- logger=logger)
- return manage_name_id_return(request, manage, soap_answer)
-
- if p.identity_provider.http_method_for_defederation_request == \
- lasso.HTTP_METHOD_REDIRECT:
- try:
- manage.initRequest(entity_id, None, lasso.HTTP_METHOD_REDIRECT)
- manage.buildRequestMsg()
- except lasso.Error, error:
- return error_page(request,
- _('fedTerm/SP Redirect: %s') % lasso.strError(error[0]),
- logger=logger)
- save_manage(request, manage)
- return HttpResponseRedirect(manage.msgUrl)
-
- return error_page(request, _('Unknown HTTP method.'), logger=logger)
-
-
-###
- # manageNameIdReturn
- # @request
- #
- # Federation termination: response from Redirect SP initiated
- ###
-def manageNameIdReturn(request):
- server = build_service_provider(request)
- if not server:
- return error_page(request,
- _('fedTerm/SP Redirect: Service provider not configured'),\
- logger=logger)
-
- manage_dump = get_manage_dump(request)
- manage = None
- if manage_dump.exists() and manage_dump.count() > 1:
- manage_dump.delete()
- return error_page(request,
- _('fedTerm/SP Redirect: Error managing manage dump'),
- logger=logger)
- elif manage_dump.exists():
- try:
- manage = \
- lasso.NameIdManagement.newFromDump(server,
- manage_dump[0].manage_dump)
- except:
- pass
- manage_dump.delete()
- else:
- manage = lasso.NameIdManagement(server)
-
- if not manage:
- return error_page(request,
- _('fedTerm/SP Redirect: Defederation failed'), logger=logger)
-
- load_federation(request, get_entity_id(request, reverse(metadata)), manage)
- message = get_saml2_request_message(request)
- return manage_name_id_return(request, manage, message)
-
-
-###
- # manage_name_id_return
- # @request
- # @logout
- # @message
- #
- # Post-response processing
- ###
-def manage_name_id_return(request, manage, message):
- while True:
- try:
- manage.processResponseMsg(message)
- except (lasso.ServerProviderNotFoundError,
- lasso.ProfileUnknownProviderError):
- provider_id = manage.remoteProviderId
- provider_loaded = load_provider(request, provider_id,
- server=manage.server, sp_or_idp='idp')
-
- if not provider_loaded:
- message = _('fedTerm/Return: \
- provider %r unknown') % provider_id
- return error_page(request, message, logger=logger)
- else:
- continue
- except lasso.Error, error:
- return error_page(request,
- _('fedTerm/manage_name_id_return: %s') % \
- lasso.strError(error[0]),
- logger=logger)
- return HttpResponseRedirect(get_registered_url(request))
-
-
-###
- # manageNameIdSOAP
- # @request
- #
- # Federation termination: request from SOAP IdP initiated
- # TODO: Manage valid soap responses on error (else error 500)
- ###
-@csrf_exempt
-def manageNameIdSOAP(request):
- try:
- soap_message = get_soap_message(request)
- except:
- return http_response_bad_request('fedTerm/IdP SOAP: Bad SOAP message')
- if not soap_message:
- return http_response_bad_request('fedTerm/IdP SOAP: Bad SOAP message')
-
- request_type = lasso.getRequestTypeFromSoapMsg(soap_message)
- if request_type != lasso.REQUEST_TYPE_NAME_ID_MANAGEMENT:
- return http_response_bad_request('fedTerm/IdP SOAP: \
- SOAP message is not a slo message')
-
- server = build_service_provider(request)
- if not server:
- return http_response_forbidden_request('fedTerm/IdP SOAP: \
- Service provider not configured')
-
- manage = lasso.NameIdManagement(server)
- if not manage:
- return http_response_forbidden_request('fedTerm/IdP SOAP: \
- Unable to create Login object')
-
- while True:
- try:
- manage.processRequestMsg(soap_message)
- break
- except (lasso.ServerProviderNotFoundError,
- lasso.ProfileUnknownProviderError):
- provider_id = manage.remoteProviderId
- provider_loaded = load_provider(request, provider_id,
- server=server, sp_or_idp='idp')
-
- if not provider_loaded:
- message = _('fedTerm/SOAP: provider %r unknown') % provider_id
- return error_page(request, message, logger=logger)
- else:
- continue
- except lasso.Error, error:
- message = 'fedTerm/IdP SOAP: %s' % lasso.strError(error[0])
- return http_response_forbidden_request(message)
-
- fed = lookup_federation_by_name_identifier(profile=manage)
- load_federation(request, get_entity_id(request, reverse(metadata)), manage, fed.user)
- try:
- manage.validateRequest()
- except lasso.Error, error:
- message = 'fedTerm/IdP SOAP: %s' % lasso.strError(error[0])
- return http_response_forbidden_request(message)
-
- fed.delete()
-
- try:
- manage.buildResponseMsg()
- except:
- message = 'fedTerm/IdP SOAP: %s' % lasso.strError(error[0])
- return http_response_forbidden_request(message)
-
- django_response = HttpResponse()
- django_response.status_code = 200
- django_response.content_type = 'text/xml'
- django_response.content = manage.msgBody
- return django_response
-
-
-###
- # manageNameId
- # @request
- #
- # Federation termination: request from Redirect IdP initiated
- ###
-def manageNameId(request):
- query = get_saml2_query_request(request)
- if not query:
- return http_response_forbidden_request('fedTerm/IdP Redirect: \
- Unable to handle Single Logout by Redirect without request')
-
- server = build_service_provider(request)
- if not server:
- return http_response_forbidden_request('fedTerm/IdP Redirect: \
- Service provider not configured')
-
- manage = lasso.NameIdManagement(server)
- if not manage:
- return http_response_forbidden_request('fedTerm/IdP Redirect: \
- Unable to create Login object')
-
- try:
- manage.processRequestMsg(query)
- except lasso.Error, error:
- message = 'fedTerm/IdP Redirect: %s' % lasso.strError(error[0])
- return http_response_forbidden_request(message)
-
- fed = lookup_federation_by_name_identifier(profile=manage)
- load_federation(request, get_entity_id(request, reverse(metadata)), manage, fed.user)
- try:
- manage.validateRequest()
- except lasso.Error, error:
- logger.warning('fedTerm/IdP Redirect: Unable to validate request')
- return
-
- fed.delete()
-
- try:
- manage.buildResponseMsg()
- except:
- message = 'fedTerm/IdP Redirect: %s' % lasso.strError(error[0])
- return http_response_forbidden_request(message)
-
- return HttpResponseRedirect(manage.msgUrl)
-
-
-#############################################
-# Helper functions
-#############################################
-
-def get_provider_id_and_options(provider_id):
- if not provider_id:
- provider_id = reverse(metadata)
- options = metadata_options
- if getattr(settings, 'AUTHSAML2_METADATA_OPTIONS', None):
- options.update(settings.AUTHSAML2_METADATA_OPTIONS)
- return provider_id, options
-
-
-def get_metadata(request, provider_id=None):
- provider_id, options = get_provider_id_and_options(provider_id)
- return get_saml2_metadata(request, provider_id, sp_map=metadata_map,
- options=options)
-
-
-def create_server(request, provider_id=None):
- provider_id, options = get_provider_id_and_options(provider_id)
- return create_saml2_server(request, provider_id, sp_map=metadata_map,
- options=options)
-
-
-def http_response_bad_request(message):
- logger.error(message)
- return HttpResponseBadRequest(_(message))
-
-
-def http_response_forbidden_request(message):
- logger.error(message)
- return HttpResponseForbidden(_(message))
-
-
-def build_service_provider(request):
- return create_server(request, reverse(metadata))
-
-
-def setAuthnrequestOptions(provider, login, force_authn, is_passive):
- if not provider or not login:
- return None
-
- p = get_idp_options_policy(provider)
- if not p:
- return None
-
- if p.no_nameid_policy:
- login.request.nameIDPolicy = None
- else:
- login.request.nameIDPolicy.format = \
- NAME_ID_FORMATS[p.requested_name_id_format]['samlv2']
- login.request.nameIDPolicy.allowCreate = p.allow_create
- login.request.nameIDPolicy.spNameQualifier = None
-
- if p.enable_binding_for_sso_response:
- login.request.protocolBinding = p.binding_for_sso_response
-
- if force_authn is None:
- force_authn = p.want_force_authn_request
- login.request.forceAuthn = force_authn
-
- if is_passive is None:
- is_passive = p.want_is_passive_authn_request
- login.request.isPassive = is_passive
-
- return p
-
-
-def profile(request, template_name='profile.html'):
- if 'next' in request.session:
- next = request.session['next']
- else:
- next = next
- if request.user is None \
- or not request.user.is_authenticated() \
- or not hasattr(request.user, '_meta'):
- return HttpResponseRedirect(next)
- logger.info('view_profile: View profile of user %s' % str(request.user))
-
- #Add creation date
- federations = LibertyProvider.objects \
- .filter(identity_provider__libertyfederation__user=request.user) \
- .values_list('name', flat=True)
-
- from frontend import AuthSAML2Frontend
- form = AuthSAML2Frontend().form()()
- if not form.fields['provider_id'].choices:
- form = None
- context = {'submit_name': 'submit-%s' % AuthSAML2Frontend().id(),
- REDIRECT_FIELD_NAME: '/profile',
- 'form': form}
-
- return render_to_string(template_name,
- {'next': next,
- 'federations': federations,
- 'base': '/authsaml2'},
- RequestContext(request, context))
-
-
-@login_required
-@csrf_exempt
-def delete_federation(request, next_url='/'):
- next = request.REQUEST.get('next', next_url)
- logger.info('delete_federation: federation deletion requested')
- if request.method == "POST":
- provider_name = request.POST.get('fed')
- if provider_name:
- LibertyFederation.objects.filter(
- user=request.user,
- idp__liberty_provider__name=provider_name).update(user=None)
- logger.info('delete_federation: federation %s deleted',
- provider_name)
- messages.add_message(request, messages.INFO,
- _('Successful federation deletion.'))
- return HttpResponseRedirect(next)
- return HttpResponseRedirect(next)
diff --git a/authentic2/authsaml2/signals.py b/authentic2/authsaml2/signals.py
deleted file mode 100644
index 59e8f17f0..000000000
--- a/authentic2/authsaml2/signals.py
+++ /dev/null
@@ -1,10 +0,0 @@
-from django.dispatch import Signal
-
-#authz_decision
-authz_decision = Signal(providing_args = ["request","attributes","provider"])
-
-#user login
-auth_login = Signal(providing_args = ["request","attributes"])
-
-#user logout
-auth_logout = Signal(providing_args = ["user"])
diff --git a/authentic2/authsaml2/templates/auth/saml2/account_linking.html b/authentic2/authsaml2/templates/auth/saml2/account_linking.html
deleted file mode 100644
index 91e46a081..000000000
--- a/authentic2/authsaml2/templates/auth/saml2/account_linking.html
+++ /dev/null
@@ -1,39 +0,0 @@
-{% extends "base.html" %}
-{% load i18n %}
-
-{% block title %}
-{% trans "Log in to link your account" %}
-{% endblock %}
-
-{% block content %}
-* {% trans "Log in to link with your existing account" %}
-
-
-{% endblock %}
diff --git a/authentic2/authsaml2/templates/auth/saml2/login_form.html b/authentic2/authsaml2/templates/auth/saml2/login_form.html
deleted file mode 100644
index 21c583170..000000000
--- a/authentic2/authsaml2/templates/auth/saml2/login_form.html
+++ /dev/null
@@ -1,8 +0,0 @@
-{% load i18n %}
-
-
-
diff --git a/authentic2/authsaml2/templates/auth/saml2/logout.html b/authentic2/authsaml2/templates/auth/saml2/logout.html
deleted file mode 100644
index bdc831297..000000000
--- a/authentic2/authsaml2/templates/auth/saml2/logout.html
+++ /dev/null
@@ -1,20 +0,0 @@
-{% extends "base.html" %}
-{% load i18n %}
-
-{% block title %}
-{% trans "Logout" %}
-{% endblock %}
-{% block bodyargs %}onload="setTimeout(function () { window.location='{{ next_page }}' }, {{ redir_timeout }})"{% endblock %}
-
-{% block content %}
-
-{% trans message %}
-
- {% for fragment in logout_list %}
- {{ fragment|safe }}
- {% endfor %}
-
-
-
-
-{% endblock %}
diff --git a/authentic2/authsaml2/templates/error_authsaml2.html b/authentic2/authsaml2/templates/error_authsaml2.html
deleted file mode 100644
index 89f7aa018..000000000
--- a/authentic2/authsaml2/templates/error_authsaml2.html
+++ /dev/null
@@ -1,9 +0,0 @@
-{% extends "base.html" %}
-{% load i18n %}
-{% block bodyargs %}onload="setTimeout(function () { window.location='{{ next_page }}' }, {{ redir_timeout }})"{% endblock %}
-
-{% block content %}
-{{ title }}
-
-{% trans "Back" %}
-{% endblock %}
diff --git a/authentic2/authsaml2/templates/profile.html b/authentic2/authsaml2/templates/profile.html
deleted file mode 100644
index 686b3c6ff..000000000
--- a/authentic2/authsaml2/templates/profile.html
+++ /dev/null
@@ -1,32 +0,0 @@
-{% load i18n %}
-{% if form or federations %}
-{% trans "SAML2 Federations" %}
-
-
-
-{% if federations %}
-
-
{% trans "Delete a federation?" %}
-{% for f in federations %}
-
-{% endfor %}
-
-{% endif %}
-
-{% if form %}
-
-
{% trans "Add a federation?" %}
-
-
-{% endif %}
-
-{% endif %}
diff --git a/authentic2/authsaml2/urls.py b/authentic2/authsaml2/urls.py
deleted file mode 100644
index 2816f92e5..000000000
--- a/authentic2/authsaml2/urls.py
+++ /dev/null
@@ -1,50 +0,0 @@
-from django.conf import settings
-
-from django.conf.urls import patterns, url
-
-from authentic2.authsaml2.saml2_endpoints import metadata, sso, finish_federation, \
- singleSignOnArtifact, singleSignOnPost, sp_slo, singleLogoutReturn, \
- singleLogoutSOAP, singleLogout, federationTermination, manageNameIdReturn, \
- manageNameIdSOAP, manageNameId, delete_federation, redirect_to_disco, \
- disco_response, finish_slo
-
-urlpatterns = patterns('',
- (r'^metadata$', metadata),
- # Receive request from user interface
- (r'^sso$', sso),
- (r'^finish_federation$', finish_federation),
- (r'^singleSignOnArtifact$', singleSignOnArtifact),
- (r'^singleSignOnPost$', singleSignOnPost),
- # Receive request from functions
- (r'^sp_slo/(.*)$', sp_slo),
- # Receive response from Redirect SP initiated
- (r'^singleLogoutReturn$', singleLogoutReturn),
- # Receive request from SOAP IdP initiated
- (r'^singleLogoutSOAP$', singleLogoutSOAP),
- # Receive request from Redirect IdP initiated
- (r'^singleLogout$', singleLogout),
- # Back of SLO treatment by the IdP Side
- (r'^finish_slo$', finish_slo),
- # Receive request from user interface
- (r'^federationTermination$', federationTermination),
- # Receive response from Redirect SP initiated
- (r'^manageNameIdReturn$', manageNameIdReturn),
- # Receive request from SOAP IdP initiated
- (r'^manageNameIdSOAP$', manageNameIdSOAP),
- # Receive request from Redirect IdP initiated
- (r'^manageNameId$', manageNameId),
- # Receive request from Redirect IdP initiated
- url(r'^delete_federation/$', delete_federation,
- name='authsaml2-delete-federation'),
-)
-
-try:
- if settings.USE_DISCO_SERVICE:
- urlpatterns += patterns('',
- #Send idp discovery request
- (r'^redirect_to_disco$', redirect_to_disco),
- #receive idp discovery response
- (r'^discoveryReturn$', disco_response),
- )
-except:
- pass
diff --git a/authentic2/authsaml2/utils.py b/authentic2/authsaml2/utils.py
deleted file mode 100644
index bca3ab3b1..000000000
--- a/authentic2/authsaml2/utils.py
+++ /dev/null
@@ -1,78 +0,0 @@
-import re
-import time
-import logging
-
-from django.template import RequestContext
-from django.contrib.auth import REDIRECT_FIELD_NAME
-from django.utils.translation import ugettext as _
-from django.shortcuts import render_to_response
-from django.contrib import messages
-from django.conf import settings
-
-__redirection_timeout = 1600
-
-__root_refererer_re = re.compile('^(https?://[^/]*/?)')
-def error_page(request, message=None, back=None, logger=None,
- default_message=True, timer=False):
- '''View that show a simple error page to the user with a back link.
-
- back - url for the back link, if None, return to root of the referer
- or the local root.
- '''
- if logger:
- logger.error('Showing message %r on an error page' % message)
- else:
- logging.error('Showing message %r on an error page' % message)
- if back is None:
- referer = request.META.get('HTTP_REFERER')
- if referer:
- root_referer = __root_refererer_re.match(referer)
- if root_referer:
- back = root_referer.group(1)
- if back is None:
- back = '/'
- global __redirection_timeout
- context = RequestContext(request)
- if timer:
- context['redir_timeout'] = __redirection_timeout
- context['next_page'] = back
- display_message = getattr(settings, 'DISPLAY_MESSAGE_ERROR_PAGE', ())
- if default_message and not display_message:
- messages.add_message(request, messages.ERROR,
- _('An error happened. Report this %s to the administrator.') % \
- time.strftime("[%Y-%m-%d %a %H:%M:%S]", time.localtime()))
- elif message:
- messages.add_message(request, messages.ERROR, message)
- return render_to_response('error_authsaml2.html', {'back': back},
- context_instance=context)
-
-# Used to register requested url during SAML redirections
-def register_next_target(request, url=None):
- if url:
- next = url
- else:
- next = request.GET.get(REDIRECT_FIELD_NAME)
- if not next:
- next = '/'
- request.session['next'] = next
-
-def get_registered_url(request):
- if 'next' in request.session:
- return request.session['next']
- return None
-
-def register_request_id(request, request_id):
- request.session['saml_request_id'] = request_id
-
-# Used for account linking
-def save_federation_temp(request, login, attributes=None):
- if login and login.identity:
- request.session['identity_dump'] = login.identity.dump()
- request.session['remoteProviderId'] = login.remoteProviderId
- request.session['nameId'] = login.nameIdentifier
- if attributes:
- request.session['attributes'] = attributes
-
-def load_federation_temp(request, login):
- if 'identity_dump' in request.session:
- login.setIdentityFromDump(request.session['identity_dump'])
diff --git a/authentic2/decorators.py b/authentic2/decorators.py
index 8803d76dc..bf69d0913 100644
--- a/authentic2/decorators.py
+++ b/authentic2/decorators.py
@@ -2,12 +2,10 @@ from django.contrib.auth.decorators import login_required
from django.http import HttpResponseRedirect
from functools import wraps
-from authentic2.authsaml2.models import SAML2TransientUser
-
-TRANSIENT_USER_TYPES = (SAML2TransientUser, )
+TRANSIENT_USER_TYPES = []
def is_transient_user(user):
- return isinstance(user, TRANSIENT_USER_TYPES)
+ return isinstance(user, tuple(TRANSIENT_USER_TYPES))
def prevent_access_to_transient_users(view_func):
def _wrapped_view(request, *args, **kwargs):
diff --git a/authentic2/idp/saml/saml2_endpoints.py b/authentic2/idp/saml/saml2_endpoints.py
index 9eabf3a40..131878bf1 100644
--- a/authentic2/idp/saml/saml2_endpoints.py
+++ b/authentic2/idp/saml/saml2_endpoints.py
@@ -72,9 +72,9 @@ from authentic2.constants import NONCE_FIELD_NAME
from authentic2.idp import signals as idp_signals
# from authentic2.idp.models import *
-from authentic2.authsaml2.models import SAML2TransientUser
from authentic2.utils import (cache_and_validate, get_backends as
get_idp_backends, get_username)
+from authentic2.decorators import is_transient_user
logger = logging.getLogger('authentic2.idp.saml')
@@ -252,13 +252,6 @@ def build_assertion(request, login, nid_format='transient', attributes=None):
authn_context = lasso.SAML2_AUTHN_CONTEXT_PASSWORD
elif backend == 'authentic2.auth2_auth.auth2_ssl.backend.SSLBackend':
authn_context = lasso.SAML2_AUTHN_CONTEXT_X509
- # XXX: grab context from the assertion received
- elif backend == \
- 'authentic2.authsaml2.backends.AuthSAML2PersistentBackend':
- authn_context = lasso.SAML2_AUTHN_CONTEXT_UNSPECIFIED
- elif backend == \
- 'authentic2.authsaml2.backends.AuthSAML2TransientBackend':
- authn_context = lasso.SAML2_AUTHN_CONTEXT_UNSPECIFIED
else:
backend = load_backend(backend)
if hasattr(backend, 'get_saml2_authn_context'):
@@ -581,8 +574,7 @@ def sso_after_process_request(request, login, consent_obtained=False,
#Deal with transient users
transient_user = False
# XXX: Deal with all kind of transient users
- type(SAML2TransientUser)
- if isinstance(request.user, SAML2TransientUser):
+ if is_transient_user(request.user):
logger.debug('the user is transient')
transient_user = True
if transient_user and login.request.nameIdPolicy.format == \
@@ -1285,52 +1277,6 @@ def slo_soap(request):
logger.exception('slo, relaying to %s failed ' %
lib_session.provider_id)
- #Send SLO to IdP
- pid = None
- q = LibertySessionDump. \
- objects.filter(django_session_key__in=django_session_keys,
- kind=LIBERTY_SESSION_DUMP_KIND_SP)
- if not q:
- logger.info('No session found for a third IdP')
- else:
- from authentic2.authsaml2 import saml2_endpoints
- server = saml2_endpoints.create_server(request)
- logout2 = lasso.Logout(server)
- for s in q:
- logger.debug('IdP session found %s' % s.session_dump)
- try:
- lib_session = lasso.Session().newFromDump(s.session_dump.encode('utf-8'))
- except lasso.Error:
- logger.debug('Unable to load session %s' % s.session_dump)
- else:
- try:
- pid = lib_session.get_assertions().keys()[0]
- logger.debug('SLO to %s' % pid)
- logout2.setSessionFromDump(s.session_dump.encode('utf8'))
- provider = load_provider(request, pid,
- server=server, sp_or_idp='idp')
- policy = get_idp_options_policy(provider)
- if not policy:
- logger.error('No policy found for %s'\
- % provider)
- elif not policy.forward_slo:
- logger.info('%s configured to not receive \
- slo' % provider)
- else:
- '''
- As we are in a synchronous binding,
- we need SOAP support
- '''
- logout2.initRequest(None, lasso.HTTP_METHOD_SOAP)
- logout2.buildRequestMsg()
- soap_response = send_soap_request(request, logout2)
- logout2.processResponseMsg(soap_response)
- logger.info('successful SLO with %s' \
- % pid)
- except Exception, e:
- logger.error('error treating SLO with IdP %s' \
- % str(e))
-
'''
Respond to the SP initiating SLO
'''
diff --git a/authentic2/saml/common.py b/authentic2/saml/common.py
index 387076787..f56aac19f 100644
--- a/authentic2/saml/common.py
+++ b/authentic2/saml/common.py
@@ -26,7 +26,6 @@ from authentic2.saml.models import LibertyFederation, LibertyProvider, \
from authentic2.saml import models
from authentic2.saml import saml2utils
-from authentic2.authsaml2 import signals
from authentic2.http_utils import get_url
from .. import nonce
@@ -438,31 +437,6 @@ def lookup_federation_by_user(user, qualifier):
return None
return fed[0]
-# List Idp providers - Use from display in templates
-# WARNING: No way for multiple federation by user with a single IdP (is it a problem??)
-def get_idp_list():
- return LibertyProvider.objects.exclude(identity_provider=None) \
- .values('entity_id','name')
-
-def get_idp_list_sorted():
- return LibertyProvider.objects.exclude(identity_provider=None) \
- .order_by('name').values('entity_id','name')
-
-def get_idp_user_federated_list(request):
- user = request.user
- if request.user.is_anonymous():
- return None
- return [p for p in get_idp_list() \
- if lookup_federation_by_user(user, p.entity_id)]
-
-def get_idp_user_not_federated_list(request):
- user = request.user
- if request.user.is_anonymous():
- return None
- return [p for p in get_idp_list() \
- if not lookup_federation_by_user(user, p.entity_id)]
-
-
# The session_index is the "session on the IdP" identifiers
# One identifier is dedicated for each sp for each user session
# to not be a factor of linkability between sp
@@ -724,9 +698,6 @@ def authz_decision_cb(sender, request=None, attributes={},
_('Your access is denied. At least one attribute does not match.')
return dic
-signals.authz_decision.connect(authz_decision_cb,
- dispatch_uid='authz_decision_on_attributes')
-
def get_session_not_on_or_after(assertion):
'''Extract the minimal value for the SessionNotOnOrAfter found in the given
assertion AuthenticationStatement(s).
diff --git a/authentic2/settings.py b/authentic2/settings.py
index 19accd07e..5fe7a2a0d 100644
--- a/authentic2/settings.py
+++ b/authentic2/settings.py
@@ -213,7 +213,6 @@ DISCO_USE_OF_METADATA = 'DISCO_USE_OF_METADATA' in os.environ
DISCO_SERVICE_NAME = os.environ.get('DISCO_SERVICE_NAME', "http://www.identity-hub.com/disco_service/disco")
DISCO_RETURN_ID_PARAM = "entityID"
SHOW_DISCO_IN_MD = 'SHOW_DISCO_IN_MD' in os.environ
-USE_DISCO_SERVICE = 'USE_DISCO_SERVICE' in os.environ
###########################
# Authentication settings
@@ -339,7 +338,6 @@ ADMIN_TOOLS_INDEX_DASHBOARD = 'authentic2.dashboard.CustomIndexDashboard'
ADMIN_TOOLS_APP_INDEX_DASHBOARD = 'authentic2.dashboard.CustomAppIndexDashboard'
ADMIN_TOOLS_MENU = 'authentic2.menu.CustomMenu'
-AUTH_SAML2 = 'AUTH_SAML2' in os.environ
AUTH_OPENID = 'AUTH_OPENID' in os.environ
AUTH_SSL = 'AUTH_SSL' in os.environ
IDP_SAML2 = 'IDP_SAML2' in os.environ
@@ -435,15 +433,6 @@ if USE_DEBUG_TOOLBAR:
except ImportError:
print "Debug toolbar missing, not loaded"
-if AUTH_SAML2:
- INSTALLED_APPS += ('authentic2.authsaml2',)
- AUTHENTICATION_BACKENDS += (
- 'authentic2.authsaml2.backends.AuthSAML2PersistentBackend',
- 'authentic2.authsaml2.backends.AuthSAML2TransientBackend')
- AUTH_FRONTENDS += ('authentic2.authsaml2.frontend.AuthSAML2Frontend',)
- IDP_BACKENDS += ('authentic2.authsaml2.backends.AuthSAML2Backend',)
- DISPLAY_MESSAGE_ERROR_PAGE = True
-
if AUTH_OPENID:
INSTALLED_APPS += ('authentic2.auth2_auth.auth2_openid', 'django_authopenid',)
AUTH_FRONTENDS += ('authentic2.auth2_auth.auth2_openid.backend.OpenIDFrontend',)
diff --git a/authentic2/templates/registration/login.html b/authentic2/templates/registration/login.html
deleted file mode 100644
index d6e05f715..000000000
--- a/authentic2/templates/registration/login.html
+++ /dev/null
@@ -1,54 +0,0 @@
-{% extends "base.html" %}
-{% load i18n %}
-
-{% block title %}
-{% trans "Log in" %}
-{% endblock %}
-
-{% block content %}
-
-
-
-
-
-
-{% if providers_list %}
-
-{% trans "Log in with a federated account?" %}
-
-
-{% endif %}
-
-
-
-{% endblock %}
-
-{% block extra_scripts %}
-
-
-{% endblock %}
diff --git a/authentic2/urls.py b/authentic2/urls.py
index d17bc0f81..0d8382f83 100644
--- a/authentic2/urls.py
+++ b/authentic2/urls.py
@@ -37,10 +37,6 @@ if settings.AUTH_SSL:
urlpatterns += not_homepage_patterns
-urlpatterns += patterns('',
- (r'^authsaml2/', include('authentic2.authsaml2.urls')),
-)
-
try:
if settings.DISCO_SERVICE:
urlpatterns += patterns('',
diff --git a/authentic2/views.py b/authentic2/views.py
index db9b97f4e..fd01895a2 100644
--- a/authentic2/views.py
+++ b/authentic2/views.py
@@ -310,9 +310,7 @@ def homepage(request):
def _homepage(request):
'''Homepage of the IdP'''
tpl_parameters = {}
- # FIXME: we should not refer to a specific authentication module here
- from authentic2.authsaml2.models import SAML2TransientUser
- if not isinstance(request.user, SAML2TransientUser):
+ if not decorators.is_transient_user(request.user):
tpl_parameters['account_management'] = 'account_management'
tpl_parameters['authorized_services'] = service_list(request)
return render_to_response('idp/homepage.html',
diff --git a/doc/settings.rst b/doc/settings.rst
index 39665d312..ecc47ffa8 100644
--- a/doc/settings.rst
+++ b/doc/settings.rst
@@ -61,16 +61,6 @@ Values:
* False: deactivate SSL authentication
* True: activate SSL authentication
-Activate or deactivate SAML2 authentication, Authentic 2 is a SAML2 service provider
-====================================================================================
-
-Variable: AUTH_SAML2
-
-Values:
-
-* False: deactivate SAML2 authentication
-* True: activate SAML2 authentication
-
Activate or deactivate OpenID authentication, Authentic 2 is an OpenID relying party
====================================================================================