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
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')
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)
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
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())
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)
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
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
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)
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.')
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)
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)
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
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")
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())
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())
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