def test_dispatcher_builds_correctly_signed_path_for_empty_path(self): RULES = [werkzeug.routing.Rule('/', endpoint='test')] urls = Map(self.SECRET, 60, RULES) dispatcher = urls.bind('example.com') path = dispatcher.build('test') signer = itsdangerous.TimestampSigner(self.SECRET) self.assertEqual('', signer.unsign(path.lstrip('/')))
async def login(request: Request, username: str, password: str) -> typing.Union[User, AnonymousUser]: secret = get_settings_variable("SECRET_KEY") signer = itsdangerous.TimestampSigner(str(secret)) max_age = get_settings_variable("SESSION_EXPIRES", default=1209600) cookie_name = get_settings_variable("SESSION_COOKIE_NAME", default="session_id") if not secret: raise CraxImproperlyConfigured( '"SECRET_KEY" variable should be defined to use Authentication backends' ) if hasattr(request, "cookies"): cookies = request.cookies if cookie_name in cookies: session_cookie = cookies[cookie_name] session_cookie = b64decode(session_cookie) user = signer.unsign(session_cookie, max_age=max_age) user = user.decode("utf-8") await set_user(request, username, password, user_pk=int(user.split(":")[1])) else: await set_user(request, username, password) return request.user
def build_static_api_explorer(registry, *cmd_args, **cmd_kwargs): settings = registry.settings build_dir = settings["statics.build_dir"] pathlib.Path(build_dir).mkdir(exist_ok=True) # grab api explorer signer = itsdangerous.TimestampSigner(settings["channelstream.secret"]) sig_for_server = signer.sign("channelstream") result = requests.get( f"{settings['channelstream.url']}/api-explorer", headers={"x-channelstream-secret": sig_for_server}, ) # rewrite the location of channelstream lib to_write = result.text.replace( f"from '{settings['channelstream.url']}/static/channelstream/index.js'", f"from '/static_bundled/node_modules/@channelstream/channelstream/src/index.js'", ).replace(f"{settings['channelstream.url']}/openapi.json", "/static_bundled/openapi.json") with io.open(pathlib.Path(build_dir) / "api-explorer.html", "w") as f: f.write(to_write) result = requests.get( f"{settings['channelstream.url']}/openapi.json", headers={"x-channelstream-secret": sig_for_server}, ) with io.open(pathlib.Path(build_dir) / "openapi.json", "w") as f: f.write(result.text)
def check_token(token): if token is None: raise Unauthorized("Invalid token") try: itsdangerous.TimestampSigner(os.getenv("TOKEN_SECRET")).unsign(token, max_age=60*60*24) except itsdangerous.BadSignature: raise Forbidden("Invalid token")
async def index(): if not app.config.get("REGISTRATIONS", False): return jsonify({"message": "Registrations are disabled."}), 400 return jsonify({ "token": itsdangerous.TimestampSigner( app.config["SECRET_KEY"]).sign("hackgov").decode() })
def signed_session(session_secret: str) -> bytes: # Use the session cookie secret to self sign a cookie oid = str(uuid.uuid4()) signer = itsdangerous.TimestampSigner(session_secret) # Create cookie and sign payload = base64.b64encode(json.dumps({"user": oid}).encode("utf-8")) return signer.sign(payload)
def __init__( self, app: ASGIApp, secret_key: str, session_header: str = 'session', max_age: int = 14 * 24 * 60 * 60, # 14 days, in seconds ) -> None: self.app = app self.signer = itsdangerous.TimestampSigner(str(secret_key)) self.session_header = session_header self.max_age = max_age
def __init__( self, app: ASGIApp, secret_key: typing.Union[str, Secret], session_cookie: str = "session", max_age: int = 14 * 24 * 60 * 60, # 14 days, in seconds ) -> None: self.app = app self.signer = itsdangerous.TimestampSigner(str(secret_key)) self.session_cookie = session_cookie self.max_age = max_age
def __init__(self, app, raise_server_exceptions=True): from source.settings import SECRET dispatch = ASGIDispatch(app=app, raise_app_exceptions=raise_server_exceptions) self.signer = itsdangerous.TimestampSigner(SECRET) super().__init__( base_url="https://testserver", dispatch=dispatch, headers={"accept": "text/html; */*"}, )
def csrf_token(): secret_key = get_settings_variable("SECRET_KEY") if secret_key is None: raise CraxImproperlyConfigured( '"SECRET_KEY" string should be defined in settings to use CSRF Protection' ) signer = itsdangerous.TimestampSigner(str(secret_key)) sign = signer.sign(str(int(time.time()))) encoded = b64encode(sign) csrf_key = encoded.decode("utf-8") return csrf_key
def create_session_signer() -> tuple: secret_key = get_settings_variable("SECRET_KEY") if secret_key is None: raise CraxImproperlyConfigured( '"SECRET_KEY" string should be defined in settings to use Crax Sessions' ) signer = itsdangerous.TimestampSigner( str(secret_key), algorithm=itsdangerous.signer.HMACAlgorithm()) max_age = get_settings_variable("SESSION_EXPIRES", default=1209600) cookie_name = get_settings_variable("SESSION_COOKIE_NAME", default="session_id") same_site = get_settings_variable("SAME_SITE_COOKIE_MODE", default="lax") return signer, max_age, cookie_name, same_site
async def token_check(token): if token is None: raise Unauthorized("Invalid token") try: if token.split(".")[0] != "hackgov": raise Unauthorized("Invalid token") except IndexError: raise Unauthorized("Invalid token") try: itsdangerous.TimestampSigner(app.config["SECRET_KEY"]).unsign( token, max_age=60 * 60 * 24) except itsdangerous.BadSignature: raise Forbidden("Invalid token")
def __init__( self, app: ASGIApp, secret_key: str, cookie_name: str, max_age: int = 14 * 24 * 60 * 60, # 14 days, in seconds same_site: str = "lax", https_only: bool = False, domain: Optional[str] = None, backend_type: Optional[BackendType] = None, backend_client: Optional[Any] = None, custom_session_backend: Optional[ISessionBackend] = None, ) -> None: """ Session Middleware Args: app: The ASGIApp secret_key: The secret key to use. cookie_name: The name of the cookie used to store the session id. max_age: The Max-Age of the cookie (Default to 14 days). same_site: The SameSite attribute of the cookie (Defaults to lax). https_only: Whether to make the cookie https only (Defaults to False). domain: The domain associated to the cookie (Default to None). backend_type: The type of predefined backend to use (Default to None, if None we'll use a regular cookie backend). backend_client: The client to use in the predefined backend. See examples for examples with predefined backends (Default to None). custom_session_backend: A custom backend that implement ISessionBackend. Raises: UnknownPredefinedBackend: The predefined backend type is unkown. """ self.app = app self.backend_type = backend_type or BackendType.cookie self.session_backend = ( custom_session_backend if custom_session_backend else self._get_predefined_session_backend(backend_client)) self.signer = itsdangerous.TimestampSigner(str(secret_key)) self.cookie_name = cookie_name self.max_age = max_age self.domain = domain self._cookie_session_id_field = "_cssid" self.security_flags = f"httponly; samesite={same_site}" if https_only: # Secure flag can be used with HTTPS only self.security_flags += "; secure"
def __init__( self, app: ASGIApp, secret_key: typing.Union[str, Secret], session_cookie: str = "session", max_age: int = 14 * 24 * 60 * 60, # 14 days, in seconds same_site: str = "lax", https_only: bool = False, ) -> None: self.app = app self.signer = itsdangerous.TimestampSigner(str(secret_key)) self.session_cookie = session_cookie self.max_age = max_age self.security_flags = "httponly; samesite=" + same_site if https_only: # Secure flag can be used with HTTPS only self.security_flags += "; secure"
async def get(self): signer = itsdangerous.TimestampSigner("WrongKey") max_age = 600 cookie_name = "session_id" sign = signer.sign("mark:4") encoded = b64encode(sign) session = encoded.decode("utf-8") session_cookie = (f"{cookie_name}={session}; path=/;" f" Max-Age={max_age}; httponly; samesite=lax") signed = {"mark:4": session_cookie} self.request.session = json.dumps(signed) response = JSONResponse( self.request, {"user": self.request.session}, ) return response
async def get(self): secret_key = get_settings_variable("SECRET_KEY") max_age = get_settings_variable("SESSION_EXPIRES", default=1209600) cookie_name = get_settings_variable("SESSION_COOKIE_NAME", default="session_id") signer = itsdangerous.TimestampSigner(str(secret_key)) sign = signer.sign("Anonymous:0") encoded = b64encode(sign) session = encoded.decode("utf-8") session_cookie = (f"{cookie_name}={session}; path=/;" f" Max-Age={max_age}; httponly; samesite=lax") signed = {"Anonymous:0": session_cookie} self.request.session = json.dumps(signed) response = JSONResponse( self.request, {"user": self.request.session}, ) return response
def generate(): if request.method == 'POST': data_user = request.json['username'] data_password = request.json['password'] try: current_user = User.query.filter_by(username=data_user).first() return jsonify( { "token": itsdangerous.TimestampSigner( app.config["SECRET_KEY"]).sign( base64.b64encode(str( current_user.id).encode())).decode() } ) if current_user and current_user.password == data_password else "Wrong credentials." except: traceback.print_exc() return "Something went wrong..", 400 else: return "Method not allowed", 400
def onMessage(self, payload, is_binary): from server.web import app """ We only support JOIN and LEAVE workspace messages. When authentication is implemented we need to verify that the user can join the selected workspace. When authentication is implemented we need to reply the client if the join failed. """ if not is_binary: message = json.loads(payload) if message['action'] == 'JOIN_WORKSPACE': if 'workspace' not in message or 'token' not in message: logger.warning('Invalid join workspace message: ' '{}'.format(message)) self.sendClose() return signer = itsdangerous.TimestampSigner(app.config['SECRET_KEY'], salt="websocket") try: workspace_id = signer.unsign(message['token'], max_age=60) except itsdangerous.BadData as e: self.sendClose() logger.warning('Invalid websocket token for workspace ' '{}'.format(message['workspace'])) logger.exception(e) else: with app.app_context(): workspace = Workspace.query.get(int(workspace_id)) if workspace.name != message['workspace']: logger.warning( 'Trying to join workspace {} with token of ' 'workspace {}. Rejecting.'.format( message['workspace'], workspace.name)) self.sendClose() else: self.factory.join_workspace(self, message['workspace']) if message['action'] == 'LEAVE_WORKSPACE': self.factory.leave_workspace(self, message['workspace'])
def decorated_function(*args, **kwargs): auth = request.authorization if auth: verify = db.devices.find_one(auth['username']) log.debug(auth) s = itsdangerous.TimestampSigner(verify['key']) try: if verify['active'] and s.unsign(auth['password'], max_age=10): return view_function(*args, **kwargs) except itsdangerous.SignatureExpired as e: log.warning("Expired signature from client {}".format( auth['username'])) except itsdangerous.BadTimeSignature as e: log.warning(str(e)) # Auth failed if not all conditions met log.warning("Auth failed: uuid: {}, token: {}".format( auth['username'], auth['password'])) else: log.warning("Auth failed: no HTTP Basic Auth headers") abort(401)
def __init__(self, app: ASGIApp, fapi: FastAPI, secret_key: typing.Union[str, Secret], session_cookie: str = "session", max_age: int = 3000, same_site: str = "lax", https_only: bool = False, dispatch: DispatchFunction = None) -> None: super().__init__(app, dispatch) self.redis = aioredis.create_redis_pool(settings.redis_url) self.redis_inited = False self.app = app self.signer = itsdangerous.TimestampSigner(str(secret_key)) self.session_cookie = session_cookie self.max_age = max_age self.same_site = same_site self.https_only = https_only @fapi.on_event("shutdown") async def shutdown(): self.redis.close() await self.redis.wait_closed()
def __init__( self, app, app_url, client_id=None, secret_key=None, salt=None): Auth.__init__(self, app) self.config = { 'permissions_cache_expiry': 5 * 60 } self._app = app self._app_url = app_url self._oauth_client_id = client_id if secret_key is None and app.server.secret_key is None: raise Exception(dedent(''' app.server.secret_key is missing. Generate a secret key in your Python session with the following commands: >>> import os >>> import base64 >>> base64.b64encode(os.urandom(30)).decode('utf-8') and assign it to the property app.server.secret_key (where app is your dash app instance). Note that you should not do this dynamically: you should create a key and then assign the value of that key in your code. ''')) if salt is None: raise Exception(dedent(''' salt is missing. The salt parameter needs to a string that is unique to this individual Dash app. ''')) self._signer = itsdangerous.TimestampSigner(secret_key, salt=salt) app.server.add_url_rule( '{}_dash-login'.format(app.config['routes_pathname_prefix']), view_func=self.login_api, methods=['post'] ) app.server.add_url_rule( '{}_oauth-redirect'.format(app.config['routes_pathname_prefix']), view_func=self.serve_oauth_redirect, methods=['get'] ) app.server.add_url_rule( '{}_is-authorized'.format(app.config['routes_pathname_prefix']), view_func=self.check_if_authorized, methods=['get'] ) _current_path = os.path.dirname(os.path.abspath(__file__)) # TODO - Dist files with open(os.path.join(_current_path, 'oauth-redirect.js'), 'r') as f: self.oauth_redirect_bundle = f.read() with open(os.path.join(_current_path, 'login.js'), 'r') as f: self.login_bundle = f.read()
def get_auth_token(): # Generate a cryptographically random number for the token tok = base64.b64encode(os.urandom(32)) # Sign it with the API key, giving us a token! s = itsdangerous.TimestampSigner(config['key']) return s.sign(tok).decode('utf-8')
def onMessage(self, payload, is_binary): from faraday.server.web import app """ We only support JOIN and LEAVE workspace messages. When authentication is implemented we need to verify that the user can join the selected workspace. When authentication is implemented we need to reply the client if the join failed. """ if not is_binary: message = json.loads(payload) if message['action'] == 'JOIN_WORKSPACE': if 'workspace' not in message or 'token' not in message: logger.warning('Invalid join workspace message: ' '{}'.format(message)) self.sendClose() return signer = itsdangerous.TimestampSigner(app.config['SECRET_KEY'], salt="websocket") try: workspace_id = signer.unsign(message['token'], max_age=60) except itsdangerous.BadData as e: self.sendClose() logger.warning('Invalid websocket token for workspace ' '{}'.format(message['workspace'])) logger.exception(e) else: with app.app_context(): workspace = Workspace.query.get(int(workspace_id)) if workspace.name != message['workspace']: logger.warning( 'Trying to join workspace {} with token of ' 'workspace {}. Rejecting.'.format( message['workspace'], workspace.name )) self.sendClose() else: self.factory.join_workspace( self, message['workspace']) if message['action'] == 'LEAVE_WORKSPACE': self.factory.leave_workspace(self, message['workspace']) if message['action'] == 'JOIN_AGENT': if 'token' not in message: logger.warn("Invalid agent join message") self.state = WebSocketProtocol.STATE_CLOSING self.sendClose() return False with app.app_context(): try: agent = decode_agent_websocket_token(message['token']) except ValueError: logger.warn('Invalid agent token!') self.state = WebSocketProtocol.STATE_CLOSING self.sendClose() return False # factory will now send broadcast messages to the agent return self.factory.join_agent(self, agent) if message['action'] == 'LEAVE_AGENT': with app.app_context(): (agent_id,) = [ k for (k, v) in connected_agents.items() if v == self ] agent = Agent.query.get(agent_id) assert agent is not None # TODO the agent could be deleted here self.factory.leave_agent(self, agent) self.state = WebSocketProtocol.STATE_CLOSING self.sendClose() return False
def onMessage(self, payload, is_binary): from faraday.server.web import app # pylint:disable=import-outside-toplevel """ We only support JOIN and LEAVE workspace messages. When authentication is implemented we need to verify that the user can join the selected workspace. When authentication is implemented we need to reply the client if the join failed. """ if not is_binary: message = json.loads(payload) if message['action'] == 'JOIN_WORKSPACE': if 'workspace' not in message or 'token' not in message: logger.warning('Invalid join workspace message: ' '{}'.format(message)) self.sendClose() return signer = itsdangerous.TimestampSigner(app.config['SECRET_KEY'], salt="websocket") try: workspace_id = signer.unsign(message['token'], max_age=60) except itsdangerous.BadData as e: self.sendClose() logger.warning('Invalid websocket token for workspace ' '{}'.format(message['workspace'])) logger.exception(e) else: with app.app_context(): workspace = Workspace.query.get(int(workspace_id)) if workspace.name != message['workspace']: logger.warning( 'Trying to join workspace {} with token of ' 'workspace {}. Rejecting.'.format( message['workspace'], workspace.name )) self.sendClose() else: self.factory.join_workspace( self, message['workspace']) if message['action'] == 'LEAVE_WORKSPACE': self.factory.leave_workspace(self, message['workspace']) if message['action'] == 'JOIN_AGENT': if 'token' not in message or 'executors' not in message: logger.warning("Invalid agent join message") self.sendClose(1000, reason="Invalid JOIN_AGENT message") return False with app.app_context(): try: agent = decode_agent_websocket_token(message['token']) update_executors(agent, message['executors']) except ValueError: logger.warning('Invalid agent token!') self.sendClose(1000, reason="Invalid agent token!") return False # factory will now send broadcast messages to the agent return self.factory.join_agent(self, agent) if message['action'] == 'LEAVE_AGENT': with app.app_context(): (agent_id,) = [ k for (k, v) in connected_agents.items() if v == self ] agent = Agent.query.get(agent_id) assert agent is not None # TODO the agent could be deleted here return self.factory.leave_agent(self, agent) if message['action'] == 'RUN_STATUS': with app.app_context(): if 'executor_name' not in message: logger.warning('Missing executor_name param in message: ''{}'.format(message)) return True (agent_id,) = [ k for (k, v) in connected_agents.items() if v == self ] agent = Agent.query.get(agent_id) assert agent is not None # TODO the agent could be deleted here execution_id = message.get('execution_id', None) assert execution_id is not None agent_execution = AgentExecution.query.filter(AgentExecution.id == execution_id).first() if agent_execution: if agent_execution.workspace.name not in \ [ workspace.name for workspace in agent.workspaces ]: logger.exception( ValueError( f"The {agent.name} agent has permission " f"to workspace {agent.workspaces} and " "ask to write to workspace " f"{agent_execution.workspace.name}" ) ) else: agent_execution.successful = message.get('successful', None) agent_execution.running = message.get('running', None) agent_execution.message = message.get('message','') db.session.commit() else: logger.exception( NoResultFound(f"No row was found for agent executor id {execution_id}"))
def check_allowed(self, handler: typing.Callable): errors = None if self.request.user is not None: if hasattr(handler, "login_required"): login_required = handler.login_required if ( hasattr(self.request.user, "pk") and self.request.user.pk == 0 and login_required is True ): errors = { "error_handler": CraxUnauthorized, "error_message": self.request.path, "status_code": 401, } if hasattr(handler, "staff_only"): staff_only = handler.staff_only if self.request.user.is_staff is False and staff_only is True: errors = { "error_handler": CraxForbidden, "error_message": self.request.path, "status_code": 403, } if hasattr(handler, "superuser_only"): superuser_only = handler.superuser_only if self.request.user.is_superuser is False and superuser_only is True: errors = { "error_handler": CraxForbidden, "error_message": self.request.path, "status_code": 403, } if hasattr(handler, "methods") and self.request.scheme in [ "http", "http.request", ]: if self.enable_csrf is True and self.request.method in ["POST", "PATCH"]: if hasattr(handler, "enable_csrf") and handler.enable_csrf is True: if "csrf_token" not in self.request.post: errors = { "error_handler": CraxForbidden, "error_message": "CSRF token missed", "status_code": 403, } elif not self.request.post["csrf_token"]: errors = { "error_handler": CraxForbidden, "error_message": "CSRF token is empty", "status_code": 403, } else: secret_key = get_settings_variable("SECRET_KEY") if secret_key is None: raise CraxImproperlyConfigured( '"SECRET_KEY" string should be defined in settings to use CSRF Protection' ) try: token = self.request.post["csrf_token"] signer = itsdangerous.TimestampSigner(str(secret_key)) max_age = get_settings_variable( "SESSION_EXPIRES", default=1209600 ) session_cookie = b64decode(token) signer.unsign(session_cookie, max_age=max_age) except ( binascii.Error, BadTimeSignature, BadSignature, SignatureExpired, ): errors = { "error_handler": CraxForbidden, "error_message": "CSRF token is incorrect", "status_code": 403, } if not self.request.method: # pragma: no cover errors = { "error_handler": CraxNoMethodGiven, "error_message": handler, "status_code": 500, } elif not handler.methods: errors = { "error_handler": CraxEmptyMethods, "error_message": handler, "status_code": 500, } else: handler.methods += ["HEAD", "OPTIONS"] if self.request.method not in handler.methods: errors = { "error_handler": CraxMethodNotAllowed, "error_message": handler, "status_code": 405, } return errors
import json import typing from base64 import b64decode, b64encode import itsdangerous from itsdangerous.exc import BadTimeSignature, SignatureExpired secret_key = "Ludibrium-Secret-133.221.333.123.111_kvYAtbZkwkhyPv5B" signer = itsdangerous.TimestampSigner(str(secret_key)) data = {"id": 0, "filenames": [], "debug": True} data = b64encode(json.dumps(data).encode("utf-8")) data = signer.sign(data).decode("utf-8") print(data)
def __init__(self, db, secret): self.db = db self.signer = itsdangerous.TimestampSigner(secret)
def get_signer(): return itsdangerous.TimestampSigner(app.config['SECRET_KEY'])
def __init__(self, secret, signature_max_age, *args, **kwargs): self.signer = itsdangerous.TimestampSigner(secret) self.signature_max_age = signature_max_age super(Map, self).__init__(*args, **kwargs)
from django.http import HttpResponseBadRequest from django.utils.translation import ugettext from django.views.decorators.csrf import csrf_exempt from django.views.decorators.http import require_POST import accounts.payment_plans as plans from . import importer as importer_lib from . import importer_worker from .models import AssetImportRequest from .views import _pmrender from accounts.decorators import restrict_minimum_plan from accounts.models import UserSettings from pinecast.helpers import get_object_or_404, json_response from podcasts.models import Podcast, PodcastEpisode signer = itsdangerous.TimestampSigner(settings.SECRET_KEY) @require_POST @login_required @json_response @restrict_minimum_plan(plans.FEATURE_MIN_IMPORTER) @importer_lib.handle_format_exceptions def importer_lookup(req): data = req.POST.get('feed') try: encoded = data.encode('utf-8') except Exception as e: return {'error': 'invalid encoding'}