Exemple #1
0
    def authenticate(self, request, ticket, service):
        """Verifies CAS ticket and gets or creates User object"""
        client = get_cas_client(service_url=service)
        username, attributes, pgtiou = client.verify_ticket(ticket)
        if attributes and request:
            request.session['attributes'] = attributes
            # Attributes
            # {
            #     'username': String
            #     'first_name': String
            #     'last_name': String
            #     'email': String
            #     'is_active': Bool
            #     'station_code': Int or None
            #     'profile_image': String or None
            #     'permissions': String
            # }
            print(attributes)

        if not username:
            return None

        user = None

        UserModel = get_user_model()
        user, created = UserModel._default_manager.get_or_create(
            **{UserModel.USERNAME_FIELD: username})

        if created:
            # If devs want to do something with new user
            pass

        if attributes:
            user.username = attributes['username']
            user.first_name = attributes['first_name']
            user.last_name = attributes['last_name']
            user.email = attributes['email']
            user.is_active = attributes['is_active']
            user.cas_permissions = attributes['permissions']
            if attributes['profile_image'] and \
               attributes['profile_image'] != 'None':
                user.profile_image = attributes['profile_image']

            user.save()

        if not self.user_can_authenticate(user):
            return None

        if pgtiou and settings.CAS_PROXY_CALLBACK and request:
            request.session['pgtiou'] = pgtiou

        # send the `cas_user_authenticated` signal
        cas_user_authenticated.send(sender=self,
                                    user=user,
                                    created=created,
                                    attributes=attributes,
                                    ticket=ticket,
                                    service=service,
                                    request=request)
        return user
Exemple #2
0
def logout(request, next_page=None):
    """Redirects to CAS logout page"""
    # try to find the ticket matching current session for logout signal
    try:
        st = SessionTicket.objects.get(session_key=request.session.session_key)
        ticket = st.ticket
    except SessionTicket.DoesNotExist:
        ticket = None
    # send logout signal
    cas_user_logout.send(
        sender="manual",
        user=request.user,
        session=request.session,
        ticket=ticket,
    )
    auth_logout(request)
    # clean current session ProxyGrantingTicket and SessionTicket
    ProxyGrantingTicket.objects.filter(session_key=request.session.session_key).delete()
    SessionTicket.objects.filter(session_key=request.session.session_key).delete()
    next_page = next_page or get_redirect_url(request)
    if settings.CAS_LOGOUT_COMPLETELY:
        protocol = get_protocol(request)
        host = request.get_host()
        redirect_url = urllib_parse.urlunparse(
            (protocol, host, next_page, '', '', ''),
        )
        client = get_cas_client(request=request)
        return HttpResponseRedirect(settings.CLIENT_HOST)
    else:
        # This is in most cases pointless if not CAS_RENEW is set. The user will
        # simply be logged in again on next request requiring authorization.
        return render(request, 'index.html')
Exemple #3
0
    def post(self, request):
        if request.POST.get('logoutRequest'):
            next_page = request.POST.get('next', settings.CAS_REDIRECT_URL)
            service_url = get_service_url(request, next_page)
            client = get_cas_client(service_url=service_url, request=request)

            clean_sessions(client, request)
            return HttpResponseRedirect(next_page)
Exemple #4
0
def test_session_factory(settings):
    session = requests.Session()
    settings.CAS_SESSION_FACTORY = Mock(return_value=session)

    client = get_cas_client()

    assert settings.CAS_SESSION_FACTORY.called
    assert client.session is session
Exemple #5
0
    def post(self, request):
        next_page = clean_next_page(
            request, request.POST.get('next', settings.CAS_REDIRECT_URL))
        service_url = get_service_url(request, next_page)
        client = get_cas_client(service_url=SERVICE_URL + LOGIN_PATH,
                                request=request)

        if request.POST.get('logoutRequest'):
            clean_sessions(client, request)
            return HttpResponseRedirect(next_page)

        return HttpResponseRedirect(client.get_login_url())
Exemple #6
0
    def get(self, request):
        """
        Redirects to CAS logout page

        :param request:
        :return:
        """
        next_page = request.GET.get('next')
        token = request.GET.get('token')
        session_key = request.GET.get('session_key')

        print('token: {} session_key: {}'.format(token, session_key))
        # try to find the ticket matching current session for logout signal
        try:
            st = SessionTicket.objects.get(session_key=session_key)
            ticket = st.ticket
        except SessionTicket.DoesNotExist:
            ticket = None
        # send logout signal
        # print('request.COOKIES: {}'.format(request.COOKIES))
        # print('request.session: {}'.format(request.session))
        logger.info('request.user: {}'.format(request.user))
        logger.info('logout ticket: {}'.format(ticket))
        logger.info('Start cas logout.')
        cas_user_logout.send(
            sender="manual",
            user=request.user,
            session=request.session,
            ticket=ticket,
        )
        logger.info('Start sys logout.')
        auth_logout(request)
        # clean current session ProxyGrantingTicket and SessionTicket
        ProxyGrantingTicket.objects.filter(session_key=session_key).delete()
        SessionTicket.objects.filter(session_key=session_key).delete()
        Token.objects.filter(key=token).delete()

        next_page = next_page or get_redirect_url(request)
        logger.info('Logout next_page: {}'.format(next_page))
        if settings.CAS_LOGOUT_COMPLETELY:
            protocol = get_protocol(request)
            host = request.get_host()
            redirect_url = urllib_parse.urlunparse(
                (protocol, host, next_page, '', '', ''), )
            logger.info('Logout redirect_url: {}'.format(redirect_url))
            client = get_cas_client(request=request)
            # logger.info('Logout client.get_logout_url(redirect_url): {}'.format(client.get_logout_url(redirect_url)))
            return HttpResponseRedirect(client.get_logout_url(next_page))
        else:
            # This is in most cases pointless if not CAS_RENEW is set. The user will
            # simply be logged in again on next request requiring authorization.
            return HttpResponseRedirect(next_page)
Exemple #7
0
def callback(request):
    """Read PGT and PGTIOU sent by CAS"""
    if request.method == 'POST' and request.POST.get('logoutRequest'):
        clean_sessions(get_cas_client(request=request), request)
        return HttpResponse("{0}\n".format(_('ok')), content_type="text/plain")
    elif request.method == 'GET':
        pgtid = request.GET.get('pgtId')
        pgtiou = request.GET.get('pgtIou')
        pgt = ProxyGrantingTicket.objects.create(pgtiou=pgtiou, pgt=pgtid)
        pgt.save()
        ProxyGrantingTicket.objects.filter(
            session_key=None,
            date__lt=(timezone.now() - timedelta(seconds=60))
        ).delete()
        return HttpResponse("{0}\n".format(_('ok')), content_type="text/plain")
    def authenticate(self, ticket, service, request=None):
        """Verifies CAS ticket and gets or creates user object"""
        client = get_cas_client(service_url=service)
        universal_id, attributes, pgtiou = client.verify_ticket(ticket)

        if attributes and request:
            request.session['attributes'] = attributes
        if not universal_id:
            return None

        try:
            user = CASUser.objects.get(universal_id=universal_id).user
            attributes['username'] = self.clean_username(
                user.username, attributes['username'])
            self.update_user_attributes(user, attributes)
            created = False
        except CASUser.DoesNotExist:
            # check if we want to create new users, if we don't fail auth
            if not settings.CAS_CREATE_USER:
                return None

            attributes['username'] = self.clean_username(
                None, attributes['username'])

            user = create_user_and_casuser(attributes['username'],
                                           attributes['email'], universal_id)
            user.save()
            created = True

        if not self.user_can_authenticate(user):
            return None

        if pgtiou and settings.CAS_PROXY_CALLBACK and request:
            request.session['pgtiou'] = pgtiou

        # send the `cas_user_authenticated` signal
        cas_user_authenticated.send(
            sender=self,
            user=user,
            created=created,
            attributes=attributes,
            ticket=ticket,
            service=service,
        )
        return user
Exemple #9
0
    def authenticate(self, ticket, service, request):
        """Verifies CAS ticket and gets or creates User object"""
        client = get_cas_client(service_url=service)
        username, attributes, pgtiou = client.verify_ticket(ticket)
        if attributes:
            request.session['attributes'] = attributes
        if not username:
            return None

        try:
            user = User.objects.get(**{User.USERNAME_FIELD: username})
            created = False
        except User.DoesNotExist:
            # check if we want to create new users, if we don't fail auth
            if not settings.CAS_CREATE_USER:
                return None
            # user will have an "unusable" password
            user = User.objects.create_user(username, '')
            user.save()
            ui = UserInfo()
            ui.user = user
            ui.nickname = "test"
            ui.save()
            created = True

        if not self.user_can_authenticate(user):
            return None

        if pgtiou and settings.CAS_PROXY_CALLBACK:
            request.session['pgtiou'] = pgtiou

        # send the `cas_user_authenticated` signal
        cas_user_authenticated.send(
            sender=self,
            user=user,
            created=created,
            attributes=attributes,
            ticket=ticket,
            service=service,
        )
        return user
Exemple #10
0
    def authenticate(self, request, ticket, service):
        client = get_cas_client(service_url=service)
        max_username, attributes, _ = client.verify_ticket(ticket)
        if not max_username:  # bad ticket
            logger.warning(
                "MAX ticket (%s) lookup was unsuccessful. "
                "Received attributes: %s", ticket, attributes)
            return None

        email = attributes.get('Email-Address', '')

        user = User.objects.filter(username=email).first()
        if user:
            update_user_attributes(user, attributes)
            logger.info("User %s successfully logged in", email)
            return user
        else:
            logger.warning(
                "MAX ticket (%s) referred to a user not in our "
                "system: %s. Received attributes: %s", ticket, email,
                attributes)
Exemple #11
0
def brcas_token(request):
    service_url = get_service_url(request)
    redirect_url = get_redirect_url(request)
    client = get_cas_client(service_url=service_url, request=request)
    ticket = request.GET.get('ticket')
    if ticket:
        user = django.contrib.auth.authenticate(
            ticket=ticket,
            service="https://api.x-passion.binets.fr/api-brcas-token-auth/",
            request=request)
        if user is not None:
            jwt_payload_handler = rest_framework_jwt.settings.api_settings.JWT_PAYLOAD_HANDLER
            jwt_encode_handler = rest_framework_jwt.settings.api_settings.JWT_ENCODE_HANDLER
            payload = jwt_payload_handler(user)
            token = jwt_encode_handler(payload)
            return render(request,
                          "storer.html",
                          context={
                              "token": token,
                              "redirect_url": redirect_url
                          })
    raise PermissionDenied('BR CAS login failed.')
Exemple #12
0
    def get(self, request):
        """
        Redirects to CAS logout page
        :param request:
        :return:
        """
        next_page = clean_next_page(request, request.GET.get('next'))

        # try to find the ticket matching current session for logout signal
        try:
            st = SessionTicket.objects.get(
                session_key=request.session.session_key)
            ticket = st.ticket
        except SessionTicket.DoesNotExist:
            ticket = None
        # send logout signal
        cas_user_logout.send(
            sender="manual",
            user=request.user,
            session=request.session,
            ticket=ticket,
        )
        auth_logout(request)
        # clean current session ProxyGrantingTicket and SessionTicket
        ProxyGrantingTicket.objects.filter(
            session_key=request.session.session_key).delete()
        SessionTicket.objects.filter(
            session_key=request.session.session_key).delete()
        next_page = next_page or get_redirect_url(request)
        if settings.CAS_LOGOUT_COMPLETELY:
            protocol = get_protocol(request)
            host = request.get_host()
            redirect_url = SERVICE_URL
            client = get_cas_client(request=request)
            return HttpResponseRedirect(client.get_logout_url(redirect_url))
        else:
            # This is in most cases pointless if not CAS_RENEW is set. The user will
            # simply be logged in again on next request requiring authorization.
            return HttpResponseRedirect(next_page)
Exemple #13
0
    def get(self, request: HttpRequest) -> HttpResponse:
        next_page = settings.SUCCESS_SSO_AUTH_REDIRECT

        try:
            del request.session['token']
        except KeyError:
            pass

        # try to find the ticket matching current session for logout signal
        try:
            st = SessionTicket.objects.get(
                session_key=request.session.session_key)
            ticket = st.ticket
        except SessionTicket.DoesNotExist:
            ticket = None
        # send logout signal
        cas_user_logout.send(
            sender="manual",
            user=request.user,
            session=request.session,
            ticket=ticket,
        )

        # clean current session ProxyGrantingTicket and SessionTicket
        ProxyGrantingTicket.objects.filter(
            session_key=request.session.session_key).delete()
        SessionTicket.objects.filter(
            session_key=request.session.session_key).delete()
        auth_logout(request)

        next_page = next_page or get_redirect_url(request)
        if settings.CAS_LOGOUT_COMPLETELY:
            client = get_cas_client(request=request)
            return HttpResponseRedirect(client.get_logout_url(next_page))

        # This is in most cases pointless if not CAS_RENEW is set. The user will
        # simply be logged in again on next request requiring authorization.
        return HttpResponseRedirect(next_page)
Exemple #14
0
def logout(request, next_page=None, **kwargs):

    backend = request.session.get("_auth_user_backend", "").split(".")[-1]

    if CONFIG.get("CAS_LOGIN") and backend == "IPAMCASBackend":
        cas_logout(request, next_page, **kwargs)

        next_page = next_page or get_redirect_url(request)
        if settings.CAS_LOGOUT_COMPLETELY:
            protocol = get_protocol(request)
            host = request.get_host()
            redirect_url = urllib_parse.urlunparse(
                (protocol, host, next_page, "", "", "")
            )
            client = get_cas_client()
            client.server_url = settings.CAS_SERVER_URL[:-3]
            return HttpResponseRedirect(client.get_logout_url(redirect_url))
        else:
            # This is in most cases pointless if not CAS_RENEW is set. The user will
            # simply be logged in again on next request requiring authorization.
            return HttpResponseRedirect(next_page)
    else:
        next_page = "internal_login" if CONFIG.get("CAS_LOGIN") else "login"
        return auth_logout_view(request, next_page=next_page, **kwargs)
    def authenticate(self, request, ticket, service):
        """Verifies CAS ticket and gets or creates User object"""
        client = get_cas_client(service_url=service)
        username, attributes, pgtiou = client.verify_ticket(ticket)
        if attributes and request:
            request.session['attributes'] = attributes

        if not username:
            return None
        user = None
        username = self.clean_username(username)
        domain = username
        # Extra added line, to ensure it is not the full email address
        if "@" in username:
            domain = username.split('@')[1]
            username = username.split('@')[0]

        EXEMPT_USERS = []
        DISALLOWED_DOMAINS = []

        if hasattr(settings, 'EXEMPT_USERS'):
            EXEMPT_USERS += settings.EXEMPT_USERS

        if hasattr(settings, 'DISALLOWED_DOMAINS'):
            DISALLOWED_DOMAINS += settings.DISALLOWED_DOMAINS

        if domain in DISALLOWED_DOMAINS and username not in EXEMPT_USERS:
            return None

        UserModel = get_user_model()

        # Note that this could be accomplished in one try-except clause, but
        # instead we use get_or_create when creating unknown pble_users since it has
        # built-in safeguards for multiple threads.
        if settings.CAS_CREATE_USER:
            user, created = UserModel._default_manager.get_or_create(**{
                UserModel.USERNAME_FIELD: username
            })
            if created:
                # Extra parameter, attributes, added
                user = self.configure_user(user, attributes)
            else:
                self.fill_misc_info(user, attributes)
        else:
            created = False
            try:
                user = UserModel._default_manager.get_by_natural_key(username)
            except UserModel.DoesNotExist:
                pass

        if not self.user_can_authenticate(user):
            return None

        if pgtiou and settings.CAS_PROXY_CALLBACK and request:
            request.session['pgtiou'] = pgtiou

        if settings.CAS_APPLY_ATTRIBUTES_TO_USER and attributes:
            # If we are receiving None for any values which cannot be NULL
            # in the User model, set them to an empty string instead.
            # Possibly it would be desirable to let these throw an error
            # and push the responsibility to the CAS provider or remove
            # them from the dictionary entirely instead. Handling these
            # is a little ambiguous.
            user_model_fields = UserModel._meta.fields
            for field in user_model_fields:
                # Handle null -> '' conversions mentioned above
                if not field.null:
                    try:
                        if attributes[field.name] is None:
                            attributes[field.name] = ''
                    except KeyError:
                        continue
                # Coerce boolean strings into true booleans
                if field.get_internal_type() == 'BooleanField':
                    try:
                        boolean_value = attributes[field.name] == 'True'
                        attributes[field.name] = boolean_value
                    except KeyError:
                        continue

            user.__dict__.update(attributes)

            # If we are keeping a local copy of the user model we
            # should save these attributes which have a corresponding
            # instance in the DB.
            if settings.CAS_CREATE_USER:
                user.save()

        # send the `cas_user_authenticated` signal
        cas_user_authenticated.send(
            sender=self,
            user=user,
            created=created,
            attributes=attributes,
            ticket=ticket,
            service=service,
            request=request
        )
        return user
Exemple #16
0
 def post(self, request):
     if request.POST.get('logoutRequest'):
         clean_sessions(get_cas_client(request=request), request)
         return HttpResponse("{0}\n".format(_('ok')),
                             content_type="text/plain")
Exemple #17
0
def login(request, next_page=None, required=False):
    """Forwards to CAS login URL or verifies CAS ticket"""
    service_url = get_service_url(request, next_page)
    client = get_cas_client(service_url=service_url, request=request)

    if not next_page and settings.CAS_STORE_NEXT and 'CASNEXT' in request.session:
        next_page = request.session['CASNEXT']
        del request.session['CASNEXT']

    if not next_page:
        next_page = get_redirect_url(request)

    if request.method == 'POST' and request.POST.get('logoutRequest'):
        clean_sessions(client, request)
        return HttpResponseRedirect(next_page)

    # backward compability for django < 2.0
    is_user_authenticated = False

    if sys.version_info >= (3, 0):
        bool_type = bool
    else:
        bool_type = types.BooleanType

    if isinstance(request.user.is_authenticated, bool_type):
        is_user_authenticated = request.user.is_authenticated
    else:
        is_user_authenticated = request.user.is_authenticated()

    if is_user_authenticated:
        if settings.CAS_LOGGED_MSG is not None:
            message = settings.CAS_LOGGED_MSG % request.user.get_username()
            user = request.user
            payload = jwt_payload_handler(user)
            token = jwt_encode_handler(payload)
            user_profile = UserProfile.objects.get(user=user)
            profile_id = user_profile.id
            name = user_profile.name
            npm = user_profile.npm
            email = user_profile.email
            role = user_profile.role.role_name
            angkatan = user_profile.angkatan.name

            data = {'user_id': user.id, 'user': user.username, 'token': token,
                    'profile_id': profile_id,
                    'name': name, 'npm': npm, 'email': email, 'role': role, 'angkatan': angkatan}
        return render(request, 'index.html')

    ticket = request.GET.get('ticket')
    if ticket:
        user = authenticate(ticket=ticket,
                            service=service_url,
                            request=request)
        pgtiou = request.session.get("pgtiou")
        if user is not None:
            if not request.session.exists(request.session.session_key):
                request.session.create()
            auth_login(request, user)
            SessionTicket.objects.create(
                session_key=request.session.session_key,
                ticket=ticket
            )

            if pgtiou and settings.CAS_PROXY_CALLBACK:
                # Delete old PGT
                ProxyGrantingTicket.objects.filter(
                    user=user,
                    session_key=request.session.session_key
                ).delete()
                # Set new PGT ticket
                try:
                    pgt = ProxyGrantingTicket.objects.get(pgtiou=pgtiou)
                    pgt.user = user
                    pgt.session_key = request.session.session_key
                    pgt.save()
                except ProxyGrantingTicket.DoesNotExist:
                    pass

            if settings.CAS_LOGIN_MSG is not None:
                name = user.get_username()
                message = settings.CAS_LOGIN_MSG % name
                messages.success(request, message)
            
            payload = jwt_payload_handler(user)
            token = jwt_encode_handler(payload)

            user_profile = UserProfile.objects.get(user=user)
            profile_id = user_profile.id
            name = user_profile.name
            npm = user_profile.npm
            email = user_profile.email
            role = user_profile.role.role_name
            angkatan = user_profile.angkatan.name

            data = {'user_id': user.id, 'user': user.username, 'token': token,
                    'profile_id': profile_id,
                    'name': name, 'npm': npm, 'email': email, 'role': role, 'angkatan': angkatan}
            return render(request, 'index.html', data)
        elif settings.CAS_RETRY_LOGIN or required:
            return HttpResponseRedirect(client.get_login_url())
        else:
            raise PermissionDenied(_('Login failed.'))
    else:
        if settings.CAS_STORE_NEXT:
            request.session['CASNEXT'] = next_page
        return HttpResponseRedirect(client.get_login_url())
Exemple #18
0
    def get(self, request):
        """
        Forwards to CAS login URL or verifies CAS ticket

        :param request:
        :return:
        """
        next_page = request.GET.get('next')
        required = request.GET.get('required', False)

        service_url = get_service_url(request, next_page)
        # logger.info('service_url: {}'.format(service_url))
        client = get_cas_client(service_url=service_url, request=request)

        if not next_page and settings.CAS_STORE_NEXT and 'CASNEXT' in request.session:
            next_page = request.session['CASNEXT']
            del request.session['CASNEXT']

        if not next_page:
            next_page = get_redirect_url(request)

        if request.user.is_authenticated:
            if settings.CAS_LOGGED_MSG is not None:
                message = settings.CAS_LOGGED_MSG % request.user.get_username()
                messages.success(request, message)
                logger.info('user is authenticated')
                user = request.user
                Token.objects.update_or_create(user=user)
            return self.successful_login(request=request, next_page=next_page)

        ticket = request.GET.get('ticket')
        logger.info('Login ticket: {}'.format(ticket))
        if ticket:
            user = authenticate(ticket=ticket,
                                service=service_url,
                                request=request)
            logger.info('ticket user: {}'.format(user))
            # print('user:'******'Login failed.'))
        else:
            if settings.CAS_STORE_NEXT:
                request.session['CASNEXT'] = next_page
            return HttpResponseRedirect(client.get_login_url())
Exemple #19
0
    def authenticate(self, request, ticket, service):
        """Verifies CAS ticket and gets or creates User object"""
        client = get_cas_client(service_url=service, request=request)
        username, attributes, pgtiou = client.verify_ticket(ticket)
        if attributes and request:
            request.session['attributes'] = attributes

        print(attributes)

        if settings.CAS_USERNAME_ATTRIBUTE != 'uid' and settings.CAS_VERSION != 'CAS_2_SAML_1_0':
            if attributes:
                username = attributes.get(settings.CAS_USERNAME_ATTRIBUTE)
            else:
                return None

        if not username:
            return None
        user = None
        username = self.clean_username(username)

        if attributes:
            reject = self.bad_attributes_reject(request, username, attributes)
            if reject:
                return None

            # If we can, we rename the attributes as described in the settings file
            # Existing attributes will be overwritten
            for cas_attr_name, req_attr_name in settings.CAS_RENAME_ATTRIBUTES.items(
            ):
                if cas_attr_name in attributes and cas_attr_name is not req_attr_name:
                    attributes[req_attr_name] = attributes[cas_attr_name]
                    attributes.pop(cas_attr_name)

        UserModel = get_user_model()

        # Note that this could be accomplished in one try-except clause, but
        # instead we use get_or_create when creating unknown users since it has
        # built-in safeguards for multiple threads.
        if settings.CAS_CREATE_USER:
            user_kwargs = {UserModel.USERNAME_FIELD: username}
            if settings.CAS_CREATE_USER_WITH_ID:
                user_kwargs['id'] = self.get_user_id(attributes)

            user, created = UserModel._default_manager.get_or_create(
                **user_kwargs)

            if attributes:
                self.configure_user(user, attributes)

        else:
            created = False
            try:
                if settings.CAS_LOCAL_NAME_FIELD:
                    user_kwargs = {settings.CAS_LOCAL_NAME_FIELD: username}
                    user = UserModel._default_manager.get(**user_kwargs)
                else:
                    user = UserModel._default_manager.get_by_natural_key(
                        username)
            except UserModel.DoesNotExist:
                pass

        if not self.user_can_authenticate(user):
            return None

        if pgtiou and settings.CAS_PROXY_CALLBACK and request:
            request.session['pgtiou'] = pgtiou

        if settings.CAS_APPLY_ATTRIBUTES_TO_USER and attributes:
            # If we are receiving None for any values which cannot be NULL
            # in the User model, set them to an empty string instead.
            # Possibly it would be desirable to let these throw an error
            # and push the responsibility to the CAS provider or remove
            # them from the dictionary entirely instead. Handling these
            # is a little ambiguous.
            user_model_fields = UserModel._meta.fields
            for field in user_model_fields:
                # Handle null -> '' conversions mentioned above
                if not field.null:
                    try:
                        if attributes[field.name] is None:
                            attributes[field.name] = ''
                    except KeyError:
                        continue
                # Coerce boolean strings into true booleans
                if field.get_internal_type() == 'BooleanField':
                    try:
                        boolean_value = attributes[field.name] == 'True'
                        attributes[field.name] = boolean_value
                    except KeyError:
                        continue

            user.__dict__.update(attributes)

            # If we are keeping a local copy of the user model we
            # should save these attributes which have a corresponding
            # instance in the DB.
            if settings.CAS_CREATE_USER:
                user.save()

        # send the `cas_user_authenticated` signal
        cas_user_authenticated.send(sender=self,
                                    user=user,
                                    created=created,
                                    username=username,
                                    attributes=attributes,
                                    pgtiou=pgtiou,
                                    ticket=ticket,
                                    service=service,
                                    request=request)
        return user