Beispiel #1
0
def test_unauthorized_signup(remote, app_rest, models_fixture):
    """Test unauthorized redirect on signup callback handler."""
    datastore = app_rest.extensions['invenio-accounts'].datastore
    existing_email = '*****@*****.**'
    user = datastore.find_user(email=existing_email)

    example_response = {'access_token': 'test_access_token'}
    example_account_info = {
        'user': {
            'email': existing_email,
            'external_id': '1234',
            'external_method': 'test_method'
        }
    }

    # Mock remote app's handler
    current_oauthclient.signup_handlers[remote.name] = {
        'info': lambda resp: example_account_info,
    }

    _security.confirmable = True
    _security.login_without_confirmation = False
    user.confirmed_at = None

    expected_url_args = {"message": "Unauthorized.", "code": 401}
    resp = authorized_signup_handler(example_response, remote)
    check_response_redirect_url_args(resp, expected_url_args)
Beispiel #2
0
    def _init():
        ioc = app_rest.extensions['oauthlib.client']

        # setup the user account via cern_openid
        with app_rest.test_client() as c:
            # Ensure remote apps have been loaded (due to before first request)
            resp = c.get(
                url_for('invenio_oauthclient.rest_login',
                        remote_app='cern_openid'))
            assert resp.status_code == 302

            example_response, example_token, example_account_info = \
                example_cern_openid_rest

            mock_response(app_rest.extensions['oauthlib.client'],
                          'cern_openid', example_token)
            mock_remote_get(ioc, 'cern_openid', example_response)

            resp = c.get(
                url_for('invenio_oauthclient.rest_authorized',
                        remote_app='cern_openid',
                        code='test',
                        state=get_state('cern_openid')))
            assert resp.status_code == 302
            expected_url_args = {
                "message": "Successfully authorized.",
                "code": 200,
            }
            check_response_redirect_url_args(resp, expected_url_args)

            assert len(g.identity.provides) == 3
Beispiel #3
0
def test_signup_handler(remote, app_rest, models_fixture):
    """Test signup handler."""
    datastore = app_rest.extensions['invenio-accounts'].datastore
    existing_email = '*****@*****.**'
    user = datastore.find_user(email=existing_email)
    # Already authenticated
    login_user(user)
    assert current_user.is_authenticated
    resp1 = signup_handler(remote)
    expected_url_args = {"message": "Successfully signed up.", "code": 200}
    check_response_redirect_url_args(resp1, expected_url_args)
    logout_user()
    assert not current_user.is_authenticated

    # No OAuth token
    resp2 = signup_handler(remote)
    expected_url_args = {"message": "Token not found.", "code": 400}

    check_response_redirect_url_args(resp2, expected_url_args)

    # Not coming from authorized request
    token = RemoteToken.create(user.id, 'testkey', 'mytoken', 'mysecret')
    token_setter(remote, token, 'mysecret')
    with pytest.raises(BuildError):
        signup_handler(remote)
Beispiel #4
0
def test_authorized_rest_handler(app_rest):
    """Test authorized callback handler."""
    oauth = current_oauthclient.oauth
    remote = oauth.remote_apps['github']
    # General error
    example_response = {'error': 'error'}
    resp = authorized_rest(example_response, remote)
    expected_url_args = {
        "message": "Authorization with remote service failed.",
        "code": 400,
    }
    check_response_redirect_url_args(resp, expected_url_args)
    # Bad verification error
    example_response = {'error': 'bad_verification_code'}
    resp = authorized_rest(example_response, remote)
    check_redirect_location(resp, '/oauth/login/github/')

    # Incorrect client credentials
    example_response = {'error': 'incorrect_client_credentials'}
    with pytest.raises(OAuthResponseError):
        authorized_rest(example_response, remote)

        # Redirect uri mismatch
        example_response = {'error': 'redirect_uri_mismatch'}
        with pytest.raises(OAuthResponseError):
            authorized_rest(example_response, remote)
Beispiel #5
0
def test_authorized_signup_handler(remote, app_rest, models_fixture):
    """Test authorized signup handler."""
    datastore = app_rest.extensions['invenio-accounts'].datastore
    user = datastore.find_user(email='*****@*****.**')

    example_response = {'access_token': 'test_access_token'}

    # Mock remote app's handler
    current_oauthclient.signup_handlers[remote.name] = {
        'setup': lambda token, resp: None
    }

    # Authenticate user
    oauth_authenticate('dev', user)

    # Mock next url
    next_url = '/test/redirect'
    session[token_session_key(remote.name) + '_next_url'] = next_url

    # Check user is redirected to next_url
    expected_url_args = {
        "message": "Successfully authorized.",
        "code": 200,
        "next_url": next_url
    }
    resp = authorized_signup_handler(example_response, remote)
    check_response_redirect_url_args(resp, expected_url_args)
def test_account_info_not_allowed_account(app_rest, example_cern_openid_rest):
    """Test account info extraction."""
    client = app_rest.test_client()

    app_rest.config['OAUTHCLIENT_CERN_OPENID_ALLOWED_ROLES'] = [
        'another cern role'
    ]
    ioc = app_rest.extensions['oauthlib.client']

    # Ensure remote apps have been loaded (due to before first request)
    client.get(
        url_for('invenio_oauthclient.rest_login', remote_app='cern_openid'))

    example_response, _, example_account_info = example_cern_openid_rest

    mock_remote_get(ioc, 'cern_openid', example_response)
    resp = account_info_rest(ioc.remote_apps['cern_openid'], None)
    assert g.oauth_logged_in_with_remote == ioc.remote_apps['cern_openid']

    assert resp.status_code == 302
    expected_url_args = {
        "message": "CERN account not allowed.",
        "code": 400,
    }
    check_response_redirect_url_args(resp, expected_url_args)
def test_account_setup(app_rest, example_cern_openid_rest, models_fixture):
    """Test account setup after login."""
    with app_rest.test_client() as c:
        ioc = app_rest.extensions['oauthlib.client']

        # Ensure remote apps have been loaded (due to before first request)
        resp = c.get(
            url_for('invenio_oauthclient.rest_login',
                    remote_app='cern_openid'))
        assert resp.status_code == 302

        example_response, example_token, example_account_info = \
            example_cern_openid_rest

        mock_response(app_rest.extensions['oauthlib.client'], 'cern_openid',
                      example_token)
        mock_remote_get(ioc, 'cern_openid', example_response)

        resp = c.get(
            url_for('invenio_oauthclient.rest_authorized',
                    remote_app='cern_openid',
                    code='test',
                    state=get_state('cern_openid')))
        assert resp.status_code == 302
        expected_url_args = {
            "message": "Successfully authorized.",
            "code": 200,
        }
        check_response_redirect_url_args(resp, expected_url_args)

        assert len(g.identity.provides) == 3

    datastore = app_rest.extensions['invenio-accounts'].datastore
    user = datastore.find_user(email='*****@*****.**')
    user.password = hash_password("1234")
    assert user

    with app_rest.test_request_context():
        resp = disconnect_rest_handler(ioc.remote_apps['cern_openid'])
        assert resp.status_code >= 300

        # simulate login (account_info fetch)
        g.oauth_logged_in_with_remote = ioc.remote_apps['cern_openid']

        login_user(user)
        assert len(g.identity.provides) == 3

        logout_user()
        assert len(g.identity.provides) == 1
        assert "cern_resource" not in session
        assert OAUTHCLIENT_CERN_OPENID_SESSION_KEY not in session

        # Login again to test the disconnect handler
        g.oauth_logged_in_with_remote = ioc.remote_apps['cern_openid']
        login_user(user)
        assert len(g.identity.provides) == 3

        disconnect_rest_handler(ioc.remote_apps['cern_openid'])
Beispiel #8
0
def test_unauthorized_disconnect(remote, app_rest):
    """Test disconnect handler when user is not authenticated."""
    def mock_unauthorized():
        return "Unauthorized"

    app_rest.login_manager.unauthorized = mock_unauthorized
    resp = disconnect_handler(remote)
    expected_url_args = {"message": "Unauthorized.", "code": 401}
    check_response_redirect_url_args(resp, expected_url_args)
Beispiel #9
0
def test_already_linked_exception(remote, app_rest):
    """Test error when service is already linked to another account."""
    @oauth_resp_remote_error_handler
    def mock_handler(resp, remote):
        raise AlreadyLinkedError(None, None)

    resp = mock_handler(None, remote)
    expected_url_args = {
        "message": "External service is already linked to another account.",
        "code": 400
    }
    check_response_redirect_url_args(resp, expected_url_args)
def test_authorized_reject(app_rest):
    """Test a rejected request."""
    with app_rest.test_client() as c:
        c.get(url_for('invenio_oauthclient.rest_login', remote_app='cern'))
        resp = c.get(
            url_for('invenio_oauthclient.rest_authorized',
                    remote_app='cern', error='access_denied',
                    error_description='User denied access',
                    state=get_state('cern')))
        assert resp.status_code in (301, 302)
        expected_url_args = {
            "message": "You rejected the authentication request.",
            "code": 400,
        }
        check_response_redirect_url_args(resp, expected_url_args)
def test_account_setup(app_rest, example_cern_openid_rest, models_fixture):
    """Test account setup after login."""
    with app_rest.test_client() as c:
        ioc = app_rest.extensions['oauthlib.client']

        # Ensure remote apps have been loaded (due to before first request)
        resp = c.get(
            url_for('invenio_oauthclient.rest_login',
                    remote_app='cern_openid'))
        assert resp.status_code == 302

        example_response, example_token, example_account_info = \
            example_cern_openid_rest

        mock_response(app_rest.extensions['oauthlib.client'], 'cern_openid',
                      example_token)
        mock_remote_get(ioc, 'cern_openid', example_response)

        resp = c.get(
            url_for('invenio_oauthclient.rest_authorized',
                    remote_app='cern_openid',
                    code='test',
                    state=get_state('cern_openid')))
        assert resp.status_code == 302
        expected_url_args = {
            "message": "Successfully authorized.",
            "code": 200,
        }
        check_response_redirect_url_args(resp, expected_url_args)

        assert len(g.identity.provides) == 3

    datastore = app_rest.extensions['invenio-accounts'].datastore
    user = datastore.find_user(email='*****@*****.**')
    assert user

    with app_rest.test_request_context():
        resp = disconnect_rest_handler(ioc.remote_apps['cern_openid'])
        assert resp.status_code >= 300

        login_user(user)
        assert len(g.identity.provides) == 3
        disconnect_rest_handler(ioc.remote_apps['cern_openid'])
Beispiel #12
0
def test_token_getter_setter(app_rest, monkeypatch):
    """Test token getter setter."""
    # Mock session id
    monkeypatch.setattr('invenio_oauthclient._compat._create_identifier',
                        lambda: '1234')
    monkeypatch.setattr(
        'invenio_oauthclient.views.client._create_identifier', lambda: '1234')

    oauth = app_rest.extensions['oauthlib.client']

    # Mock user
    user = MagicMock()
    user.id = 1
    user.get_id = MagicMock(return_value=1)
    user.is_anonymous = False

    with app_rest.test_client() as c:
        login_user_via_session(c, user)
        # First call login to be redirected
        res = c.get(url_for('invenio_oauthclient.rest_login',
                            remote_app='full'))
        assert res.status_code == 302
        assert res.location.startswith(
            oauth.remote_apps['full'].authorize_url
        )
        state = parse_qs(urlparse(res.location).query)['state'][0]

        # Mock resposen class
        mock_response(app_rest.extensions['oauthlib.client'], 'full')

        # Imitate that the user authorized our request in the remote
        # application.
        c.get(url_for(
            'invenio_oauthclient.rest_authorized', remote_app='full',
            code='test', state=state,
        ))

        # Assert if everything is as it should be.
        from flask import session as flask_session
        assert flask_session['oauth_token_full'] == \
            ('test_access_token', '')

        t = RemoteToken.get(1, 'fullid')
        assert t.remote_account.client_id == 'fullid'
        assert t.access_token == 'test_access_token'
        assert RemoteToken.query.count() == 1

        # Mock a new authorized request
        mock_response(app_rest.extensions['oauthlib.client'], 'full', data={
            'access_token': 'new_access_token',
            'scope': "",
            'token_type': 'bearer'
        })

        c.get(url_for(
            'invenio_oauthclient.rest_authorized', remote_app='full',
            code='test', state=state
        ))

        t = RemoteToken.get(1, 'fullid')
        assert t.access_token == 'new_access_token'
        assert RemoteToken.query.count() == 1

        val = token_getter(
            app_rest.extensions['oauthlib.client'].remote_apps['full'])
        assert val == ('new_access_token', '')

        # Disconnect account
        res = c.get(url_for(
            'invenio_oauthclient.rest_disconnect', remote_app='full',
        ))
        assert res.status_code == 302
        expected_url_args = {
            "message": "Successfully disconnected.",
            "code": 200
        }
        check_response_redirect_url_args(res, expected_url_args)

        # Assert that remote account have been removed.
        t = RemoteToken.get(1, 'fullid')
        assert t is None
        # TODO: Figure out what is leaving session open & blocked
        db.session.close()
Beispiel #13
0
def test_account_setup(app_rest, example_cern, models_fixture):
    """Test account setup after login."""
    with app_rest.test_client() as c:
        ioc = app_rest.extensions['oauthlib.client']

        # Ensure remote apps have been loaded (due to before first request)
        resp = c.get(
            url_for('invenio_oauthclient.rest_login', remote_app='cern'))
        assert resp.status_code == 302

        example_response, example_token, example_account_info = example_cern

        mock_response(app_rest.extensions['oauthlib.client'], 'cern',
                      example_token)
        mock_remote_get(ioc, 'cern', example_response)

        resp = c.get(
            url_for('invenio_oauthclient.rest_authorized',
                    remote_app='cern',
                    code='test',
                    state=get_state('cern')))
        assert resp.status_code == 302
        expected_url_args = {
            "message": "Successfully authorized.",
            "code": 200,
        }
        check_response_redirect_url_args(resp, expected_url_args)
        assert len(g.identity.provides) == 7

    datastore = app_rest.extensions['invenio-accounts'].datastore
    user = datastore.find_user(email='*****@*****.**')
    user.password = hash_password("1234")
    assert user

    with app_rest.test_request_context():
        resp = disconnect_rest_handler(ioc.remote_apps['cern'])
        assert resp.status_code >= 300

        # simulate login (account_info fetch)
        g.oauth_logged_in_with_remote = ioc.remote_apps['cern']

        login_user(user)
        assert isinstance(g.identity, Identity)
        assert g.identity.provides == set([
            UserNeed(4),
            UserNeed('*****@*****.**'),
            RoleNeed('*****@*****.**'),
            RoleNeed('*****@*****.**'),
            RoleNeed('*****@*****.**'),
            RoleNeed('*****@*****.**'),
            RoleNeed('*****@*****.**'),
        ])

        logout_user()
        assert isinstance(g.identity, AnonymousIdentity)
        # NOTE: Wrong role, g.identity.provides = {Need(['id', 4])} read more
        # https://github.com/inveniosoftware/invenio-access/blob/e28e76d5361a29202b94d498f1968454c24c5c80/tests/test_loaders.py#L47
        assert len(g.identity.provides) == 1

        assert "cern_resource" not in session
        assert OAUTHCLIENT_CERN_SESSION_KEY not in session

        # Login again to test the disconnect handler
        g.oauth_logged_in_with_remote = ioc.remote_apps['cern']
        login_user(user)
        assert isinstance(g.identity, Identity)
        assert len(g.identity.provides) == 7

        disconnect_rest_handler(ioc.remote_apps['cern'])
Beispiel #14
0
def test_authorized_signup_valid_user(app_rest, example_github):
    """Test authorized callback with sign-up."""
    example_email = '*****@*****.**'

    with app_rest.test_client() as c:
        # User login with email 'info'
        with mock.patch('github3.login') as MockLogin:
            MockLogin.return_value = MockGh(email='*****@*****.**')

            # Ensure remote apps have been loaded (due to before first
            # request)
            resp = c.get(
                url_for('invenio_oauthclient.rest_login', remote_app='github'))

            assert resp.status_code == 302

            mock_response(app_rest.extensions['oauthlib.client'], 'github',
                          example_github)

            # User authorized the requests and is redirect back
            resp = c.get(
                url_for('invenio_oauthclient.rest_authorized',
                        remote_app='github',
                        code='test',
                        state=_get_state()))
            assert resp.status_code == 302
            expected_url_args = {
                "message": "Successfully authorized.",
                "code": 200,
            }
            check_response_redirect_url_args(resp, expected_url_args)

            # Assert database state (Sign-up complete)
            user = User.query.filter_by(email=example_email).one()
            remote = RemoteAccount.query.filter_by(user_id=user.id).one()
            RemoteToken.query.filter_by(id_remote_account=remote.id).one()
            assert user.active

            # Disconnect link
            resp = c.get(
                url_for('invenio_oauthclient.rest_disconnect',
                        remote_app='github'))
            assert resp.status_code == 302

            # User exists
            user = User.query.filter_by(email=example_email).one()
            assert 0 == UserIdentity.query.filter_by(method='orcid',
                                                     id_user=user.id,
                                                     id='githubuser').count()
            assert RemoteAccount.query.filter_by(user_id=user.id).count() == 0
            assert RemoteToken.query.count() == 0

        # User login with another email ('info2')
        with mock.patch('github3.login') as MockLogin:
            MockLogin.return_value = MockGh(email='*****@*****.**')

            # User authorized the requests and is redirect back
            resp = c.get(
                url_for('invenio_oauthclient.rest_authorized',
                        remote_app='github',
                        code='test',
                        state=_get_state()))
            assert resp.status_code == 302
            check_response_redirect_url_args(resp, expected_url_args)

            # check that exist only one account
            user = User.query.filter_by(email=example_email).one()
            assert user.email == example_email