def _authenticate_user(req): session = req.env['beaker.session'] try: req.context['user'] = session['user'] connection = db.connect() cursor = connection.cursor() cursor.execute('SELECT `csrf_token` FROM `session` WHERE `id` = %s', session['_id']) if cursor.rowcount != 1: cursor.close() connection.close() raise HTTPUnauthorized('Invalid Session', 'CSRF token missing', '') token = cursor.fetchone()[0] if req.get_header('X-CSRF-TOKEN') != token: cursor.close() connection.close() raise HTTPUnauthorized('Invalid Session', 'CSRF validation failed', '') cursor.close() connection.close() except KeyError: raise HTTPUnauthorized('Unauthorized', 'User must be logged in', '')
def on_get(self, req: Request, res: Response): if req.auth is None: raise HTTPNotImplemented('Not Implemented', 'Use Basic Auth method!') auth_type, token = req.auth.split(' ') if auth_type.lower() != 'bearer': raise HTTPUnauthorized("Unauthorized") jwt_payload = self.__validate_token(token) user = self.__get_user(jwt_payload["user"]) res.status = HTTP_200 res.body = json.dumps(user)
def __handle__(*args, **kwargs): """ :param args: :param kwargs: service_name: the name of the service that is using the requester :return: the response object if no error detected :raises: requests.exceptions.Timeout: when the timeout is reached requests.exceptions.ConnectionError: When no connection is available """ service = kwargs.get('service_name', 'Service') if 'ignore_exception' in kwargs: r = function(*args, **kwargs) return r try: r = function(*args, **kwargs) if r.status_code == 401: raise HTTPUnauthorized( title='You are not authorized', description='Please validate your authentication') if r.status_code == 404: raise HTTPNotFound() if r.status_code == 500: logger.error('Internal server error, message {}'.format( r.text)) raise HTTPInternalServerError( 'Failed to process request on {}'.format(service), code='102') if r.status_code > 299: logger.error('Failed to process request, message {}'.format( r.text)) raise HTTPError(str(r.status_code), description=r.text, code='103') return r except requests.exceptions.Timeout: logger.error('{} Timeout'.format(service)) raise HTTPError( HTTP_REQUEST_TIMEOUT, title='{} Timeout'.format(service), description='{} connection timeout'.format(service), code='100') except requests.exceptions.ConnectionError: raise HTTPError(HTTP_INTERNAL_SERVER_ERROR, title='{} Connection Error'.format(service), description='{} connection error'.format(service), code='101')
def delete_subchapter_mutate(cls, info, model=None, **kwargs): if info.context['auth']['data']: if not info.context['auth']['data']['admin']: raise CodeduExceptionHandler(HTTPUnauthorized(description="PERMISSION DENIED")) query = model.get_query(info) model = model._meta.model data = kwargs.get('data', None) if data: instance = get_instance_by_pk(query, model, data) tmp_instance = instance.one() instance.delete() if tmp_instance.token: shutil.rmtree(f"{root_path}/images/subchapter/{tmp_instance.token}") return cls(**{model.__tablename__:tmp_instance}) else: raise CodeduExceptionHandler(HTTPUnauthorized(description=info.context['auth']['description']))
def on_delete(self, req: Request, resp: Response, id: int): token = req.get_param('token', required=True) user_data = get_user_data(token) if not is_site_admin(user_data, self.uowm): raise HTTPUnauthorized( f'Not authorized to make this request', f'You are not authorized to make this request') with self.uowm.start() as uow: template = uow.config_message_template.get_by_id(id) if not template: raise HTTPNotFound( title=f'Message template {id} not found', description=f'Unable to find message template with ID {id}' ) uow.config_message_template.remove(template) uow.commit()
def process_resource(self, request, response, resource, params): # Check the authorization credentials. authorized = False if request.auth is not None and request.auth.startswith('Basic '): # b64decode() returns bytes, but we require a str. credentials = b64decode(request.auth[6:]).decode('utf-8') username, password = credentials.split(':', 1) if (username == config.webservice.admin_user and password == config.webservice.admin_pass): authorized = True if not authorized: # Not authorized. realm = 'Basic realm="{}",charset="{}"'.format(REALM, UTF8) raise HTTPUnauthorized('401 Unauthorized', 'REST API authorization failed', challenges=[realm])
def simple_create_mutate(cls, info, model=None, **kwargs): if info.context['auth']['data']: model = model._meta.model data = kwargs.get('data', None) image_info = info.context.get('image_info', None) if data: data['user_id'] = info.context['auth']['data']['user_id'] db_session = info.context.get('session', None) if db_session: instance = model(**data) db_session.add(instance) db_session_flush(db_session) return cls(**{model.__tablename__:instance}) else: raise CodeduExceptionHandler(HTTPUnauthorized(description=info.context['auth']['description']))
def update_subchapter_mutate(cls, info, model=None, **kwargs): if info.context['auth']['data']: if not info.context['auth']['data']['admin']: raise CodeduExceptionHandler(HTTPUnauthorized(description="PERMISSION DENIED")) query = model.get_query(info) model = model._meta.model data = kwargs.get('data', None) image_info = info.context.get('image_info', None) if data: instance = get_instance_by_pk(query, model, data) instance.update(data) if image_info: image_handle('subchapter', instance.one(), image_info) return cls(**{model.__tablename__:instance.one()}) else: raise CodeduExceptionHandler(HTTPUnauthorized(description=info.context['auth']['description']))
def get_profile(self, account_id): sm = Session_Maker(self.Api_Session) with sm as session: profile = session.query(Profile).filter( Profile.account_id == account_id).first() if profile is None: msg = "Uknown account_id passed." raise HTTPUnauthorized("Bad account_id", msg) profile_dict = { 'gradYear': str(profile.gradYear), 'firstName': profile.firstName, 'lasName': profile.lastName, 'major': profile.major } return profile_dict
def on_post_potential(self, req: Request, resp: Response): token = req.get_param('token', required=True) post_id = req.get_param('post_id', required=True) user_data = get_user_data(token) if not user_data: raise HTTPUnauthorized('Invalid user token provided', 'Invalid user token provided') with self.uowm.start() as uow: template = MemeTemplatePotential(post_id=post_id, submitted_by=user_data['name'], vote_total=1) template.votes.append( MemeTemplatePotentialVote(post_id=template.post_id, user=user_data['name'], vote=1)) uow.meme_template_potential.add(template) uow.commit()
def on_delete(self, req: Request, resp: Response): token = req.get_param('token', required=True) watch_id = req.get_param_as_int('watch_id', required=True) user_data = get_user_data(token) with self.uowm.start() as uow: watch = uow.repostwatch.get_by_id(watch_id) if not watch: raise HTTPNotFound( title='No watch found', description=f'Failed to find watch with ID {watch_id}') if watch.user.lower() != user_data['name'].lower(): if not is_sleuth_admin(token, user_data): raise HTTPUnauthorized( title='You are not authorized to delete this watch', description= 'You are not authorized to delete this post watch') uow.repostwatch.remove(watch) uow.commit()
def wrapper(request, *args, **kw): user = request.context['user'] # this is authentication part if not user.id: raise HTTPUnauthorized('Invalid or expired session') # this is authorization part groups = set(user.groups) if groups_required and not groups.intersection(groups_required): raise HTTPForbidden('Unauthorized access') if groups_forbidden and groups.intersection(groups_forbidden): raise HTTPForbidden('Unauthorized access') return f(*args, **kw)
def on_patch(self, req: Request, resp: Response, subreddit: Text): token = req.get_param('token', required=True) user_data = get_user_data(token) if not is_sub_mod_token(token, subreddit, self.config.reddit_useragent): raise HTTPUnauthorized( f'Not authorized to make changes to {subreddit}', f'You\'re not a moderator on {subreddit}') with self.uowm.start() as uow: monitored_sub = uow.monitored_sub.get_by_sub(subreddit) if not monitored_sub: raise HTTPNotFound( title=f'Subreddit {subreddit} Not Found', description=f'Subreddit {subreddit} Not Found') raw = json.load(req.bounded_stream) for k, v in raw.items(): if k not in self.config.sub_monitor_exposed_config_options: continue if hasattr(monitored_sub, k): if getattr(monitored_sub, k) != v: log.debug('Update %s config | %s: %s => %s', subreddit, k, getattr(monitored_sub, k), v) uow.monitored_sub_config_change.add( MonitoredSubConfigChange( source='site', subreddit=subreddit, config_key=k, old_value=str(getattr(monitored_sub, k)), new_value=str(v), updated_by=user_data['name'])) setattr(monitored_sub, k, v) try: uow.commit() except Exception as e: log.exception('Problem saving config', exc_info=True) raise HTTPInternalServerError( title='Problem Saving Config', description='Something went t**s up when saving the config' ) celery.send_task( 'redditrepostsleuth.core.celery.admin_tasks.update_subreddit_config_from_database', args=[monitored_sub, user_data], queue='monitored_sub_config_update')
def on_patch(self, req: Request, resp: Response): token = req.get_param('token', required=True) user_data = get_user_data(token) data = json.load(req.bounded_stream) with self.uowm.start() as uow: watch = uow.repostwatch.get_by_id(data['id']) if not watch: raise HTTPNotFound( title=f'Post Watch Not Found', description= f'Unable to find post watch with ID {data["id"]}') if watch.user.lower() != user_data['name'].lower(): if not is_sleuth_admin(token, user_data): raise HTTPUnauthorized( title='You are not authorized to make this change', description= 'You are not authorized to modify this post watch') watch.enabled = data['enabled'] uow.commit()
def create_subchapter_mutate(cls, info, model=None, **kwargs): if info.context['auth']['data']: if not info.context['auth']['data']['admin']: raise CodeduExceptionHandler(HTTPUnauthorized(description="PERMISSION DENIED")) model = model._meta.model data = kwargs.get('data', None) image_info = info.context.get('image_info', None) if data: db_session = info.context.get('session', None) if db_session: instance = model(**data) db_session.add(instance) db_session_flush(db_session) if image_info: image_handle('subchapter', instance, image_info) return cls(**{model.__tablename__:instance}) else: raise CodeduExceptionHandler(HTTPUnauthorized(description=info.context['auth']['description']))
def on_patch(self, req: Request, resp: Response, id: int): token = req.get_param('token', required=True) user_data = get_user_data(token) if not is_site_admin(user_data, self.uowm): raise HTTPUnauthorized( f'Not authorized to make this request', f'You are not authorized to make this request') with self.uowm.start() as uow: template = uow.config_message_template.get_by_id(id) if not template: raise HTTPNotFound( title=f'Message template {id} not found', description=f'Unable to find message template with ID {id}' ) raw = json.load(req.bounded_stream) template.template_name = raw['template_name'] template.template = raw['template'] resp.body = json.dumps(template.to_dict()) uow.commit()
def on_post(self, req, resp): """Create a new session based on provided login information""" json = req.json #FIXME: implement timing-invariance to fix timing attacks try: user = User.objects.get(email=json.get("email")) if password_ctx.verify(json.get("password"), user.auth): session = Session() session.user = user session.save() resp.session = session resp.json = {'sid': session.sid, 'uid':str(user.id), 'email': user.email} else: raise AuthenticationError() except (DoesNotExist, AuthenticationError) as err: raise HTTPUnauthorized("AuthenticationError", "No such user or wrong password", "")
def process_resource(self, request, response, resource, params): # Set this attribute on the resource right before it is dispatched to. # This can be used by the resource to provide different responses # based on the API version, and for path_to() to provide an API # version-specific path. resource.api = params.pop('api') # Check the authorization credentials. authorized = False if request.auth is not None and request.auth.startswith('Basic '): # b64decode() returns bytes, but we require a str. credentials = b64decode(request.auth[6:]).decode('utf-8') username, password = credentials.split(':', 1) if (username == config.webservice.admin_user and password == config.webservice.admin_pass): authorized = True if not authorized: # Not authorized. raise HTTPUnauthorized( '401 Unauthorized', 'REST API authorization failed', challenges=['Basic realm=Mailman3'])
def on_post(self, req: Request, resp: Response): token = req.get_param('token', required=True) user_data = get_user_data(token) raw = json.load(req.bounded_stream) if not is_site_admin(user_data, self.uowm): raise HTTPUnauthorized( f'Not authorized to make this request', f'You are not authorized to make this request') with self.uowm.start() as uow: new_template = ConfigMessageTemplate( template_name=raw['template_name'], template=raw['template'], template_slug=raw['template_slug']) uow.config_message_template.add(new_template) try: resp.body = json.dumps(new_template.to_dict()) uow.commit() except IntegrityError as e: raise HTTPInternalServerError( title='Failed to save message template', description=str(e))
def on_get_user(self, req: Request, resp: Response, user: Text): results = [] token = req.get_param('token', required=True) user_data = get_user_data(token) if user.lower() != user_data['name'].lower(): if not is_sleuth_admin(token, user_data): raise HTTPUnauthorized( title='You are not authorized to views these watches', description= f'You are not authorized to view watches for {user}') with self.uowm.start() as uow: watches = uow.repostwatch.get_all_by_user(user_data['name']) for watch in watches: post = uow.posts.get_by_post_id(watch.post_id) if not post: continue results.append({ 'watch': watch.to_dict(), 'post': post.to_dict() }) resp.body = json.dumps(results)
def wrapper(request, *args, **kw): user = request.context['user'] # this is authentication part if not user.id: raise HTTPUnauthorized('Invalid or expired session') # this is authorization part groups = set(user.groups) if self.site_identifier in kw: site_id = int(kw[self.site_identifier]) groups = groups.union(user.site_groups.get(site_id, [])) if groups_required and not groups.intersection(groups_required): raise HTTPForbidden('Unauthorized access') if groups_forbidden and groups.intersection(groups_forbidden): raise HTTPForbidden('Unauthorized access') return f(*args, **kw)
def set_context(token): uid, groups, name, email, mobile, site_groups = None, [], '', None, None, {} if token: try: session = sessions.get( token, ['uid', 'name', 'groups', 'email', 'mobile', 'site_groups'] ) uid, name, groups, email, mobile, site_groups = ( session['uid'], session['name'], session['groups'], session['email'], session['mobile'], session['site_groups'] ) except InvalidSessionError: raise HTTPUnauthorized('Invalid or expired session') return User( sid=token, id=uid, name=name, groups=groups, email=email, mobile=mobile, site_groups=site_groups )
def _decode_jwt_token(self, token): options = dict( ('verify_' + claim, True) for claim in self.verify_claims) options.update( dict(('require_' + claim, True) for claim in self.required_claims)) try: payload = jwt.decode(jwt=token, key=self.secret_key, options=options, algorithms=[self.algorithm], issuer=self.issuer, audience=self.audience, leeway=self.leeway) except InvalidTokenError as ex: raise HTTPUnauthorized(title='401 Unauthorized', description=str(ex), challenges=None) return payload
def process_resource(self, req, resp, resource, params): """If this is not an exempt route, verify that a valid, signed jwt is present. """ if req.path in self.exempt_routes: return token = req.headers.get('AUTHORIZATION', '').partition('Bearer ')[2] try: claims = jwt.decode(token, key=self.secret, audience=self.audience, leeway=self.leeway) params['jwt_claims'] = {} for claim in claims: params['jwt_claims'][claim] = claims[claim] except jwt.InvalidTokenError as err: raise HTTPUnauthorized('Authentication Required', 'Please provide a valid auth token.', None)
def authentication_required(req, resp, resource, uri_kwargs): """Ensure that user is authenticated otherwise return ``401 Unauthorized``. If request fails to authenticate this authorization hook will also include list of ``WWW-Athenticate`` challenges. Args: req (falcon.Request): the request object. resp (falcon.Response): the response object. resource (object): the resource object. uri_kwargs (dict): keyword arguments from the URI template. .. versionadded:: 0.4.0 """ if 'user' not in req.context: args = ["Unauthorized", "This resource requires authentication"] # compat: falcon >= 1.0.0 requires the list of challenges if FALCON_VERSION >= (1, 0, 0): args.append(req.context.get('challenges', [])) raise HTTPUnauthorized(*args)
def on_post(req, resp): login_info = uri.parse_query_string(req.context['body']) user = login_info.get('username') password = login_info.get('password') if user is None or password is None: raise HTTPBadRequest('Invalid login attempt', 'Missing user/password') if not auth_manager.authenticate(user, password): raise HTTPUnauthorized('Authentication failure', 'bad login credentials', '') connection = db.connect() cursor = connection.cursor(db.DictCursor) data = get_user_data(None, {'name': user}, dbinfo=(connection, cursor)) if not data: cursor.close() connection.close() raise HTTPNotFound() session = req.env['beaker.session'] session['user'] = user session.save() csrf_token = '%x' % SystemRandom().getrandbits(128) try: cursor.execute( 'INSERT INTO `session` (`id`, `csrf_token`) VALUES (%s, %s)', (req.env['beaker.session']['_id'], csrf_token)) except db.IntegrityError: raise HTTPBadRequest('Invalid login attempt', 'User already logged in') connection.commit() cursor.close() connection.close() # TODO: purge out of date csrf token data[0]['csrf_token'] = csrf_token resp.body = dumps(data[0])
def on_patch_potential(self, req: Request, resp: Response, id: int): token = req.get_param('token', required=True) vote = req.get_param_as_int('vote', required=True, min_value=-1, max_value=1) user_data = get_user_data(token) if not user_data: raise HTTPUnauthorized('Invalid user token provided', 'Invalid user token provided') with self.uowm.start() as uow: template = uow.meme_template_potential.get_by_id(id) if not template: raise HTTPNotFound( title=f'Unable to find template with ID {id}', description=f'Unable to find template with ID {id}') existing_vote = next( (x for x in template.votes if x.user == user_data['name']), None) if existing_vote and existing_vote.vote == vote: raise HTTPBadRequest( title='Invalid vote', description='You have already cast a vote for this template' ) elif existing_vote: template.vote_total += vote existing_vote.vote = vote else: template.vote_total += vote template.votes.append( MemeTemplatePotentialVote( post_id=template.post_id, user=user_data['name'], vote=vote, meme_template_potential_id=template.id)) uow.commit()
def create_question_mutate(cls, info, model=None, **kwargs): if info.context['auth']['data']: model = model._meta.model data = kwargs.get('data', None) if data: tags = data.get('tags', None) if tags: del data['tags'] data['user_id'] = info.context['auth']['data']['user_id'] db_session = info.context.get('session', None) if db_session: instance = model(**data) if tags: tags = tags.split(" ") exist_tags = {tag.name:tag for tag in gql_models['tag'].get_query(info).filter(gql_models['tag']._meta.model.name.in_(tags)).all()} new_tags = [gql_models['tag']._meta.model(name=tag) for tag in tags if not tag in exist_tags.keys()] db_session.add_all(new_tags) instance.tags = list(exist_tags.values())+new_tags db_session.add(instance) db_session_flush(db_session) return cls(**{model.__tablename__:instance}) else: raise CodeduExceptionHandler(HTTPUnauthorized(description=info.context['auth']['description']))
def update_post_like_mutate(cls, info, model=None, **kwargs): if info.context['auth']['data']: query = model.get_query(info) model = model._meta.model data = kwargs.get('data', None) image_info = info.context.get('image_info', None) if data: data['user_id'] = info.context['auth']['data']['user_id'] db_session = info.context.get('session', None) if db_session: instance = get_instance_by_pk(query, model, data) if not instance.first(): tmp_instance = model(**data) db_session.add(tmp_instance) db_session_flush(db_session) else: tmp_instance = instance.one() instance.delete() return cls(**{model.__tablename__: tmp_instance}) else: raise CodeduExceptionHandler( HTTPUnauthorized( description=info.context['auth']['description']))
def create(self, params, meta, **kwargs): validated = kwargs.get('validated') refresh_token = validated.get('refresh_token') new_refresh_token = generate_user_token() new_access_token = generate_user_token(lenght=128) # redis keys for tokens refresh_token_key = cache.hmget(CACHE_TOKENS_KEYS, refresh_token)[0] user_info_byte = cache.hgetall(refresh_token_key) if not user_info_byte: raise HTTPUnauthorized(title="Unauthorized", description="Invalid token") user_info = {} for k, v in user_info_byte.items(): user_info[k.decode()] = v.decode() new_refresh_token_key = CACHE_REFRESH_TOKEN.format( project_id=user_info.get('project'), service=user_info.get('service'), token=new_refresh_token, ) new_access_token_key = CACHE_ACCESS_TOKEN.format( project_id=user_info.get('project'), service=user_info.get('service'), token=new_access_token, ) cache_service_tokens_key = CACHE_SERVICE_TOKEN_LIST.format( project_id=user_info.get('project'), service=user_info.get('service')) # old access token access_token = user_info.pop('access_token', None) access_token_key = cache.hmget(CACHE_TOKENS_KEYS, access_token)[0] # delete old access token from redis cache.delete(access_token_key) cache.hdel(CACHE_TOKENS_KEYS, access_token) # add the access and refresh token in service_tokens cache.sadd(cache_service_tokens_key, new_access_token) cache.sadd(cache_service_tokens_key, new_refresh_token) # set the new access token cache.hmset(new_access_token_key, user_info) cache.hset(CACHE_TOKENS_KEYS, new_access_token, new_access_token_key) # update user_info with access token which corresponds to new refresh token user_info['access_token'] = new_access_token # set the new refresh token with updated user_info cache.hmset(new_refresh_token_key, user_info) cache.hset(CACHE_TOKENS_KEYS, new_refresh_token, new_refresh_token_key) # remove the old refresh token from redis cache.delete(refresh_token_key) cache.hdel(CACHE_TOKENS_KEYS, refresh_token) # set expire time for the access token cache.expire(new_access_token_key, CACHE_ACCESS_TOKEN_EXPIRES_IN) return { "refresh_token": new_refresh_token, "access_token": new_access_token, "expires_in": CACHE_ACCESS_TOKEN_EXPIRES_IN }