예제 #1
0
파일: test_link.py 프로젝트: rolinge/fence
def test_google_link_no_proxy_group(
    app,
    client,
    db_session,
    encoded_creds_jwt,
    add_new_g_acnt_mock,
    google_auth_get_user_info_mock,
    add_google_email_to_proxy_group_mock,
):
    user_id = encoded_creds_jwt["user_id"]

    test_auth_code = "abc123"
    redirect = "http://localhost"
    google_account = "*****@*****.**"

    test_session_jwt = create_session_token(
        app.keypairs[0],
        config.get("SESSION_TIMEOUT"),
        context={
            "google_link": True,
            "user_id": user_id,
            "google_proxy_group_id": None,  # <- no proxy group
            "redirect": redirect,
        },
    )

    existing_account = UserGoogleAccount(email=google_account, user_id=user_id)
    db_session.add(existing_account)
    db_session.commit()

    # manually set cookie for initial session
    client.set_cookie("localhost",
                      config["SESSION_COOKIE_NAME"],
                      test_session_jwt,
                      httponly=True)

    # simulate successfully authed reponse with user email
    google_auth_get_user_info_mock.return_value = {"email": google_account}

    r = client.get("/link/google/callback",
                   query_string={"code": test_auth_code})

    assert not add_new_g_acnt_mock.called

    # make sure we're redirecting with error information
    parsed_url = urlparse(r.headers["Location"])
    query_params = parse_qs(parsed_url.query)
    response_redirect = urlunparse(
        (parsed_url.scheme, parsed_url.netloc, parsed_url.path, "", "", ""))
    assert "exp" not in query_params
    assert "linked_email" not in query_params
    assert "error" in query_params
    assert "error_description" in query_params
    assert response_redirect == redirect

    assert not flask.session.get("google_link")
    assert not flask.session.get("user_id")
    assert not flask.session.get("google_proxy_group_id")

    assert not add_google_email_to_proxy_group_mock.called
예제 #2
0
def test_valid_session_modified(app):
    username = "******"
    modified_username = "******"

    test_session_jwt = create_session_token(app.keypairs[0],
                                            config.get("SESSION_TIMEOUT"),
                                            context={"username": username})

    # Test that once the session is started, we have access to
    # the username
    with app.test_client() as client:
        # manually set cookie for initial session
        client.set_cookie(
            "localhost",
            config["SESSION_COOKIE_NAME"],
            test_session_jwt,
            httponly=True,
            samesite="Lax",
        )
        with client.session_transaction() as session:

            assert session["username"] == username
            session["username"] = modified_username

        with client.session_transaction() as session:
            assert session["username"] == modified_username
예제 #3
0
def test_expired_session_timeout(app):
    # make the start time be one timeout in the past (so the
    # session is expired)
    max_inactivity = app.config.get("SESSION_TIMEOUT")
    now = int(time.time())
    last_active = (now - max_inactivity.seconds)
    username = "******"

    # since we're timetraveling, we have to trick the JWT (since it relies
    # on the current time and this expiration to calculate
    # the actual expiration time). For testing, we'll "expire" it on creation
    jwt_expiration = 0
    test_session_jwt = create_session_token(app.keypairs[0],
                                            jwt_expiration,
                                            context=dict(
                                                session_started=last_active,
                                                username=username))

    with app.test_client() as client:
        # manually set cookie for initial session
        client.set_cookie("localhost", SESSION_COOKIE_NAME, test_session_jwt)
        with client.session_transaction() as session:
            # make sure we don't have the username when opening
            # the session, since it has expired
            assert session.get("username") != username
예제 #4
0
def test_expired_session_lifetime(app):
    # make the start time be max lifetime ago (so it's expired)
    lifetime = config.get("SESSION_LIFETIME")
    now = int(time.time())
    one_lifetime_ago = now - lifetime
    username = "******"

    test_session_jwt = create_session_token(
        app.keypairs[0],
        config.get("SESSION_TIMEOUT"),
        context=dict(session_started=one_lifetime_ago, username=username),
    )

    with app.test_client() as client:
        # manually set cookie for initial session
        client.set_cookie(
            "localhost",
            config["SESSION_COOKIE_NAME"],
            test_session_jwt,
            httponly=True,
            samesite="Lax",
        )
        with client.session_transaction() as session:
            # make sure we don't have the username when opening
            # the session, since it has expired
            assert session.get("username") != username
예제 #5
0
def test_google_link_auth_return(
    app,
    client,
    db_session,
    encoded_creds_jwt,
    google_auth_get_user_info_mock,
    add_google_email_to_proxy_group_mock,
):
    """
    Test the link endpoint that gets hit after authN. Make sure we
    make calls to create new user google accounts and return a redirect
    with the redirect from the flask.session.
    """
    user_id = encoded_creds_jwt["user_id"]
    proxy_group_id = encoded_creds_jwt["proxy_group_id"]

    test_auth_code = "abc123"
    redirect = "http://localhost"
    google_account = "*****@*****.**"

    test_session_jwt = create_session_token(
        app.keypairs[0],
        app.config.get("SESSION_TIMEOUT"),
        context={
            "google_link": True,
            "user_id": user_id,
            "google_proxy_group_id": proxy_group_id,
            "redirect": redirect,
        },
    )

    # manually set cookie for initial session
    client.set_cookie("localhost", SESSION_COOKIE_NAME, test_session_jwt)

    # simulate successfully authed reponse with user email
    google_auth_get_user_info_mock.return_value = {"email": google_account}

    r = client.get("/link/google/callback",
                   query_string={"code": test_auth_code})

    assert r.status_code == 302
    parsed_url = urlparse(r.headers["Location"])
    query_params = parse_qs(parsed_url.query)
    response_redirect = urlunparse(
        (parsed_url.scheme, parsed_url.netloc, parsed_url.path, "", "", ""))
    assert "exp" in query_params
    assert query_params["linked_email"][0] == google_account
    assert response_redirect == redirect

    user_google_account = (db_session.query(UserGoogleAccount).filter(
        UserGoogleAccount.email == google_account,
        UserGoogleAccount.user_id == user_id,
    ).first())
    assert user_google_account

    assert not flask.session.get("google_link")
    assert not flask.session.get("user_id")
    assert not flask.session.get("google_proxy_group_id")

    assert add_google_email_to_proxy_group_mock.called
예제 #6
0
def test_valid_session_valid_access_token_diff_user(app, test_user_a,
                                                    test_user_b, db_session,
                                                    monkeypatch):
    """
    Test the case where a valid access token is in a cookie, but it's for a
    different user than the one logged in. Make sure that a new access token
    is created for the logged in user and the response doesn't contain info
    for the non-logged in user.
    """
    monkeypatch.setitem(config, "MOCK_AUTH", False)
    user = db_session.query(User).filter_by(id=test_user_a["user_id"]).first()
    keypair = app.keypairs[0]

    test_session_jwt = create_session_token(
        keypair,
        config.get("SESSION_TIMEOUT"),
        context={
            "username": user.username,
            "provider": "google"
        },
    )

    # different user's access token
    other_user = db_session.query(User).filter_by(
        id=test_user_b["user_id"]).first()
    test_access_jwt = generate_signed_access_token(
        kid=keypair.kid,
        private_key=keypair.private_key,
        user=other_user,
        expires_in=config["ACCESS_TOKEN_EXPIRES_IN"],
        scopes=["openid", "user"],
        iss=config.get("BASE_URL"),
    ).token

    with app.test_client() as client:
        # manually set cookie for initial session
        client.set_cookie("localhost", config["SESSION_COOKIE_NAME"],
                          test_session_jwt)
        client.set_cookie("localhost", config["ACCESS_TOKEN_COOKIE_NAME"],
                          test_access_jwt)

        response = client.get("/user")
        cookies = _get_cookies_from_response(response)

        # either there's a new access_token in the response headers or the
        # previously set access token been changed
        access_token = (cookies.get("access_token", {}).get("access_token")
                        or test_access_jwt)

        valid_access_token = validate_jwt(access_token, purpose="access")
        assert response.status_code == 200
        response_user_id = response.json.get("user_id") or response.json.get(
            "sub")
        assert response_user_id == test_user_a["user_id"]

        user_id = valid_access_token.get("user_id") or valid_access_token.get(
            "sub")
        assert test_user_a["user_id"] == int(user_id)
예제 #7
0
def test_patch_google_link_account_doesnt_exist(
    app,
    client,
    db_session,
    encoded_creds_jwt,
    google_auth_get_user_info_mock,
    add_google_email_to_proxy_group_mock,
):
    """
    Test extending expiration for an unlinked G account access via PATCH.
    """
    encoded_credentials_jwt = encoded_creds_jwt["jwt"]
    user_id = encoded_creds_jwt["user_id"]
    proxy_group_id = encoded_creds_jwt["proxy_group_id"]

    test_session_jwt = create_session_token(
        app.keypairs[0],
        config.get("SESSION_TIMEOUT"),
        context={"google_proxy_group_id": proxy_group_id},
    )

    # manually set cookie for initial session
    client.set_cookie(
        "localhost",
        config["SESSION_COOKIE_NAME"],
        test_session_jwt,
        httponly=True,
        samesite="Lax",
    )

    r = client.patch(
        "/link/google", headers={"Authorization": "Bearer " + encoded_credentials_jwt}
    )

    assert r.status_code == 404

    # make sure accounts weren't created
    g_account = (
        db_session.query(UserGoogleAccount)
        .filter(UserGoogleAccount.user_id == user_id)
        .first()
    )
    assert not g_account

    account_in_proxy_group = (
        db_session.query(UserGoogleAccountToProxyGroup)
        .filter(UserGoogleAccountToProxyGroup.proxy_group_id == proxy_group_id)
        .first()
    )
    assert not account_in_proxy_group

    assert not add_google_email_to_proxy_group_mock.called
예제 #8
0
def test_valid_session_valid_access_token(app, db_session, test_user_a,
                                          test_user_b, monkeypatch):
    monkeypatch.setitem(config, "MOCK_AUTH", False)
    user = db_session.query(User).filter_by(id=test_user_a["user_id"]).first()
    keypair = app.keypairs[0]

    test_session_jwt = create_session_token(
        keypair,
        config.get("SESSION_TIMEOUT"),
        context={
            "username": user.username,
            "provider": "google"
        },
    )

    test_access_jwt = generate_signed_access_token(
        kid=keypair.kid,
        private_key=keypair.private_key,
        user=user,
        expires_in=config["ACCESS_TOKEN_EXPIRES_IN"],
        scopes=["openid", "user"],
        iss=config.get("BASE_URL"),
        forced_exp_time=None,
        client_id=None,
        linked_google_email=None,
    ).token

    # Test that once the session is started, we have access to
    # the username
    with app.test_client() as client:
        # manually set cookie for initial session
        client.set_cookie(
            "localhost",
            config["SESSION_COOKIE_NAME"],
            test_session_jwt,
            httponly=True,
            samesite="Lax",
        )
        client.set_cookie(
            "localhost",
            config["ACCESS_TOKEN_COOKIE_NAME"],
            test_access_jwt,
            httponly=True,
            samesite="Lax",
        )

        response = client.get("/user")
        user_id = response.json.get("user_id") or response.json.get("sub")
        assert response.status_code == 200
        assert user_id == user.id
예제 #9
0
def test_google_login_http_headers_are_less_than_4k_for_user_with_many_projects(
        app, client, monkeypatch, db_session):
    """
    Test that when the current user has access to a large number of projects,
    the http headers of the response from a GET to /login/google/login are less
    than 4k bytes in size.
    """
    monkeypatch.setitem(config, "MOCK_GOOGLE_AUTH", True)
    test_session_jwt = create_session_token(
        app.keypairs[0],
        config.get("SESSION_TIMEOUT"),
        context={
            "redirect":
            "https://localhost/user/oauth2/authorize?client_id=7f7kAS4MJraUuo77d7RWHr4mZ6bvGtuzup7hw46I&response_type=id_token&redirect_uri=https://webapp.example/fence&scope=openid+user+data+google_credentials&nonce=randomvalue"
        },
    )
    client.set_cookie(
        "localhost",
        config["SESSION_COOKIE_NAME"],
        test_session_jwt,
        httponly=True,
        samesite="Lax",
    )

    user_projects = {
        "test": {
            f"project{x}": {
                "read",
                "read-storage",
                "update",
                "upload",
                "create",
                "write-storage",
                "delete",
            }
            for x in range(20)
        }
    }
    user_info = {
        "test": {
            "tags": {},
        }
    }
    dbGaP = os.environ.get("dbGaP") or config.get("dbGaP")
    syncer = UserSyncer(dbGaP, config["DB"], {})
    syncer.sync_to_db_and_storage_backend(user_projects, user_info, db_session)

    resp = client.get("/login/google/login")
    assert len(str(resp.headers)) < 4096
    assert resp.status_code == 302
예제 #10
0
    def get_updated_token(self, app):
        if self._encoded_token:
            # Create a new token by passing in fields from the current
            # token. If `session_started` is None, it will be defaulted
            # to the issue time for the JWT and passed into future tokens
            # to keep track of the overall lifetime of the session
            token = create_session_token(
                flask.current_app.keypairs[0],
                config.get("SESSION_TIMEOUT"),
                self.session_token["context"],
            )
            self._encoded_token = token

        return self._encoded_token
예제 #11
0
def test_valid_session(app):
    username = "******"

    test_session_jwt = create_session_token(
        app.keypairs[0],
        app.config.get("SESSION_TIMEOUT").seconds,
        context={'username': username},
    )

    # Test that once the session is started, we have access to
    # the username
    with app.test_client() as client:
        # manually set cookie for initial session
        client.set_cookie("localhost", SESSION_COOKIE_NAME, test_session_jwt)
        with client.session_transaction() as session:
            assert session["username"] == username
예제 #12
0
def test_session_cleared(app):
    username = "******"

    test_session_jwt = create_session_token(
        app.keypairs[0], config.get("SESSION_TIMEOUT"), context=dict(username=username)
    )

    # Test that once the session is started, we have access to
    # the username
    with app.test_client() as client:
        # manually set cookie for initial session
        client.set_cookie("localhost", config["SESSION_COOKIE_NAME"], test_session_jwt)
        with client.session_transaction() as session:
            session["username"] = username
            session.clear()
            assert session.get("username") != username
        client_cookies = [cookie.name for cookie in client.cookie_jar]
        assert config["SESSION_COOKIE_NAME"] not in client_cookies
예제 #13
0
def test_logout_fence(app, client, user_with_fence_provider, monkeypatch):
    other_fence_logout_url = "https://test-url.com"
    monkeypatch.setitem(config, "MOCK_AUTH", False)
    monkeypatch.setitem(config, "SHIBBOLETH_HEADER", None)
    monkeypatch.setitem(config, "OPENID_CONNECT",
                        {"fence": {
                            "api_base_url": other_fence_logout_url
                        }})

    username = "******"

    test_session_jwt = create_session_token(
        app.keypairs[0],
        config.get("SESSION_TIMEOUT"),
        context={
            "username": username,
            "provider": "fence"
        },
    )

    # Test that once the session is started, we have access to
    # the username
    redirect = "https://some_site.com"
    # fence will reject unexpected redirect URLs, so we patch the validator to consider
    # this redirect valid
    with mock.patch("fence.allowed_login_redirects",
                    return_value={"some_site.com"}):
        # manually set cookie for initial session
        client.set_cookie(
            "localhost",
            config["SESSION_COOKIE_NAME"],
            test_session_jwt,
            httponly=True,
            samesite="Lax",
        )

        r = client.get("/logout?next={}".format(redirect))
        assert r.status_code == 302
        assert r.location.startswith(other_fence_logout_url)

        parsed_url = urllib.parse.urlparse(r.location)
        result_redirect = urllib.parse.parse_qs(
            parsed_url.query).get("next")[0]
        assert result_redirect == redirect
예제 #14
0
def test_logout_fence(app, user_with_fence_provider, monkeypatch):
    other_fence_logout_url = "https://test-url.com"
    monkeypatch.setitem(app.config, "MOCK_AUTH", False)
    monkeypatch.setitem(app.config, "SHIBBOLETH_HEADER", None)
    monkeypatch.setitem(
        app.config,
        "OPENID_CONNECT",
        {"fence": {
            "api_base_url": other_fence_logout_url
        }},
    )

    username = "******"

    test_session_jwt = create_session_token(
        app.keypairs[0],
        app.config.get("SESSION_TIMEOUT"),
        context={
            "username": username,
            "provider": "fence"
        },
    )

    # Test that once the session is started, we have access to
    # the username
    with app.test_client() as client:
        # manually set cookie for initial session
        client.set_cookie("localhost", SESSION_COOKIE_NAME, test_session_jwt)

        r = client.get("/logout?next=https://some_site.com")
        assert r.status_code == 302
        assert r.location.startswith(other_fence_logout_url)

        parsed_url = urlparse.urlparse(r.location)
        raw_redirect = urlparse.parse_qs(parsed_url.query).get("next")[0]
        redirect = urllib.unquote(raw_redirect)
        assert redirect == "https://some_site.com"
예제 #15
0
def test_google_link_g_account_access_extension(
    app,
    client,
    db_session,
    encoded_creds_jwt,
    add_new_g_acnt_mock,
    google_auth_get_user_info_mock,
    add_google_email_to_proxy_group_mock,
):
    """
    Test the link endpoint that gets hit after authN when the provided Google
    account is already linked. This time test if we correctly extend the
    google accounts access.
    """
    user_id = encoded_creds_jwt["user_id"]
    proxy_group_id = encoded_creds_jwt["proxy_group_id"]

    original_expiration = 1000
    test_auth_code = "abc123"
    redirect = "http://localhost"
    google_account = "*****@*****.**"

    test_session_jwt = create_session_token(
        app.keypairs[0],
        config.get("SESSION_TIMEOUT"),
        context={
            "google_link": True,
            "user_id": user_id,
            "google_proxy_group_id": proxy_group_id,
            "redirect": redirect,
        },
    )

    existing_account = UserGoogleAccount(email=google_account, user_id=user_id)
    db_session.add(existing_account)
    db_session.commit()
    g_account_access = UserGoogleAccountToProxyGroup(
        user_google_account_id=existing_account.id,
        proxy_group_id=proxy_group_id,
        expires=original_expiration,
    )
    db_session.add(g_account_access)
    db_session.commit()

    # manually set cookie for initial session
    client.set_cookie("localhost", config["SESSION_COOKIE_NAME"],
                      test_session_jwt)

    # simulate successfully authed reponse with user email
    google_auth_get_user_info_mock.return_value = {"email": google_account}

    r = client.get("/link/google/callback",
                   query_string={"code": test_auth_code})

    account_in_proxy_group = (
        db_session.query(UserGoogleAccountToProxyGroup).filter(
            UserGoogleAccountToProxyGroup.user_google_account_id ==
            existing_account.id).first())
    assert account_in_proxy_group.proxy_group_id == proxy_group_id

    # check that expiration changed and that it's less than the cfg
    # expires in (since this check will happen a few seconds after
    # it gets set)
    assert account_in_proxy_group.expires != original_expiration
    assert account_in_proxy_group.expires <= (
        int(time.time()) + config["GOOGLE_ACCOUNT_ACCESS_EXPIRES_IN"])

    assert not add_new_g_acnt_mock.called
    assert r.status_code == 302

    parsed_url = urlparse(r.headers["Location"])
    query_params = parse_qs(parsed_url.query)
    response_redirect = urlunparse(
        (parsed_url.scheme, parsed_url.netloc, parsed_url.path, "", "", ""))
    assert "exp" in query_params
    assert query_params["linked_email"][0] == google_account
    assert response_redirect == redirect

    assert not flask.session.get("google_link")
    assert not flask.session.get("user_id")
    assert not flask.session.get("google_proxy_group_id")

    assert not add_google_email_to_proxy_group_mock.called
예제 #16
0
def test_google_link_g_account_exists(
    app,
    client,
    db_session,
    encoded_creds_jwt,
    add_new_g_acnt_mock,
    google_auth_get_user_info_mock,
    add_google_email_to_proxy_group_mock,
):
    """
    Test the link endpoint that gets hit after authN when the provided Google
    account is already linked. Make sure we don't attempt to create a new one
    and that we redirect with no errors
    """
    user_id = encoded_creds_jwt["user_id"]
    proxy_group_id = encoded_creds_jwt["proxy_group_id"]

    test_auth_code = "abc123"
    redirect = "http://localhost"
    google_account = "*****@*****.**"

    test_session_jwt = create_session_token(
        app.keypairs[0],
        config.get("SESSION_TIMEOUT"),
        context={
            "google_link": True,
            "user_id": user_id,
            "google_proxy_group_id": proxy_group_id,
            "redirect": redirect,
        },
    )

    existing_account = UserGoogleAccount(email=google_account, user_id=user_id)
    db_session.add(existing_account)
    db_session.commit()

    # manually set cookie for initial session
    client.set_cookie(
        "localhost",
        config["SESSION_COOKIE_NAME"],
        test_session_jwt,
        httponly=True,
        samesite="Lax",
    )

    # simulate successfully authed reponse with user email
    google_auth_get_user_info_mock.return_value = {"email": google_account}

    r = client.get("/link/google/callback", query_string={"code": test_auth_code})

    assert not add_new_g_acnt_mock.called
    assert r.status_code == 302

    parsed_url = urlparse(r.headers["Location"])
    query_params = parse_qs(parsed_url.query)
    response_redirect = urlunparse(
        (parsed_url.scheme, parsed_url.netloc, parsed_url.path, "", "", "")
    )
    assert "exp" in query_params
    assert query_params["linked_email"][0] == google_account
    assert response_redirect == redirect

    assert not flask.session.get("google_link")
    assert not flask.session.get("user_id")
    assert not flask.session.get("google_proxy_group_id")

    # check that we're adding the G account to the proxy group
    assert add_google_email_to_proxy_group_mock.called
예제 #17
0
def test_patch_google_link(
    app,
    client,
    db_session,
    encoded_creds_jwt,
    google_auth_get_user_info_mock,
    add_google_email_to_proxy_group_mock,
):
    """
    Test extending expiration for previously linked G account access via PATCH.
    Test valid and invalid expires_in parameters.
    """
    encoded_credentials_jwt = encoded_creds_jwt["jwt"]
    user_id = encoded_creds_jwt["user_id"]
    proxy_group_id = encoded_creds_jwt["proxy_group_id"]

    original_expiration = 1000
    google_account = "*****@*****.**"

    test_session_jwt = create_session_token(
        app.keypairs[0],
        config.get("SESSION_TIMEOUT"),
        context={
            "google_proxy_group_id": proxy_group_id,
            "linked_google_email": google_account,
        },
    )

    existing_account = UserGoogleAccount(email=google_account, user_id=user_id)
    db_session.add(existing_account)
    db_session.commit()
    g_account_access = UserGoogleAccountToProxyGroup(
        user_google_account_id=existing_account.id,
        proxy_group_id=proxy_group_id,
        expires=original_expiration,
    )
    db_session.add(g_account_access)
    db_session.commit()

    # manually set cookie for initial session
    client.set_cookie("localhost", config["SESSION_COOKIE_NAME"],
                      test_session_jwt)

    r = client.patch(
        "/link/google",
        headers={"Authorization": "Bearer " + encoded_credentials_jwt})

    assert r.status_code == 200

    account_in_proxy_group = (
        db_session.query(UserGoogleAccountToProxyGroup).filter(
            UserGoogleAccountToProxyGroup.user_google_account_id ==
            existing_account.id).first())
    assert account_in_proxy_group.proxy_group_id == proxy_group_id

    # check that expiration changed and that it's less than the cfg
    # expires in (since this check will happen a few seconds after
    # it gets set)
    updated_expiration = account_in_proxy_group.expires
    assert updated_expiration != original_expiration
    assert updated_expiration <= (int(time.time()) +
                                  config["GOOGLE_ACCOUNT_ACCESS_EXPIRES_IN"])

    assert not add_google_email_to_proxy_group_mock.called

    # invalid expires_in: should fail
    requested_exp = "abc"  # expires_in must be int >0
    r = client.patch(
        "/link/google?expires_in={}".format(requested_exp),
        headers={"Authorization": "Bearer " + encoded_credentials_jwt},
    )
    assert r.status_code == 400

    # valid expires_in: should succeed
    requested_exp = 60
    r = client.patch(
        "/link/google?expires_in={}".format(requested_exp),
        headers={"Authorization": "Bearer " + encoded_credentials_jwt},
    )
    assert r.status_code == 200

    account_in_proxy_group = (
        db_session.query(UserGoogleAccountToProxyGroup).filter(
            UserGoogleAccountToProxyGroup.user_google_account_id ==
            existing_account.id).first())
    # make sure the link is valid for the requested time
    # (allow up to 15 sec for runtime)
    diff = account_in_proxy_group.expires - int(time.time())
    assert requested_exp <= diff <= requested_exp + 15
예제 #18
0
def test_patch_google_link_account_not_in_token(
    app,
    client,
    db_session,
    encoded_creds_jwt,
    google_auth_get_user_info_mock,
    add_google_email_to_proxy_group_mock,
):
    """
    Test extending expiration for previously linked G account access via PATCH.

    This will test the case where the linking happened during the life
    of an access token and the same access token is used here (e.g.
    account exists but a new token hasn't been generated with the linkage
    info yet)
    """
    encoded_credentials_jwt = encoded_creds_jwt["jwt"]
    user_id = encoded_creds_jwt["user_id"]
    proxy_group_id = encoded_creds_jwt["proxy_group_id"]

    original_expiration = 1000
    google_account = "*****@*****.**"

    test_session_jwt = create_session_token(
        app.keypairs[0],
        config.get("SESSION_TIMEOUT"),
        context={"google_proxy_group_id": proxy_group_id},
    )

    existing_account = UserGoogleAccount(email=google_account, user_id=user_id)
    db_session.add(existing_account)
    db_session.commit()
    g_account_access = UserGoogleAccountToProxyGroup(
        user_google_account_id=existing_account.id,
        proxy_group_id=proxy_group_id,
        expires=original_expiration,
    )
    db_session.add(g_account_access)
    db_session.commit()

    # manually set cookie for initial session
    client.set_cookie("localhost", config["SESSION_COOKIE_NAME"],
                      test_session_jwt)

    r = client.patch(
        "/link/google",
        headers={"Authorization": "Bearer " + encoded_credentials_jwt})

    assert r.status_code == 200

    account_in_proxy_group = (
        db_session.query(UserGoogleAccountToProxyGroup).filter(
            UserGoogleAccountToProxyGroup.user_google_account_id ==
            existing_account.id).first())
    assert account_in_proxy_group.proxy_group_id == proxy_group_id

    # check that expiration changed and that it's less than the cfg
    # expires in (since this check will happen a few seconds after
    # it gets set)
    assert account_in_proxy_group.expires != original_expiration
    assert account_in_proxy_group.expires <= (
        int(time.time()) + config["GOOGLE_ACCOUNT_ACCESS_EXPIRES_IN"])

    assert not add_google_email_to_proxy_group_mock.called
예제 #19
0
def test_google_link_when_google_mocked(
    app,
    client,
    db_session,
    encoded_creds_jwt,
    google_auth_get_user_info_mock,
    add_google_email_to_proxy_group_mock,
    monkeypatch,
):
    """"""
    monkeypatch.setitem(config, "MOCK_GOOGLE_AUTH", True)

    user_id = encoded_creds_jwt["user_id"]
    proxy_group_id = encoded_creds_jwt["proxy_group_id"]

    redirect = "http://localhost"
    google_account = encoded_creds_jwt["username"]

    test_session_jwt = create_session_token(
        app.keypairs[0],
        config.get("SESSION_TIMEOUT"),
        context={
            "google_link": True,
            "user_id": user_id,
            "google_proxy_group_id": proxy_group_id,
            "redirect": redirect,
        },
    )

    # manually set cookie for initial session
    client.set_cookie("localhost", config["SESSION_COOKIE_NAME"],
                      test_session_jwt)

    headers = {"Authorization": "Bearer " + encoded_creds_jwt.jwt}

    r_link = client.get("/link/google/",
                        headers=headers,
                        query_string={"redirect": redirect})

    redirect_location = str(r_link.location).replace(config["BASE_URL"], "")
    # Pass through the Authorization header in the response...
    # In our actual commons, the reverse proxy handles dumping this into the request
    # again. this is ONLY used when MOCK_GOOGLE_AUTH is true (e.g. we're trying to
    # fake a Google login)
    auth_header = r_link.headers.get("Authorization")
    r = client.get(redirect_location, headers={"Authorization": auth_header})

    assert r.status_code == 302
    parsed_url = urlparse(r.headers["Location"])
    query_params = parse_qs(parsed_url.query)
    response_redirect = urlunparse(
        (parsed_url.scheme, parsed_url.netloc, parsed_url.path, "", "", ""))
    assert "exp" in query_params
    assert query_params["linked_email"][0] == google_account
    assert response_redirect == redirect

    user_google_account = (db_session.query(UserGoogleAccount).filter(
        UserGoogleAccount.email == google_account,
        UserGoogleAccount.user_id == user_id,
    ).first())
    assert user_google_account

    assert not flask.session.get("google_link")
    assert not flask.session.get("user_id")
    assert not flask.session.get("google_proxy_group_id")

    assert add_google_email_to_proxy_group_mock.called
예제 #20
0
def test_google_link_g_account_exists_linked_to_different_user(
    app,
    client,
    db_session,
    encoded_creds_jwt,
    add_new_g_acnt_mock,
    google_auth_get_user_info_mock,
    add_google_email_to_proxy_group_mock,
):
    """
    Test the link endpoint that gets hit after authN when the provided Google
    account is already linked to a different user. We should not attempt to
    create a new user google account and just redirect with
    an error.
    """
    user_id = encoded_creds_jwt["user_id"]
    proxy_group_id = encoded_creds_jwt["proxy_group_id"]

    test_auth_code = "abc123"
    redirect = "http://localhost"
    google_account = "*****@*****.**"

    test_session_jwt = create_session_token(
        app.keypairs[0],
        config.get("SESSION_TIMEOUT"),
        context={
            "google_link": True,
            "user_id": user_id + 5,  # <- NOT the user whose g acnt exists
            "google_proxy_group_id": proxy_group_id,
            "redirect": redirect,
        },
    )

    existing_account = UserGoogleAccount(email=google_account, user_id=user_id)
    db_session.add(existing_account)
    db_session.commit()

    # manually set cookie for initial session
    client.set_cookie("localhost", config["SESSION_COOKIE_NAME"],
                      test_session_jwt)

    # simulate successfully authed reponse with user email
    google_auth_get_user_info_mock.return_value = {"email": google_account}

    r = client.get("/link/google/callback",
                   query_string={"code": test_auth_code})

    assert not add_new_g_acnt_mock.called

    # make sure we're redirecting with error information
    parsed_url = urlparse(r.headers["Location"])
    query_params = parse_qs(parsed_url.query)
    response_redirect = urlunparse(
        (parsed_url.scheme, parsed_url.netloc, parsed_url.path, "", "", ""))
    response_redirect = urlunparse(
        (parsed_url.scheme, parsed_url.netloc, parsed_url.path, "", "", ""))
    assert "exp" not in query_params
    assert "linked_email" not in query_params
    assert "error" in query_params
    assert "error_description" in query_params
    assert response_redirect == redirect

    assert not flask.session.get("google_link")
    assert not flask.session.get("user_id")
    assert not flask.session.get("google_proxy_group_id")

    assert not add_google_email_to_proxy_group_mock.called