Example #1
0
def test_token_getter(remote, models_fixture, app):
    """Test token getter on response from OAuth server."""
    datastore = app.extensions['invenio-accounts'].datastore
    existing_email = '*****@*****.**'
    user = datastore.find_user(email=existing_email)

    # Missing RemoteToken
    oauth_authenticate('dev', user)
    assert not token_getter(remote)

    # Populated RemoteToken
    RemoteToken.create(user.id, 'testkey', 'mytoken', 'mysecret')
    oauth_authenticate('dev', user)
    assert token_getter(remote) == ('mytoken', 'mysecret')
def test_token_getter(remote, models_fixture):
    """Test token getter on response from OAuth server."""
    app = models_fixture
    datastore = app.extensions['invenio-accounts'].datastore
    existing_email = '*****@*****.**'
    user = datastore.find_user(email=existing_email)

    # Missing RemoteToken
    oauth_authenticate('dev', user)
    assert not token_getter(remote)

    # Populated RemoteToken
    RemoteToken.create(user.id, 'testkey', 'mytoken', 'mysecret')
    oauth_authenticate('dev', user)
    assert token_getter(remote) == ('mytoken', 'mysecret')
Example #3
0
def authorized_signup_handler(resp, remote, *args, **kwargs):
    """Handle sign-in/up functionality.

    This is needed as we don't use Flask Forms (for now), thus the default
    function would fail.
    """
    # Remove any previously stored auto register session key
    session.pop(token_session_key(remote.name) + '_autoregister', None)

    # Store token in session
    # ----------------------
    # Set token in session - token object only returned if
    # current_user.is_autenticated().
    token = response_token_setter(remote, resp)
    handlers = current_oauthclient.signup_handlers[remote.name]

    # Sign-in/up user
    # ---------------
    if not current_user.is_authenticated:
        account_info = handlers['info'](resp)
        account_info_received.send(remote,
                                   token=token,
                                   response=resp,
                                   account_info=account_info)
        user = oauth_get_user(
            remote.consumer_key,
            account_info=account_info,
            access_token=token_getter(remote)[0],
        )
        if user is None:
            # Auto sign-up if user not found
            user = oauth_register(account_info)

        # Authenticate user
        if not oauth_authenticate(
                remote.consumer_key,
                user,
                require_existing_link=False,
                remember=current_app.config['OAUTHCLIENT_REMOTE_APPS'][
                    remote.name].get('remember', False)):
            return current_app.login_manager.unauthorized()

        # Link account
        # ------------
        # Need to store token in database instead of only the session when
        # called first time.
        token = response_token_setter(remote, resp)

    # Setup account
    # -------------
    if not token.remote_account.extra_data:
        account_setup = handlers['setup'](token, resp)
        account_setup_received.send(remote,
                                    token=token,
                                    response=resp,
                                    account_setup=account_setup)

    return redirect('/')
Example #4
0
 def session_token(self):
     """Return OAuth session token."""
     session_token = None
     if self.user_id is not None:
         session_token = token_getter(self.remote)
     if session_token:
         token = RemoteToken.get(self.user_id,
                                 self.remote.consumer_key,
                                 access_token=session_token[0])
         return token
     return None
Example #5
0
 def session_token(self):
     """Return OAuth session token."""
     session_token = None
     if self.user_id is not None:
         session_token = token_getter(self.remote)
     if session_token:
         token = RemoteToken.get(
             self.user_id, self.remote.consumer_key,
             access_token=session_token[0]
         )
         return token
     return None
Example #6
0
def get_token(user_id=None):
    """Retrieve token for linked GitHub account."""
    session_token = None
    if user_id is None:
        session_token = token_getter(get_remote())
    if session_token:
        token = RemoteToken.get(
            current_user.get_id(), get_client_id(),
            access_token=session_token[0]
        )
        return token
    return None
Example #7
0
def authorized_signup_handler(resp, remote, *args, **kwargs):
    """Handle sign-in/up functionality.

    This is needed as we don't use Flask Forms (for now), thus the default
    function would fail.
    """
    # Remove any previously stored auto register session key
    session.pop(token_session_key(remote.name) + '_autoregister', None)

    # Store token in session
    # ----------------------
    # Set token in session - token object only returned if
    # current_user.is_autenticated().
    token = response_token_setter(remote, resp)
    handlers = current_oauthclient.signup_handlers[remote.name]

    # Sign-in/up user
    # ---------------
    if not current_user.is_authenticated:
        account_info = handlers['info'](resp)
        account_info_received.send(
            remote, token=token, response=resp, account_info=account_info
        )
        user = oauth_get_user(
            remote.consumer_key,
            account_info=account_info,
            access_token=token_getter(remote)[0],
        )
        if user is None:
            # Auto sign-up if user not found
            user = oauth_register(account_info)

        # Authenticate user
        if not oauth_authenticate(remote.consumer_key, user,
                                  require_existing_link=False):
            return current_app.login_manager.unauthorized()

        # Link account
        # ------------
        # Need to store token in database instead of only the session when
        # called first time.
        token = response_token_setter(remote, resp)

    # Setup account
    # -------------
    if not token.remote_account.extra_data:
        account_setup = handlers['setup'](token, resp)
        account_setup_received.send(
            remote, token=token, response=resp, account_setup=account_setup
        )

    return redirect('/')
Example #8
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()
def test_token_getter_setter(monkeypatch):
    """Test token getter setter."""
    # Mock session id
    monkeypatch.setattr('flask_login._create_identifier', lambda: '1234')
    monkeypatch.setattr(
        'invenio_oauthclient.views.client._create_identifier', lambda: '1234')

    app = setup_app()
    oauth = app.extensions['oauthlib.client']

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

    with patch('flask_login._get_user', return_value=user):
        with app.test_client() as c:
            # First call login to be redirected
            res = c.get(url_for("invenio_oauthclient.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.extensions['oauthlib.client'], 'full')

            # Imitate that the user authorized our request in the remote
            # application.
            c.get(url_for(
                "invenio_oauthclient.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.extensions['oauthlib.client'], 'full', data={
                "access_token": "new_access_token",
                "scope": "",
                "token_type": "bearer"
            })

            c.get(url_for(
                "invenio_oauthclient.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.extensions['oauthlib.client'].remote_apps['full'])
            assert val == ('new_access_token', '')

            # Disconnect account
            res = c.get(url_for(
                "invenio_oauthclient.disconnect", remote_app='full',
            ))
            assert res.status_code == 302
            assert res.location.endswith(
                url_for('invenio_oauthclient_settings.index')
            )
            # Assert that remote account have been removed.
            t = RemoteToken.get(1, "fullid")
            assert t is None
Example #10
0
def test_token_getter_setter(views_fixture, monkeypatch):
    """Test token getter setter."""
    # Mock session id
    monkeypatch.setattr('flask_login._create_identifier', lambda: '1234')
    monkeypatch.setattr('invenio_oauthclient.views.client._create_identifier',
                        lambda: '1234')

    app = views_fixture
    oauth = app.extensions['oauthlib.client']

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

    with patch('flask_login._get_user', return_value=user):
        with app.test_client() as c:
            # First call login to be redirected
            res = c.get(url_for("invenio_oauthclient.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.extensions['oauthlib.client'], 'full')

            # Imitate that the user authorized our request in the remote
            # application.
            c.get(
                url_for(
                    "invenio_oauthclient.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.extensions['oauthlib.client'],
                          'full',
                          data={
                              "access_token": "new_access_token",
                              "scope": "",
                              "token_type": "bearer"
                          })

            c.get(
                url_for("invenio_oauthclient.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.extensions['oauthlib.client'].remote_apps['full'])
            assert val == ('new_access_token', '')

            # Disconnect account
            res = c.get(
                url_for(
                    "invenio_oauthclient.disconnect",
                    remote_app='full',
                ))
            assert res.status_code == 302
            assert res.location.endswith(
                url_for('invenio_oauthclient_settings.index'))
            # 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()
    def test_token_getter_setter(self, session, save_session):
        from invenio_oauthclient.models import RemoteToken
        from invenio_oauthclient.handlers import token_getter
        from invenio_oauthclient.client import oauth

        # Mock user
        user = MagicMock()
        user.get_id = MagicMock(return_value=1)
        user.is_authenticated = MagicMock(return_value=True)

        # Mock session id
        session.sid = '1234'

        with patch('flask_login._get_user', return_value=user):
            with self.app.test_client() as c:
                # First call login to be redirected
                res = c.get(url_for("oauthclient.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
                self.mock_response(app='full')

                # Imitate that the user authorized our request in the remote
                # application.
                c.get(url_for(
                    "oauthclient.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
                self.mock_response(app='full', data={
                    "access_token": "new_access_token",
                    "scope": "",
                    "token_type": "bearer"
                })

                c.get(url_for(
                    "oauthclient.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(oauth.remote_apps['full'])
                assert val == ('new_access_token', '')

                # Disconnect account
                res = c.get(url_for(
                    "oauthclient.disconnect", remote_app='full',
                ))
                assert res.status_code == 302
                assert res.location.endswith(
                    url_for('oauthclient_settings.index')
                )
                # Assert that remote account have been removed.
                t = RemoteToken.get(1, "fullid")
                assert t is None
Example #12
0
    def authorized_handler(self, resp, remote, *args, **kwargs):
        """Handle sign-in functionality.

        :param remote: The remote application.
        :param resp: The response.
        :returns: Redirect response.
        """
        # Remove any previously stored auto register session key
        session.pop(token_session_key(remote.name) + '_autoregister', None)

        # Store token in session
        # ----------------------
        # Set token in session - token object only returned if
        # current_user.is_autenticated().
        token = response_token_setter(remote, resp)
        handlers = current_oauthclient.signup_handlers[remote.name]

        # Sign-in user
        # ---------------
        if not current_user.is_authenticated:
            account_info = handlers['info'](resp)
            account_info_received.send(remote,
                                       token=token,
                                       response=resp,
                                       account_info=account_info)

            user = oauth_get_user(
                remote.consumer_key,
                account_info=account_info,
                access_token=token_getter(remote)[0],
            )

            # Make sure that external identity either matches
            # or is not yet created (gets created on first oidc login)
            extid = _get_external_id(account_info)
            user_identity: UserIdentity = UserIdentity.query.filter_by(
                id=extid['id'], method=extid['method']).first()
            if user_identity and user_identity.id != extid['id']:
                abort(401)

            if user is None:
                abort(403)

            # Authenticate user
            if not oauth_authenticate(
                    remote.consumer_key, user, require_existing_link=False):
                return current_app.login_manager.unauthorized()

            # Link account
            # ------------
            # Need to store token in database instead of only the session when
            # called first time.
            token = response_token_setter(remote, resp)

        # Setup account
        # -------------
        if not token.remote_account.extra_data:
            account_setup = handlers['setup'](token, resp)
            account_setup_received.send(remote,
                                        token=token,
                                        response=resp,
                                        account_setup=account_setup)
            db.session.commit()
            account_setup_committed.send(remote, token=token)
        else:
            db.session.commit()

        # Redirect to next
        next_url = get_session_next_url(remote.name)
        if next_url:
            return redirect(next_url)
        return redirect(url_for('invenio_oauthclient_settings.index'))
def cern_authorized_signup_handler(resp, remote, *args, **kwargs):
    """Handle sign-in/up functionality.
    :param remote: The remote application.
    :param resp: The response.
    :returns: Redirect response.
    """
    # Remove any previously stored auto register session key
    session.pop(token_session_key(remote.name) + '_autoregister', None)

    # Store token in session
    # ----------------------
    # Set token in session - token object only returned if
    # current_user.is_autenticated().
    token = response_token_setter(remote, resp)
    handlers = current_oauthclient.signup_handlers[remote.name]

    # Sign-in/up user
    # ---------------
    if not current_user.is_authenticated:
        account_info = handlers['info'](resp)
        account_info_received.send(remote,
                                   token=token,
                                   response=resp,
                                   account_info=account_info)

        user = oauth_get_user(
            remote.consumer_key,
            account_info=account_info,
            access_token=token_getter(remote)[0],
        )
        if user is None:
            # Auto sign-up if user not found
            form = create_csrf_disabled_registrationform()
            form = fill_form(form, account_info['user'])
            user = oauth_register(form)

            # if registration fails ...
            if user is None:
                # requires extra information
                session[token_session_key(remote.name) +
                        '_autoregister'] = True
                session[token_session_key(remote.name) +
                        '_account_info'] = account_info
                session[token_session_key(remote.name) + '_response'] = resp
                db.session.commit()
                return redirect(url_for(
                    '.signup',
                    remote_app=remote.name,
                ))
        # Authenticate user
        if not oauth_authenticate(
                remote.consumer_key, user, require_existing_link=False):
            return current_app.login_manager.unauthorized()

        # Link account
        # ------------
        # Need to store token in database instead of only the session when
        # called first time.
        token = response_token_setter(remote, resp)

    # Setup account
    # -------------
    if not token.remote_account.extra_data:
        account_setup = handlers['setup'](token, resp)
        account_setup_received.send(remote,
                                    token=token,
                                    response=resp,
                                    account_setup=account_setup)
        db.session.commit()
        account_setup_committed.send(remote, token=token)
    else:
        db.session.commit()

    # Redirect to next
    if current_user.is_authenticated and not egroup_admin():
        logout_user()
        return redirect(get_post_logout_redirect())

    next_url = get_session_next_url(remote.name)
    if next_url:
        return redirect(next_url)
    return redirect(url_for('invenio_oauthclient_settings.index'))
Example #14
0
    def test_token_getter_setter(self, session, save_session):
        from invenio_oauthclient.models import RemoteToken
        from invenio_oauthclient.handlers import token_getter
        from invenio_oauthclient.client import oauth

        # Mock user
        user = MagicMock()
        user.get_id = MagicMock(return_value=1)
        user.is_authenticated = MagicMock(return_value=True)

        # Mock session id
        session.sid = '1234'

        with patch('flask_login._get_user', return_value=user):
            with self.app.test_client() as c:
                # First call login to be redirected
                res = c.get(url_for("oauthclient.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
                self.mock_response(app='full')

                # Imitate that the user authorized our request in the remote
                # application.
                c.get(
                    url_for(
                        "oauthclient.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
                self.mock_response(app='full',
                                   data={
                                       "access_token": "new_access_token",
                                       "scope": "",
                                       "token_type": "bearer"
                                   })

                c.get(
                    url_for("oauthclient.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(oauth.remote_apps['full'])
                assert val == ('new_access_token', '')

                # Disconnect account
                res = c.get(
                    url_for(
                        "oauthclient.disconnect",
                        remote_app='full',
                    ))
                assert res.status_code == 302
                assert res.location.endswith(
                    url_for('oauthclient_settings.index'))
                # Assert that remote account have been removed.
                t = RemoteToken.get(1, "fullid")
                assert t is None