text: import logging
  
  from django.conf import settings
  from django.http import HttpResponse, HttpResponseForbidden, \
                          HttpResponseBadRequest, HttpResponseRedirect
  from django.contrib.auth import login, authenticate
  from django.contrib.auth.models import User, Group
  from django.core.urlresolvers import get_script_prefix
  
  logger = logging.getLogger(__name__)
  
  def shibboleth_session_auth(request):
      """Authenticate a session using Shibboleth.
  
      This allows Shibboleth to be one of many options for authenticating to
      the site. Instead of protecting the whole site via Shibboleth, we protect
      a single view (this view).  The view will authenticate the user using
      the attributes passed in via request.META to authenticate the user.
  
      """
  
      idp_attr = settings.SHIBBOLETH_SESSION_AUTH['IDP_ATTRIBUTE']
      idp = request.META.get(idp_attr)
      if not idp:
          logger.error("IdP header missing (%s)", idp_attr)
          return HttpResponseBadRequest("Invalid response from IdP")
  
      if idp not in settings.SHIBBOLETH_SESSION_AUTH['AUTHORIZED_IDPS']:
          logger.info("Unauthorized IdP: %s", idp)
          return HttpResponseForbidden("unauthorized IdP: {}".format(idp))
  
      user_attrs = {}
  
      for http_attr, user_attr, required in settings.SHIBBOLETH_SESSION_AUTH['USER_ATTRIBUTES']:
          user_attrs[user_attr] = request.META.get(http_attr, None)
          if required and user_attrs[user_attr] is None:
              logger.error("SSO missing attribute: %s", user_attr)
              return HttpResponseBadRequest("Invalid response from IdP")
  
      try:
          user = User.objects.get(username=user_attrs['username'])
      except User.DoesNotExist:
          user = User(**user_attrs)
          user.set_unusable_password()
          user.save()
  
      idp_provided_group_names = []
      if idp in settings.SHIBBOLETH_SESSION_AUTH['GROUPS_BY_IDP']:
          for group_name in settings.SHIBBOLETH_SESSION_AUTH['GROUPS_BY_IDP'][idp]:
              idp_provided_group_names.append(group_name)
              try:
                  group = Group.objects.get(name=group_name)
              except Group.DoesNotExist:
                  logger.info("creating group %s (locally configured for IdP %s)", group_name, idp)
                  continue
  
              if group not in user.groups.all():
                  user.groups.add(group)
                  logger.info("adding user %s to group %s", user.username, group.name)
  
      group_attr = settings.SHIBBOLETH_SESSION_AUTH['GROUP_ATTRIBUTE']
      if group_attr in request.META:
          idp_group_names = request.META[group_attr].split(";")
          idp_provided_group_names.extend(idp_group_names)
          for group_name in idp_group_names:
              group, created = Group.objects.get_or_create(name=group_name)
              if created:
                  logging.info("creating group %s (remotely provided by IdP %s)", group_name, idp)
  
              if group not in user.groups.all():
                  group.user_set.add(user)
                  logger.info("adding user %s to group %s", user.username, group.name)
  
      user_groups = user.groups.all()
      for group in user_groups:
          if group.name not in idp_provided_group_names:
              group.user_set.remove(user)
  
      staff_group_name = settings.SHIBBOLETH_SESSION_AUTH['DJANGO_STAFF_GROUP']
      if staff_group_name:
          is_staff_group_member = user.groups.filter(name=staff_group_name).count() > 0
          if user.is_staff != is_staff_group_member:
              user.is_staff = is_staff_group_member
              user.save()
  
      user = authenticate(remote_user=user.username)
      login(request, user)
  
      if "next" in request.GET:
          redirect_target = request.GET['next']
      else:
          redirect_target = get_script_prefix()
  
      return HttpResponseRedirect(redirect_target)
  