Exemple #1
0
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.")
Exemple #2
0
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] + ("", "", "", "")),
            ))
Exemple #3
0
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
Exemple #4
0
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
Exemple #5
0
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
Exemple #6
0
    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)
Exemple #7
0
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())
Exemple #8
0
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()})
Exemple #9
0
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")
Exemple #10
0
 def get(self, request):
     raise SecurityError()
Exemple #11
0
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