コード例 #1
0
def _decode_jwt_from_request(token_type, locations, fresh):
    # All the places we can get a JWT from in this request
    get_encoded_token_functions = []

    # Get locations in the order specified by the decorator or JWT_TOKEN_LOCATION
    # configuration.
    if not locations:
        locations = config.token_location

    # Add the functions in the order specified by locations.
    for location in locations:
        if location == "cookies":
            get_encoded_token_functions.append(
                lambda: _decode_jwt_from_cookies(token_type))
        if location == "query_string":
            get_encoded_token_functions.append(_decode_jwt_from_query_string)
        if location == "headers":
            get_encoded_token_functions.append(_decode_jwt_from_headers)
        if location == "json":
            get_encoded_token_functions.append(
                lambda: _decode_jwt_from_json(token_type))

    # Try to find the token from one of these locations. It only needs to exist
    # in one place to be valid (not every location).
    errors = []
    decoded_token = None
    jwt_header = None
    for get_encoded_token_function in get_encoded_token_functions:
        try:
            encoded_token, csrf_token = get_encoded_token_function()
            decoded_token = decode_token(encoded_token, csrf_token)
            jwt_header = get_unverified_jwt_headers(encoded_token)
            break
        except NoAuthorizationError as e:
            errors.append(str(e))

    # Do some work to make a helpful and human readable error message if no
    # token was found in any of the expected locations.
    if not decoded_token:
        if len(locations) > 1:
            err_msg = "Missing JWT in {start_locs} or {end_locs} ({details})".format(
                start_locs=", ".join(locations[:-1]),
                end_locs=locations[-1],
                details="; ".join(errors),
            )
            raise NoAuthorizationError(err_msg)
        else:
            raise NoAuthorizationError(errors[0])

    # Additional verifications provided by this extension
    verify_token_type(decoded_token, expected_type=token_type)
    if fresh:
        _verify_token_is_fresh(jwt_header, decoded_token)
    verify_token_not_blocklisted(jwt_header, decoded_token, token_type)
    custom_verification_for_token(jwt_header, decoded_token)

    return decoded_token, jwt_header
コード例 #2
0
    def check(self, header, token):
        # Check if token has already been no-listed.
        origtoken = token
        if 'jti' not in token and 'token' not in token:
            token = jwt_utils.decode_token(token)
        if DBSession.query(JWTNoList).filter(
                JWTNoList.token == token['jti']).count() > 0:
            return True

        return False
コード例 #3
0
ファイル: view_decorators.py プロジェクト: otr0624/StoreApp
def _decode_jwt_from_request(request_type):
    # All the places we can get a JWT from in this request
    get_encoded_token_functions = []

    locations = config.token_location

    # add the functions in the order specified in JWT_TOKEN_LOCATION
    for location in locations:
        if location == "cookies":
            get_encoded_token_functions.append(
                lambda: _decode_jwt_from_cookies(request_type))
        if location == "query_string":
            get_encoded_token_functions.append(_decode_jwt_from_query_string)
        if location == "headers":
            get_encoded_token_functions.append(_decode_jwt_from_headers)
        if location == "json":
            get_encoded_token_functions.append(
                lambda: _decode_jwt_from_json(request_type))

    # Try to find the token from one of these locations. It only needs to exist
    # in one place to be valid (not every location).
    errors = []
    decoded_token = None
    jwt_header = None
    for get_encoded_token_function in get_encoded_token_functions:
        try:
            encoded_token, csrf_token = get_encoded_token_function()
            decoded_token = decode_token(encoded_token, csrf_token)
            jwt_header = get_unverified_jwt_headers(encoded_token)
            break
        except NoAuthorizationError as e:
            errors.append(str(e))

    # Do some work to make a helpful and human readable error message if no
    # token was found in any of the expected locations.
    if not decoded_token:
        token_locations = config.token_location
        multiple_jwt_locations = len(token_locations) != 1

        if multiple_jwt_locations:
            err_msg = "Missing JWT in {start_locs} or {end_locs} ({details})".format(
                start_locs=", ".join(token_locations[:-1]),
                end_locs=token_locations[-1],
                details="; ".join(errors),
            )
            raise NoAuthorizationError(err_msg)
        else:
            raise NoAuthorizationError(errors[0])

    verify_token_type(decoded_token, expected_type=request_type)
    verify_token_not_blacklisted(decoded_token, request_type)
    return decoded_token, jwt_header
コード例 #4
0
ファイル: auth.py プロジェクト: r202-coe-psu/hh-service
def refresh_token():
    user = current_user

    access_token = create_access_token(user)
    refresh_token = create_refresh_token(user)

    jwt_data = decode_token(access_token)

    token = dict(access_token=access_token,
                 refresh_token=refresh_token,
                 issued_date=datetime.datetime.utcnow(),
                 expiry_date=datetime.datetime.utcfromtimestamp(
                     jwt_data.get('exp')))

    return render_json(token)
コード例 #5
0
        def decorate(*args, **kwargs):

            resp = Unauthorized()
            resp.data = {"message": "Invalid token"}

            target_audit_uuid = ""
            if "audit_uuid" in kwargs:
                target_audit_uuid = kwargs["audit_uuid"]
            elif "scan_uuid" in kwargs:
                target_audit_uuid = kwargs["scan_uuid"][0:24] + "0" * 8

            # Anonymous access configuration is allowed for non administration APIs only
            if app.config["ALLOW_ANONYMOUS_AUDIT_ACCESS"] is True and self.admin is False:
                identity = {"name": ""}
            else:
                try:
                    # Check if given JWT is valid
                    verify_jwt_in_request()
                    identity = get_jwt_identity()
                # If the token is valid but already expired
                except ExpiredSignatureError:
                    encoded_token, _ = _decode_jwt_from_headers()
                    expired_token = decode_token(encoded_token, allow_expired=True)
                    identity = expired_token["sub"]
                    if "auth_endpoint" in identity:
                        # Offer re-authorization endpoint for the target audit
                        url = urlparse(identity["auth_endpoint"])
                        audit_qs = {"audit": target_audit_uuid}
                        new_qs = {**parse_qs(url.query), **audit_qs}
                        auth_endpoint = url._replace(query=urlencode(new_qs, doseq=True)).geturl()
                        resp.data["reauth_endpoint"] = auth_endpoint
                    raise resp
                except Exception:
                    raise resp

                # Anonymous token is not allowed when anonymous access configuration is disabled
                if "name" not in identity or len(identity["name"]) == 0:
                    raise resp

                # Check if the token's scope is valid for the specified API's target
                target_scopes = ["*"]
                if self.admin is False and len(target_audit_uuid) > 0:
                    target_scopes.append(target_audit_uuid)
                if identity["scope"] not in target_scopes:
                    raise resp

            g.identity = identity
            return f(*args, **kwargs)
コード例 #6
0
def _decode_jwt_from_json(request_type):
    if request.content_type != "application/json":
        raise NoAuthorizationError("Invalid content-type. Must be application/json.")

    if request_type == "access":
        token_key = config.json_key
    else:
        token_key = config.refresh_json_key

    try:
        encoded_token = request.json.get(token_key, None)
        if not encoded_token:
            raise BadRequest()
    except BadRequest:
        raise NoAuthorizationError('Missing "{}" key in json data.'.format(token_key))

    return decode_token(encoded_token)
コード例 #7
0
def _decode_jwt_from_cookies(request_type):
    if request_type == 'access':
        cookie_key = config.access_cookie_name
        csrf_header_key = config.access_csrf_header_name
    else:
        cookie_key = config.refresh_cookie_name
        csrf_header_key = config.refresh_csrf_header_name

    encoded_token = request.cookies.get(cookie_key)
    if not encoded_token:
        raise NoAuthorizationError('Missing cookie "{}"'.format(cookie_key))

    if config.csrf_protect and request.method in config.csrf_request_methods:
        csrf_value = request.headers.get(csrf_header_key, None)
        if not csrf_value:
            raise CSRFError("Missing CSRF token in headers")
    else:
        csrf_value = None

    return decode_token(encoded_token, csrf_value=csrf_value)
コード例 #8
0
ファイル: auth.py プロジェクト: r202-coe-psu/hh-service
def auth():
    auth_dict = request.get_json()['auth']
    try:
        name = auth_dict['identity']['password']['user']['name']
        password = auth_dict['identity']['password']['user']['password']
    except Exception as e:
        response_dict = request.get_json()
        response_dict.update(e.messages)
        response = render_json(response_dict)
        response.status_code = 400
        abort(response)

    user = models.User.objects(me.Q(username=name) | me.Q(email=name)).first()
    if user:
        if user.verify_password(password):
            access_token = create_access_token(user)
            refresh_token = create_refresh_token(user)

            jwt_data = decode_token(access_token)

            token = dict(methods=['password'],
                         user=dict(id=user.id, name=name),
                         access_token=access_token,
                         refresh_token=refresh_token,
                         issued_date=datetime.datetime.utcnow(),
                         expiry_date=datetime.datetime.utcfromtimestamp(
                             jwt_data.get('exp')))
            return render_json(token)

    errors = [{
        'status': '401',
        'title': 'User or Password mismatch',
        'detail': 'User or Password mismatch'
    }]

    response_dict = request.get_json()
    response_dict['errors'] = errors

    response = render_json(response_dict)
    response.status_code = 401
    abort(response)
コード例 #9
0
    def add(self, token):

        if 'token' in token:
            orig_token = copy.deepcopy(token['token'])
            token_type = token['token']['type']
            decoded_token = token['token']
            token = token['token']['jti']
        elif 'type' in token:
            orig_token = copy.deepcopy(token)
            token_type = token['type']
            decoded_token = token
            token = token['jti']
        else:
            orig_token = copy.deepcopy(token)
            decoded_token = jwt_utils.decode_token(token)
            token_type = decoded_token['type']
            token = decoded_token['jti']

        if self.check('x', decoded_token):
            return

        # Already restricted.
        if DBSession.query(JWTNoList).filter(JWTNoList.token == token).first():
            return

        if token_type == 'access':
            remove_after = datetime.utcnow(
            ) + app.config['JWT_ACCESS_TOKEN_EXPIRES']
        else:
            remove_after = datetime.utcnow(
            ) + app.config['JWT_REFRESH_TOKEN_EXPIRES']

        with ScopedSession() as local_db_session:
            TokenNo = JWTNoList(
                token=token,
                token_type=token_type,
                remove_after=remove_after,
            )
            local_db_session.add(TokenNo)
コード例 #10
0
    def is_accessible(self):
        try:

            token = request.args.get("jwt")
            if not token:
                token = urllib.parse.parse_qsl(request.args.get("url"))[0][1]
            decoded_token = decode_token(token)
            verify_token_not_blacklisted(decoded_token, request_type="access")
            ctx_stack.top.jwt = decoded_token
            if has_user_loader():
                user = user_loader(ctx_stack.top.jwt["identity"])
                if user is None:
                    raise UserLoadError(
                        "user_loader returned None for {}".format(user))
                ctx_stack.top.jwt_user = user

            current_user = get_jwt_identity()
            is_admin = UserModel.query.filter_by(
                username=current_user).one().admin
            return current_user and is_admin
        except Exception as e:
            current_app.logger.critical("FAULTY ADMIN UI ACCESS: %s", str(e))
            return False
コード例 #11
0
def _decode_jwt_from_headers():
    header_name = config.header_name
    header_type = config.header_type

    # Verify we have the auth header
    jwt_header = request.headers.get(header_name, None)
    if not jwt_header:
        raise NoAuthorizationError("Missing {} Header".format(header_name))

    # Make sure the header is in a valid format that we are expecting, ie
    # <HeaderName>: <HeaderType(optional)> <JWT>
    parts = jwt_header.split()
    if not header_type:
        if len(parts) != 1:
            msg = "Bad {} header. Expected value '<JWT>'".format(header_name)
            raise InvalidHeaderError(msg)
        encoded_token = parts[0]
    else:
        if parts[0] != header_type or len(parts) != 2:
            msg = "Bad {} header. Expected value '{} <JWT>'".format(header_name, header_type)
            raise InvalidHeaderError(msg)
        encoded_token = parts[1]

    return decode_token(encoded_token)
コード例 #12
0
def _decode_jwt_from_request(
    locations: LocationType,
    fresh: bool,
    refresh: bool = False,
    verify_type: bool = True,
) -> Tuple[dict, dict, str]:
    # Figure out what locations to look for the JWT in this request
    if isinstance(locations, str):
        locations = [locations]

    if not locations:
        locations = config.token_location

    # Get the decode functions in the order specified by locations.
    # Each entry in this list is a tuple (<location>, <encoded-token-function>)
    get_encoded_token_functions = []
    for location in locations:
        if location == "cookies":
            get_encoded_token_functions.append(
                (location, lambda: _decode_jwt_from_cookies(refresh)))
        elif location == "query_string":
            get_encoded_token_functions.append(
                (location, _decode_jwt_from_query_string))
        elif location == "headers":
            get_encoded_token_functions.append(
                (location, _decode_jwt_from_headers))
        elif location == "json":
            get_encoded_token_functions.append(
                (location, lambda: _decode_jwt_from_json(refresh)))
        else:
            raise RuntimeError(f"'{location}' is not a valid location")

    # Try to find the token from one of these locations. It only needs to exist
    # in one place to be valid (not every location).
    errors = []
    decoded_token = None
    jwt_header = None
    jwt_location = None
    for location, get_encoded_token_function in get_encoded_token_functions:
        try:
            encoded_token, csrf_token = get_encoded_token_function()
            decoded_token = decode_token(encoded_token, csrf_token)
            jwt_location = location
            jwt_header = get_unverified_jwt_headers(encoded_token)
            break
        except NoAuthorizationError as e:
            errors.append(str(e))

    # Do some work to make a helpful and human readable error message if no
    # token was found in any of the expected locations.
    if not decoded_token:
        if len(locations) > 1:
            err_msg = "Missing JWT in {start_locs} or {end_locs} ({details})".format(
                start_locs=", ".join(locations[:-1]),
                end_locs=locations[-1],
                details="; ".join(errors),
            )
            raise NoAuthorizationError(err_msg)
        else:
            raise NoAuthorizationError(errors[0])

    # Additional verifications provided by this extension
    if verify_type:
        verify_token_type(decoded_token, refresh)

    if fresh:
        _verify_token_is_fresh(jwt_header, decoded_token)
    verify_token_not_blocklisted(jwt_header, decoded_token)
    custom_verification_for_token(jwt_header, decoded_token)

    return decoded_token, jwt_header, jwt_location
コード例 #13
0
def decode_jwt_from_request(request_type, **options):
    locations = options.get("locations", [])
    # All the places we can get a JWT from in this request
    get_encoded_token_functions = []
    if locations:
        if "cookies" in locations:
            get_encoded_token_functions.append(
                lambda: _decode_jwt_from_cookies(request_type))
        if "query_string" in locations:
            get_encoded_token_functions.append(_decode_jwt_from_query_string)
        if "headers" in locations:
            get_encoded_token_functions.append(_decode_jwt_from_headers)
        if "json" in locations:
            get_encoded_token_functions.append(
                lambda: _decode_jwt_from_json(request_type))
    else:
        if config.jwt_in_cookies:
            get_encoded_token_functions.append(
                lambda: _decode_jwt_from_cookies(request_type))
        if config.jwt_in_query_string:
            get_encoded_token_functions.append(_decode_jwt_from_query_string)
        if config.jwt_in_headers:
            get_encoded_token_functions.append(_decode_jwt_from_headers)
        if config.jwt_in_json:
            get_encoded_token_functions.append(
                lambda: _decode_jwt_from_json(request_type))

    # Try to find the token from one of these locations. It only needs to exist
    # in one place to be valid (not every location).
    errors = []
    decoded_token = None
    for get_encoded_token_function in get_encoded_token_functions:
        try:
            encoded_token, csrf_token = get_encoded_token_function()
            decoded_token = decode_token(encoded_token, csrf_token)
            break
        except ExpiredSignatureError:
            expired_data = decode_token(encoded_token,
                                        csrf_token,
                                        allow_expired=True)
            if options.get("allow_expired", False):
                decoded_token = expired_data
            else:
                # Save the expired token so
                # we can access it in a callback later
                ctx_stack.top.expired_jwt = expired_data
                raise
        except NoAuthorizationError as e:
            errors.append(str(e))

    # Do some work to make a helpful and human readable error message if no
    # token was found in any of the expected locations.
    if not decoded_token:
        token_locations = config.token_location
        multiple_jwt_locations = len(token_locations) != 1

        if multiple_jwt_locations:
            err_msg = "Missing JWT in {start_locs} or {end_locs} ({details})"\
                .format(
                    start_locs=", ".join(token_locations[:-1]),
                    end_locs=token_locations[-1],
                    details="; ".join(errors)
                )
            raise NoAuthorizationError(err_msg)
        else:
            raise NoAuthorizationError(errors[0])

    verify_token_type(decoded_token, expected_type=request_type)
    verify_token_not_blacklisted(decoded_token, request_type)
    return decoded_token