class CASLoginProvider(BaseProtocol): def __init__(self, success_redirect_url=None): self.name = 'cas' self.protocol_type = 'cas' self.display_name = askbot_settings.CAS_SERVER_NAME self.icon_media_path = askbot_settings.CAS_LOGIN_BUTTON self.one_click_registration = getattr( django_settings, 'ASKBOT_CAS_ONE_CLICK_REGISTRATION_ENABLED', False) self.client = CASClient( version=askbot_settings.CAS_PROTOCOL_VERSION, server_url=askbot_settings.CAS_SERVER_URL, service_url=self.get_service_url(success_redirect_url)) def verify_ticket(self, *args, **kwargs): return self.client.verify_ticket(*args, **kwargs) def get_login_url(self): return self.client.get_login_url() @classmethod def get_service_url(cls, success_redirect_url): service_url = site_url(reverse('user_complete_cas_signin')) if success_redirect_url: service_url += '?' + urllib.parse.urlencode( {'next': success_redirect_url}) return service_url
class CASLoginProvider(BaseProtocol): def __init__(self, success_redirect_url=None): self.name = 'cas' self.protocol_type = 'cas' self.display_name = askbot_settings.CAS_SERVER_NAME self.icon_media_path = askbot_settings.CAS_LOGIN_BUTTON self.one_click_registration = getattr( django_settings, 'ASKBOT_CAS_ONE_CLICK_REGISTRATION_ENABLED', False ) self.client = CASClient( version=askbot_settings.CAS_PROTOCOL_VERSION, server_url=askbot_settings.CAS_SERVER_URL, service_url=self.get_service_url(success_redirect_url) ) def verify_ticket(self, *args, **kwargs): return self.client.verify_ticket(*args, **kwargs) def get_login_url(self): return self.client.get_login_url() @classmethod def get_service_url(cls, success_redirect_url): service_url = site_url(reverse('user_complete_cas_signin')) if success_redirect_url: service_url += '?' + urllib.urlencode({'next': success_redirect_url}) return service_url
def signin_with_cas(self): client = CASClient(version='2', renew=False, extra_login_params=False, server_url=CONF.lfid_url, service_url=CONF.lfid_return_url) redirect_url = client.get_login_url() self.redirect(url=redirect_url, permanent=False)
def signin_with_cas(self): client = CASClient(version='2', renew=False, extra_login_params=False, server_url=CONF.lfid_url, service_url='http://{0}/{1}'.format( self.request.host, CONF.lfid_return_url)) redirect_url = client.get_login_url() self.redirect(url=redirect_url, permanent=False)
def link_from_profile(request, institution): """ Attempts to authenticate a CAS account for the provided institution, and links it to the current Uniauth profile if successful. """ next_url = request.GET.get('next') ticket = request.GET.get('ticket') # Ensure there is an institution with the provided slug try: institution = Institution.objects.get(slug=institution) except Institution.DoesNotExist: raise Http404 if not next_url: next_url = get_redirect_url(request, use_referer=True) # If the user is not already logged into a verified # Uniauth account, raise permission denied if not request.user.is_authenticated or is_tmp_user(request.user) \ or is_unlinked_account(request.user): raise PermissionDenied("Must be logged in as verified Uniauth user.") service_url = get_service_url(request, next_url) client = CASClient(version=2, service_url=service_url, server_url=institution.cas_server_url) # If a ticket was provided, attempt to authenticate with it if ticket: user = authenticate(request=request, institution=institution, ticket=ticket, service=service_url) # Authentication successful: link to Uniauth profile if # the institution account has not been linked yet + proceed if user: if is_unlinked_account(user): merge_model_instances(request.user, [user]) username_split = get_account_username_split(user.username) _add_institution_account(request.user.profile, username_split[1], username_split[2]) return HttpResponseRedirect(next_url) # Authentication failed: raise permission denied else: raise PermissionDenied("Verification of CAS ticket failed") # If no ticket was provided, redirect to the # login URL for the institution's CAS server else: return HttpResponseRedirect(client.get_login_url())
async def get(self): try: if self.settings_dict["mode"] == "production": service_url = f"https://{self.settings_dict['domain']}/login?next=%2Flogin" else: service_url = "http://lscodebuddy.byu.edu:8008/login?next=%2Flogin" server_url = "https://cas.byu.edu/cas/" cas_client = CASClient(version=3, service_url=service_url, server_url=server_url) ticket = self.get_argument('ticket', False) if not ticket: cas_login_url = cas_client.get_login_url() self.redirect(cas_login_url) user_id, attributes, pgtiou = cas_client.verify_ticket(ticket) user_dict = { "name": attributes["preferredFirstName"] + " " + attributes["preferredSurname"], "given_name": attributes["preferredFirstName"], "family_name": attributes["preferredSurname"], "locale": "en", "email_address": attributes["emailAddress"] } if self.content.user_exists(user_id): # Update user with current information when they already exist. self.content.update_user(user_id, user_dict) else: # Store current user information when they do not already exist. self.content.add_user(user_id, user_dict) self.set_secure_cookie("user_id", user_id, expires_days=30) redirect_path = self.get_secure_cookie("redirect_path") self.clear_cookie("redirect_path") if not redirect_path: redirect_path = "/" self.redirect(redirect_path) except Exception as inst: self.clear_all_cookies() render_error(self, traceback.format_exc())
def cas_login(request, institution): """ Redirects to the CAS login URL, or verifies the CAS ticket, if provided. Accepts the slug of the institution to log in to. """ next_url = request.GET.get('next') ticket = request.GET.get('ticket') # Ensure there is an institution with the provided slug try: institution = Institution.objects.get(slug=institution) except Institution.DoesNotExist: raise Http404 if not next_url: next_url = get_redirect_url(request, use_referer=True) # If the user is already authenticated, proceed to next page if request.user.is_authenticated: return _login_success(request, request.user, next_url) service_url = get_service_url(request, next_url) client = CASClient(version=2, service_url=service_url, server_url=institution.cas_server_url) # If a ticket was provided, attempt to authenticate with it if ticket: user = authenticate(request=request, institution=institution, ticket=ticket, service=service_url) # Authentication successful: setup session + proceed if user: if not request.session.exists(request.session.session_key): request.session.create() auth_login(request, user) request.session['auth-method'] = "cas-" + institution.slug return _login_success(request, user, next_url, ["ticket"]) # Authentication failed: raise permission denied else: raise PermissionDenied("Verification of CAS ticket failed.") # If no ticket was provided, redirect to the # login URL for the institution's CAS server else: return HttpResponseRedirect(client.get_login_url())
async def login_route(next: str = "/", ticket: str = None, cas_client: CASClient = Depends(get_cas), db: AsyncIOMotorClient = Depends(get_database)): """login using CAS login """ if not ticket: # No ticket, the request come from end user, send to CAS login cas_login_url = cas_client.get_login_url() return RedirectResponse(url=cas_login_url) _user, attributes, _ = cas_client.verify_ticket(ticket) if not _user: return {"success": 0, "message": "Invalid user! Retry logging in!"} else: logging.debug(f"CAS verify ticket response: user: {_user}") # TODO add additional login functionality here redirect_url = f"{next}#/?user={_user}" return RedirectResponse(url=redirect_url)
async def login_route(request: Request, ticket: str = None, cas_client: CASClient = Depends(get_cas), db: Session = Depends(get_db)): current_time = datetime.datetime.now() if not ticket: # No ticket, the request come from end user, send to CAS login cas_login_url = cas_client.get_login_url() return RedirectResponse(url=cas_login_url) username, attributes, _ = cas_client.verify_ticket(ticket) request.session['username'] = username if not username: return {"success": 0, "message": "Invalid user! Retry logging in!"} else: logging.debug(f"CAS verify ticket response: user: {username}") existing = await DBUser.get_by_username(db, username) if existing: db_user = {"last_login": current_time} await DBUser.update(db, username, db_user) else: # add the initial state as unanswered db_user = DBUser( username=username, last_login=current_time, first_login=current_time, ) await DBUser.add(db, db_user) access_token = jwt.encode({ 'username': username }, str(SECRET_KEY), algorithm="HS256").decode() return { "access_token": access_token, "username": username, "token_type": "bearer", }
async def login_route( next: str = "/", ticket: str = None, cas_client: CASClient = Depends(get_cas), db: AsyncIOMotorClient = Depends(get_database) ) -> ResponseBase: """login using CAS login """ if not ticket: # No ticket, the request come from end user, send to CAS login cas_login_url = cas_client.get_login_url() return RedirectResponse(url=cas_login_url) _user, attributes, _ = cas_client.verify_ticket(ticket) if not _user: return ResponseBase(success=False, error=[f"Invalid user! {_user}", attributes]) logging.debug(f"CAS verify ticket response: user: {_user}") _update = await db.core.users.update_one( {"username": _user}, {"$set": { "last_login": attributes["authenticationDate"] }}) if _update.matched_count == 0: user = User(username=_user, first_login=attributes["authenticationDate"], last_login=attributes["authenticationDate"]) _res = await db.core.users.insert_one(user.dict()) jwt_token = jwt.encode({ 'username': _user }, str(SECRET_KEY), algorithm="HS256").decode() return ResponseBase(data={"token": jwt_token})