def _verify_csrf_token(request): # Get the token out of the session # Note: We have to use the private request._session because # request.session is not guaranteed to exist when this function is # called. csrf_token = request._session.get("user.csrf") # Validate that we have a stored token, if we do not then we have nothing # to compare the incoming token against. if csrf_token is None: raise SecurityError("CSRF token not set.") # Attempt to look in the form data request_token = request.form.get("csrf_token") # Also attempt to look in the headers, this makes things like Ajax easier # and PUT/DELETE possible. request_token = request.headers.get("X-CSRF-Token", request_token) # Validate that we have a token attached to this request somehow if not request_token: raise SecurityError("CSRF token missing.") # Validate that the stored token and the request token match each other if not hmac.compare_digest(csrf_token, request_token): raise SecurityError("CSRF token incorrect.")
def _verify_csrf_origin(request): # Determine the origin of this request origin = request.headers.get("Origin", request.headers.get("Referer")) # Fail if we were not able to locate an origin at all if origin is None: raise SecurityError("Origin checking failed - no Origin or Referer.") # Parse the origin and host for comparison origin_parsed = urllib.parse.urlparse(origin) host_parsed = urllib.parse.urlparse(request.host_url) # Fail if our origin is null if origin == "null": raise SecurityError( "Origin checking failed - null does not match {}.".format( urllib.parse.urlunparse(host_parsed[:2] + ("", "", "", "")))) # Fail if the received origin does not match the host if ((origin_parsed.scheme, origin_parsed.hostname, origin_parsed.port) != (host_parsed.scheme, host_parsed.hostname, host_parsed.port)): raise SecurityError( "Origin checking failed - {} does not match {}.".format( urllib.parse.urlunparse(origin_parsed[:2] + ("", "", "", "")), urllib.parse.urlunparse(host_parsed[:2] + ("", "", "", "")), ))
def get_host(environ, trusted_hosts=None): """Return the real host for the given WSGI environment. This first checks the `X-Forwarded-Host` header, then the normal `Host` header, and finally the `SERVER_NAME` environment variable (using the first one it finds). Optionally it verifies that the host is in a list of trusted hosts. If the host is not in there it will raise a :exc:`~werkzeug.exceptions.SecurityError`. :param environ: the WSGI environment to get the host of. :param trusted_hosts: a list of trusted hosts, see :func:`host_is_trusted` for more information. """ if 'HTTP_X_FORWARDED_HOST' in environ: rv = environ['HTTP_X_FORWARDED_HOST'].split(',', 1)[0].strip() elif 'HTTP_HOST' in environ: rv = environ['HTTP_HOST'] else: rv = environ['SERVER_NAME'] if (environ['wsgi.url_scheme'], environ['SERVER_PORT']) not \ in (('https', '443'), ('http', '80')): rv += ':' + environ['SERVER_PORT'] if trusted_hosts is not None: if not host_is_trusted(rv, trusted_hosts): from werkzeug.exceptions import SecurityError raise SecurityError('Host "%s" is not trusted' % rv) return rv
def get_host(environ, trusted_hosts=None): """Return the host for the given WSGI environment. This first checks the ``Host`` header. If it's not present, then ``SERVER_NAME`` and ``SERVER_PORT`` are used. The host will only contain the port if it is different than the standard port for the protocol. Optionally, verify that the host is trusted using :func:`host_is_trusted` and raise a :exc:`~werkzeug.exceptions.SecurityError` if it is not. :param environ: The WSGI environment to get the host from. :param trusted_hosts: A list of trusted hosts. :return: Host, with port if necessary. :raise ~werkzeug.exceptions.SecurityError: If the host is not trusted. """ if 'HTTP_HOST' in environ: rv = environ['HTTP_HOST'] if environ['wsgi.url_scheme'] == 'http' and rv.endswith(':80'): rv = rv[:-3] elif environ['wsgi.url_scheme'] == 'https' and rv.endswith(':443'): rv = rv[:-4] else: rv = environ['SERVER_NAME'] if (environ['wsgi.url_scheme'], environ['SERVER_PORT']) not \ in (('https', '443'), ('http', '80')): rv += ':' + environ['SERVER_PORT'] if trusted_hosts is not None: if not host_is_trusted(rv, trusted_hosts): from werkzeug.exceptions import SecurityError raise SecurityError('Host "%s" is not trusted' % rv) return rv
def get_host(environ, trusted_hosts=None): """Return the real host for the given WSGI environment. This first checks the normal `Host` header, and if it's not present, then `SERVER_NAME` and `SERVER_PORT` environment variables. Optionally it verifies that the host is in a list of trusted hosts. If the host is not in there it will raise a :exc:`~werkzeug.exceptions.SecurityError`. :param environ: the WSGI environment to get the host of. :param trusted_hosts: a list of trusted hosts, see :func:`host_is_trusted` for more information. """ if 'HTTP_HOST' in environ: rv = environ['HTTP_HOST'] if environ['wsgi.url_scheme'] == 'http' and rv.endswith(':80'): rv = rv[:-3] elif environ['wsgi.url_scheme'] == 'https' and rv.endswith(':443'): rv = rv[:-4] else: rv = environ['SERVER_NAME'] if (environ['wsgi.url_scheme'], environ['SERVER_PORT']) not \ in (('https', '443'), ('http', '80')): rv += ':' + environ['SERVER_PORT'] if trusted_hosts is not None: if not host_is_trusted(rv, trusted_hosts): from werkzeug.exceptions import SecurityError raise SecurityError('Host "%s" is not trusted' % rv) return rv
def wrapped(self, view, app, request, *args, **kwargs): # Assume that anything not defined as 'safe' by RFC2616 needs # protection if request.method not in {"GET", "HEAD", "OPTIONS", "TRACE"}: # We have 3 potential states for a view function to be in, it could # have asked for CSRF, exempted for CSRF, or done none of these. if getattr(view, "_csrf", None) is None: # CSRF influences the response and thus we cannot know if it is # safe to access the session or if that will inadvertently # trigger the response to require a Vary: Cookie so if the # function has not explicitly told us one way or another we # will always hard fail on an unsafe method. raise SecurityError("No CSRF protection applied to view") elif getattr(view, "_csrf", None): # The function has explicitly opted in to the CSRF protection # and we can assume that it has handled setting up the CSRF # token as well as making sure that a Vary: Cookie header has # been added. _verify_origin(request) _verify_token(request) # Ensure that the session has a token stored for this request. This is # purposely done *after* we've validated the CSRF above. If there is # no CSRF token stored we want that to be a distinct messages from if # the given token doesn't match a new, random, token. if getattr(view, "_csrf", None): _ensure_csrf_token(request) # If we've gotten to this point, than either the request was a "safe" # method, the view has opted out of CSRF, or the CSRF has been # verified. In any case it *should* be safe to actually process this # request. return fn(self, view, app, request, *args, **kwargs)
def customer_create(): params = request.json required_fields = ['fullname', 'phone'] for rf in required_fields: if not params.has_key(rf): raise BadRequest("Need `%s` field" % rf, jsonify({'errCode': 'ERROR_FIELD_REQUIRED'})) if not len(params['fullname']): raise BadRequest("Fullname not null", jsonify({'errCode': 'ERROR_FULLNAME_IS_NULL'})) phone = params['phone'] email = params['email'] note = params.get('note', "") if not re.match(PHONE_PATTERN, phone): raise BadRequest("Phone is not true format", response=jsonify({'errCode': 'ERROR_PHONE_FORMAT'})) if not re.match(EMAIL_PATTERN, email): raise BadRequest("Email is not true format", jsonify({'errCode': 'ERROR_EMAIL_FORMAT'})) if len(note) > 1000: raise BadRequest("Note is too long", jsonify({'errCode': 'ERROR_NOTE_TOO_LONG'})) conds = (Customer.phone == params['phone']) if params.get('email'): conds |= (Customer.email == params['email']) customer_obj = Customer.query.filter(conds).first() if customer_obj: raise SecurityError("Customer %s is existed!" % params['fullname'], jsonify({'errCode': 'ERROR_CUSTOMER_IS_EXISTED'})) #TODO verify email and phone customer_obj = Customer() customer_obj.fullname = params['fullname'] customer_obj.email = email customer_obj.phone = phone customer_obj.note = note customer_obj.birthday = params.get('birthday') customer_obj.created_at = datetime.datetime.utcnow() customer_obj.updated_at = datetime.datetime.utcnow() db.session.add(customer_obj) db.session.commit() customer_obj = Customer.query.filter(Customer.phone == phone).first() return jsonify(customer_obj.to_dict())
def customer_update(): params = request.json required_fields = ['id'] for rf in required_fields: if not params.has_key(rf): raise BadRequest("Need `%s` field" % rf, jsonify({'errCode': 'ERROR_FIELD_REQUIRED'})) customer_obj = Customer.query.filter_by(id=params['id']).first() if not customer_obj: raise SecurityError("Customer %s is existed!" % params['fullname'], jsonify({'errCode': 'ERROR_CUSTOMER_NOT_EXISTED'})) customer_obj.fullname = params.get('fullname', customer_obj.fullname) customer_obj.email = params.get('email', customer_obj.email) customer_obj.phone = params.get('phone', customer_obj.phone) customer_obj.note = params.get('note', customer_obj.note) customer_obj.birthday = params.get('birthday', customer_obj.birthday) customer_obj.updated_at = datetime.datetime.utcnow() db.session.merge(customer_obj) db.session.commit() return jsonify({customer_obj.to_dict()})
def login(): """ Handle requests to the /login route """ if current_user.is_authenticated: user_access_token_key = 'user_{}_access_token'.format(current_user.id) access_token = cache.get(user_access_token_key) return jsonify({ 'user_id': current_user.id, 'access_token': access_token, 'avatar': current_user.avatar, 'display_name': current_user.display_name, 'first_name': current_user.first_name, 'last_name': current_user.last_name }) params = request.json access_token = params['access_token'] grant_type = params['grant_type'] if grant_type != 'google': raise BadRequest("`grant_type` must be google") verify_url = 'https://www.googleapis.com/oauth2/v3/userinfo?access_token=%s' % access_token try: s = urllib2.urlopen(verify_url) response = json.loads(s.read()) s.close() except urllib2.URLError as e: raise SecurityError('Access token verify failed!') google_id = str(response['sub']) gender = response['gender'] if response.has_key('gender') else None location = None avatar = None if response.has_key('picture'): avatar = response['picture'] timezone = None if response.has_key('timezone'): timezone = int(response['timezone']) email = response['email'] first_name = response.get('given_name', '') last_name = response.get('family_name', '') display_name = response.get('name', '') verified = response['email_verified'] \ if response.has_key('email_verified') and response.has_key('email') else 0 if email in app.config['SUPERVISOR_EMAIL']: user = User.query.filter_by(google_id=google_id).first() if not user: # create new user if not exist user = User() user.google_id = google_id user.email = email user.verified = verified user.email_verified = verified user.first_name = first_name user.last_name = last_name user.display_name = display_name if gender: user.gender = gender if avatar: user.avatar = avatar if timezone: user.timezone = timezone if location: user.location = location user.last_login_date = datetime.datetime.now() user.updated_at = user.last_login_date db.session.add(user) db.session.commit() # save access_token to redis cache user_access_token_key = 'user_{}_access_token'.format(user.id) cache.set(user_access_token_key, access_token, timeout=3600) login_user(user, remember=True) return jsonify({ 'user_id': user.id, 'access_token': access_token, 'avatar': user.avatar, 'display_name': display_name, 'first_name': first_name, 'last_name': last_name }) raise Forbidden("You need to contact with admin to create a account")
def get(self, request): raise SecurityError()
def hash_secret_key(data, attr_name="hashed_secret"): secret = data[attr_name] if len(secret) < MIN_SECRET_LENGTH: raise SecurityError(f"minimal length of secret for API key is {MIN_SECRET_LENGTH}") data[attr_name] = secure_hash(secret) return data