def post(self, request): serializer = self.serializer_class(data=request.data) serializer.is_valid(raise_exception=True) data = serializer.validated_data if data['domain'] == 'xjtu': cas_client = CASClient(version='CAS_2_SAML_1_0', server_url='https://cas.xjtu.edu.cn', service_url=data['service']) netid, attr, _ = cas_client.verify_ticket(data['ticket']) if netid is None: raise serializers.ValidationError( 'fail to verify ticket (xjtu)') identifier = 'xjtu-' + netid try: user = User.objects.get(username=identifier) angel = user.angel except User.DoesNotExist: user = User.objects.create_user(username=identifier) user.set_unusable_password() user.save() angel = Angel(user=user, real_name=unquote(attr['cn'])) angel.save() else: raise serializers.ValidationError('unknown domain') token, _created = Token.objects.get_or_create(user=user) return Response({**AngelSerializer(angel).data, 'token': token.key})
def authenticate(self, request, institution, ticket, service): user_model = get_user_model() # Attempt to verify the ticket with the institution's CAS server client = CASClient(version=2, service_url=service, server_url=institution.cas_server_url) username, attributes, pgtiou = client.verify_ticket(ticket) # Add the attributes returned by the CAS server to the session if request and attributes: request.session['attributes'] = attributes # If no username was returned, verification failed if not username: return None # Attempt to find a user possessing an account # with that username for the institution try: user = InstitutionAccount.objects.get(cas_id=username, institution=institution).profile.user except InstitutionAccount.DoesNotExist: user = None # If such a user does not exist, get or create # one with a deterministic, CAS username if not user: temp_username = "******" % (institution.slug, username) user, created = user_model._default_manager.get_or_create( **{user_model.USERNAME_FIELD: temp_username}) return user
def get(self): logging.warning("cas return") ticket = self.get_query_argument('ticket') logging.warning("ticket:%s", ticket) 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)) user, attrs, _ = client.verify_ticket(ticket) logging.debug("user:%s", user) logging.debug("attr:%s", attrs) openid = user role = const.DEFAULT_ROLE new_user_info = { 'openid': openid, 'email': attrs['mail'], 'fullname': attrs['profile_name_full'], const.ROLE: role } user = yield dbapi.db_find_one(self.table, {'openid': openid}) if not user: dbapi.db_save(self.table, new_user_info) else: role = user.get(const.ROLE) self.clear_cookie(const.OPENID) self.clear_cookie(const.ROLE) self.clear_cookie('ticket') self.set_secure_cookie(const.OPENID, openid) self.set_secure_cookie(const.ROLE, role) self.set_secure_cookie('ticket', ticket) self.redirect('http://{0}'.format(self.request.host))
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 signout_cas(self): client = CASClient(version='2', renew=False, extra_login_params=False, server_url=CONF.lfid_url, service_url=CONF.lfid_return_url) url = client.get_logout_url(CONF.ui_url) self.redirect(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())
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 signout_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)) self.clear_cookie('ticket') self.clear_cookie('signin_type') url = client.get_logout_url('http://{0}'.format(self.request.host)) self.redirect(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())
def logout(request): """ Logs the user out of their Uniauth account, and redirects to the next page, defaulting to the URL specified by the UNIAUTH_LOGOUT_REDIRECT_URL setting. If no redirect page is set (URL parameter not given and UNIAUTH_LOGOUT_REDIRECT_URL is None), renders the logout template. Also logs the user out of CAS if they logged in via CAS, and the UNIAUTH_LOGOUT_CAS_COMPLETELY setting is true. """ next_page = request.GET.get('next') auth_method = request.session.get('auth-method') if not next_page and get_setting('UNIAUTH_LOGOUT_REDIRECT_URL'): next_page = get_redirect_url( request, get_setting('UNIAUTH_LOGOUT_REDIRECT_URL')) # Formally log out user auth_logout(request) # Determine whether the user logged in through an institution's CAS institution = None if auth_method and auth_method.startswith("cas-"): try: institution = Institution.objects.get(slug=auth_method[4:]) except Institution.DoesNotExist: pass # If we need to logout an institution's CAS, # redirect to that CAS server's logout URL if institution and get_setting('UNIAUTH_LOGOUT_CAS_COMPLETELY'): redirect_url = urlunparse( (get_protocol(request), request.get_host(), next_page or reverse('uniauth:logout'), '', '', '')) client = CASClient(version=2, service_url=get_service_url(request), server_url=institution.cas_server_url) return HttpResponseRedirect(client.get_logout_url(redirect_url)) # If next page is set, proceed to it elif next_page: return HttpResponseRedirect(next_page) # Otherwise, render the logout view else: return render(request, 'uniauth/logout.html')
def get(self): # Login if necessary c = CASClient(CAS_URL, SERVICE_URL) id = c.Authenticate(self.request.get('ticket', None)) if id: sess = sessions.Session() try: sess['id'] = id[:id.find('@')] self.redirect('/entry') return except: pass self.response.out.write('Login failed')
def get_cas_client(service_url=None, request=None): server_url = django_settings.SSO_UI_URL if server_url and request and server_url.startswith("/"): scheme = request.META.get("X-Forwarded-Proto", request.scheme) server_url = scheme + "://" + request.META["HTTP_HOST"] + server_url return CASClient(service_url=service_url, server_url=server_url, version=2)
def get_cas_client(service_url=None, request=None): server_url = f"{app.config['SSO_UI_URL']}" if server_url and request and server_url.startswith("/"): scheme = request.headers.get("X-Forwarded-Proto", request.scheme) server_url = scheme + "://" + request.headers["HTTP_HOST"] + server_url return CASClient(service_url=service_url, server_url=server_url, version=2)
def get_cas_client(service_url=None, request=None): """ initializes the CASClient according to the CAS_* settigs """ # Handle CAS_SERVER_URL without protocol and hostname server_url = django_settings.CAS_SERVER_URL if server_url and request and server_url.startswith('/'): scheme = request.META.get("X-Forwarded-Proto", request.scheme) server_url = scheme + "://" + request.META['HTTP_HOST'] + server_url # assert server_url.startswith('http'), "settings.CAS_SERVER_URL invalid" if not django_settings.CAS_VERIFY_SSL_CERTIFICATE: warnings.warn( "`CAS_VERIFY_SSL_CERTIFICATE` is disabled, meaning that SSL certificates " "are not being verified by a certificate authority. This can expose your " "system to various attacks and should _never_ be disabled in a production " "environment.") return CASClient( service_url=service_url, version=django_settings.CAS_VERSION, server_url=server_url, extra_login_params=django_settings.CAS_EXTRA_LOGIN_PARAMS, renew=django_settings.CAS_RENEW, username_attribute=django_settings.CAS_USERNAME_ATTRIBUTE, proxy_callback=django_settings.CAS_PROXY_CALLBACK, verify_ssl_certificate=django_settings.CAS_VERIFY_SSL_CERTIFICATE)
def check_auth(username, password): print "authentication" return True #login try: client = CASClient( "shchandheld.intra.searshc.com", "/casWeb/v1/tickets/", port=None, timeout=15, https=True, ) token = client.login(username, password) except Exception as e: print "Exception" return False return True
def __init__(self, application, request, **kwargs): super(SignBaseHandler, self).__init__(application, request, **kwargs) self.table = 'users' self.cas_client = CASClient(version='2', server_url=CONF.lfid_cas_url, service_url='{}/{}'.format( CONF.ui_url, CONF.lfid_signin_return))
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", }
def get_cas_client(service_url=None): """ initializes the CASClient according to the CAS_* settigs """ return CASClient(service_url=service_url, version=django_settings.CAS_VERSION, server_url=django_settings.CAS_SERVER_URL, extra_login_params=django_settings.CAS_EXTRA_LOGIN_PARAMS, renew=django_settings.CAS_RENEW, username_attribute=django_settings.CAS_USERNAME_ATTRIBUTE, proxy_callback=django_settings.CAS_PROXY_CALLBACK)
def authenticate(self, request, **kwargs): """ Method to verify CAS-tickets. :param request: HttpRequest to verification page. :param ticket: Ticket to verify (as string). :param service: Service url to use in verification. :returns user: User instance or None if not verified. """ try: ticket = kwargs['ticket'] service = kwargs['service'] except KeyError: return None user_model = AuthUser # Attempt to verify the ticket with the institution's CAS server client = CASClient(version=2, service_url=service, server_url=str(utils.get_setting('CAS_SERVER_URL'))) username, attributes, pgtiou = client.verify_ticket(ticket) # Add the attributes returned by the CAS server to the session if request and attributes: request.session['attributes'] = attributes # If no username was returned, verification failed if not username: return None # Try to find user try: user = user_model.objects.get_by_natural_key(username) except user_model.DoesNotExist: user = None return user if self.user_can_authenticate(user) else None
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})
class HfLogout(tornado.web.RequestHandler): """ Endpoint for performing HydroFrame logout. When successful, a cookie is removed from the browser. """ cas_client = CASClient(version=3, service_url=env.cas_service_url, server_url=env.cas_server_url) def get(self): cas_logout_url = self.cas_client.get_logout_url( self.request.headers.get('Referer')) self.clear_cookie('cas-username') return self.redirect(cas_logout_url)
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 get_cas_client(service_url=None, request=None): """ initializes the CASClient according to the CAS_* settigs """ # Handle CAS_SERVER_URL without protocol and hostname server_url = django_settings.CAS_SERVER_URL if server_url and request and server_url.startswith('/'): scheme = request.META.get("X-Forwarded-Proto", request.scheme) server_url = scheme + "://" + request.META['HTTP_HOST'] + server_url # assert server_url.startswith('http'), "settings.CAS_SERVER_URL invalid" return CASClient(service_url=service_url, version=django_settings.CAS_VERSION, server_url=server_url, extra_login_params=django_settings.CAS_EXTRA_LOGIN_PARAMS, renew=django_settings.CAS_RENEW, username_attribute=django_settings.CAS_USERNAME_ATTRIBUTE, proxy_callback=django_settings.CAS_PROXY_CALLBACK)
class HfLogin(tornado.web.RequestHandler): """ Endpoint for performing HydroFrame Authentication using CAS + DUO two-factor authentication. When successful, a cookie is set in the browser which can be checked via HFIsAuthenticated. """ cas_client = CASClient(version=3, service_url=env.cas_service_url, server_url=env.cas_server_url) def get(self): next_url = self.get_argument('next', self.request.headers.get('Referer')) ticket = self.get_argument('ticket', None) cas_username = self.get_secure_cookie('cas-username') app_log.info(f'{next_url}, {ticket}, {cas_username}') if cas_username: return self.redirect(self.request.headers.get('Referer')) # perform CAS Authentication if ticket is None: app_log.info('no cas ticket found') # add the referrer url as the next url self.cas_client.service_url += f'?next={next_url}' # No ticket, the request come from end user, send to CAS login cas_login_url = self.cas_client.get_login_url() app_log.info(f'redirecting to {cas_login_url}') return self.redirect(cas_login_url) # There is a ticket, the request come from CAS as callback. # need call `verify_ticket()` to validate ticket and get user profile. user, attributes, pgtiou = self.cas_client.verify_ticket(ticket) if not user: return 'Failed to verify ticket. <a href="/login">Login</a>' else: app_log.info('setting cas-username cookie') self.set_secure_cookie('cas-username', user) return self.redirect(next_url)
def get_cas_client(med_config): return CASClient( version=get_cas_client_version(med_config), service_url=get_cas_client_service_url(med_config), server_url=get_cas_client_server_url(med_config), )
from typing import Optional from cas import CASClient from fastapi import FastAPI from starlette.middleware.sessions import SessionMiddleware from starlette.requests import Request from starlette.responses import Response from fastapi.responses import HTMLResponse app = FastAPI(title=__name__) from fastapi.responses import RedirectResponse cas_client = CASClient( version=3, service_url='http://127.0.0.1:8002/login?next=%2Fprofile', server_url='http://127.0.0.1:8000/cas/' ) app.add_middleware(SessionMiddleware, secret_key="!secret") @app.get('/') async def index(request: Request): return RedirectResponse(request.url_for('login')) @app.get('/profile') async def profile(request: Request): print(request.session.get("user")) user = request.session.get("user") if user:
class CAS: client: CASClient = CASClient( version=3, service_url="http://127.0.0.1:8000/core/login?next=%2F", server_url="http://218.95.164.199:4065/cas/")
class CAS: client: CASClient = CASClient( version=3, # TODO replace with relevant url service_url="http://0.0.0.0:8000/api/core/login?next=%2F", server_url="https://login.iiit.ac.in/cas/")