From 19c69da417770d896cb91145c034da7be6367ef8 Mon Sep 17 00:00:00 2001 From: Benjamin Dauvergne Date: Wed, 29 Apr 2015 16:39:14 +0200 Subject: [PATCH 1/2] Add a model to store user<->NameID mapping (#7085) --- mellon/adapters.py | 31 +++++++++++++++++++++++++++++-- mellon/app_settings.py | 1 + mellon/migrations/0001_initial.py | 34 ++++++++++++++++++++++++++++++++++ mellon/models.py | 20 +++++++++++++++++++- 4 files changed, 83 insertions(+), 3 deletions(-) create mode 100644 mellon/migrations/0001_initial.py diff --git a/mellon/adapters.py b/mellon/adapters.py index c11b679..25da084 100644 --- a/mellon/adapters.py +++ b/mellon/adapters.py @@ -4,7 +4,7 @@ from django.core.exceptions import PermissionDenied from django.contrib import auth from django.contrib.auth.models import Group -from . import utils, app_settings +from . import utils, app_settings, models log = logging.getLogger(__name__) @@ -45,7 +45,17 @@ class DefaultAdapter(object): else: return username - def lookup_user(self, idp, saml_attributes): + def lookup_user_by_name_id(self, idp, saml_attributes): + User = auth.get_user_model() + name_id = saml_attributes['name_id_content'] + issuer = saml_attributes['issuer'] + try: + return User.objects.get(saml_identifiers__name_id=name_id, + saml_identifiers__issuer=issuer) + except User.DoesNotExist: + pass + + def lookup_user_by_username(self, idp, saml_attributes): User = auth.get_user_model() username = self.format_username(idp, saml_attributes) if not username: @@ -60,11 +70,28 @@ class DefaultAdapter(object): return return user + def lookup_user(self, idp, saml_attributes): + lookup_methods = utils.get_setting(idp, 'LOOKUP_METHODS') + for method in lookup_methods: + if method == 'name_id': + user = self.lookup_user_by_name_id(idp, saml_attributes) + if method == 'username': + user = self.lookup_user_by_username(idp, saml_attributes) + if not user is None: + return user + def provision(self, user, idp, saml_attributes): + self.provision_name_id(user, idp, saml_attributes) self.provision_attribute(user, idp, saml_attributes) self.provision_superuser(user, idp, saml_attributes) self.provision_groups(user, idp, saml_attributes) + def provision_name_id(self, user, idp, saml_attributes): + models.UserSAMLIdentifier.objects.get_or_create( + user=user, + issuer=saml_attributes['issuer'], + name_id=saml_attributes['name_id_content']) + def provision_attribute(self, user, idp, saml_attributes): realm = utils.get_setting(idp, 'REALM') attribute_mapping = utils.get_setting(idp, 'ATTRIBUTE_MAPPING') diff --git a/mellon/app_settings.py b/mellon/app_settings.py index 69d59eb..f079513 100644 --- a/mellon/app_settings.py +++ b/mellon/app_settings.py @@ -25,6 +25,7 @@ class AppSettings(object): 'CREATE_GROUP': True, 'ERROR_URL': None, 'ERROR_REDIRECT_AFTER_TIMEOUT': 120, + 'LOOKUP_METHODS': ['name_id', 'username'], } @property diff --git a/mellon/migrations/0001_initial.py b/mellon/migrations/0001_initial.py new file mode 100644 index 0000000..eca7a91 --- /dev/null +++ b/mellon/migrations/0001_initial.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations +from django.conf import settings + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name='UserSAMLIdentifier', + fields=[ + ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), + ('issuer', models.TextField(verbose_name='Issuer')), + ('name_id', models.TextField(verbose_name='SAML identifier')), + ('created', models.DateTimeField(auto_now_add=True, verbose_name='created')), + ('user', models.ForeignKey(related_name='saml_identifiers', verbose_name='user', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'verbose_name': 'user SAML identifier', + 'verbose_name_plural': 'users SAML identifiers', + }, + bases=(models.Model,), + ), + migrations.AlterUniqueTogether( + name='usersamlidentifier', + unique_together=set([('issuer', 'name_id')]), + ), + ] diff --git a/mellon/models.py b/mellon/models.py index 71a8362..7dfa1fa 100644 --- a/mellon/models.py +++ b/mellon/models.py @@ -1,3 +1,21 @@ from django.db import models +from django.utils.translation import ugettext_lazy as _ +from django.conf import settings -# Create your models here. +class UserSAMLIdentifier(models.Model): + user = models.ForeignKey( + verbose_name=_('user'), + to=settings.AUTH_USER_MODEL, + related_name='saml_identifiers') + issuer = models.TextField( + verbose_name=_('Issuer')) + name_id = models.TextField( + verbose_name=_('SAML identifier')) + created = models.DateTimeField( + verbose_name=_('created'), + auto_now_add=True) + + class Meta: + verbose_name = _('user SAML identifier') + verbose_name_plural = _('users SAML identifiers') + unique_together = (('issuer', 'name_id'),) -- 2.1.4