Beispiel #1
0
def save_token(token_data, request):
    requested_scopes = set(scope_to_list(token_data.get('scope', '')))
    application = OAuthApplication.query.filter_by(
        client_id=request.client.client_id).one()
    link = OAuthApplicationUserLink.query.with_parent(application).with_parent(
        request.user).first()

    if link is None:
        link = OAuthApplicationUserLink(application=application,
                                        user=request.user,
                                        scopes=requested_scopes)
    else:
        if not requested_scopes:
            # for already-authorized apps not specifying a scope uses all scopes the
            # user previously granted to the app
            requested_scopes = set(link.scopes)
            token_data['scope'] = list_to_scope(requested_scopes)
        new_scopes = requested_scopes - set(link.scopes)
        if new_scopes:
            logger.info('New scopes for %r: %s', link, new_scopes)
            link.update_scopes(new_scopes)

    link.tokens.append(
        OAuthToken(access_token=token_data['access_token'],
                   scopes=requested_scopes))

    # get rid of old tokens if there are too many
    q = (db.session.query(OAuthToken.id).with_parent(link).filter_by(
        _scopes=db.cast(sorted(requested_scopes), ARRAY(db.String))).order_by(
            OAuthToken.created_dt.desc()).offset(
                MAX_TOKENS_PER_SCOPE).scalar_subquery())
    OAuthToken.query.filter(
        OAuthToken.id.in_(q)).delete(synchronize_session='fetch')
Beispiel #2
0
def dummy_app_link(db, dummy_application, dummy_user):
    """Return an app link for the dummy user."""
    link = OAuthApplicationUserLink(application=dummy_application,
                                    user=dummy_user,
                                    scopes=['read:legacy_api', 'read:user'])
    db.session.add(link)
    db.session.flush()
    return link
Beispiel #3
0
def test_merge_users(create_user, dummy_user, dummy_application, dummy_token, create_application, test_client):
    source_user = create_user(123)

    # app on both users (already exists on dummy user via dummy token)
    app_link = OAuthApplicationUserLink(application=dummy_application, user=source_user,
                                        scopes=['read:user', 'write:legacy_api'])
    token_string = generate_token()
    OAuthToken(access_token=token_string, app_user_link=app_link, scopes=['read:user'])

    # app only on source user
    test_app = create_application(name='test')
    app_link2 = OAuthApplicationUserLink(application=test_app, user=source_user, scopes=['read:user'])
    token_string2 = generate_token()
    OAuthToken(access_token=token_string2, app_user_link=app_link2, scopes=['read:user'])
    OAuthToken(access_token=generate_token(), app_user_link=app_link2, scopes=['read:user'])
    OAuthToken(access_token=generate_token(), app_user_link=app_link2, scopes=['read:user'])

    resp = test_client.get('/api/user/', headers={'Authorization': f'Bearer {dummy_token._plaintext_token}'})
    assert resp.status_code == 200
    assert resp.json['id'] == dummy_user.id

    for token in (token_string, token_string2):
        resp = test_client.get('/api/user/', headers={'Authorization': f'Bearer {token}'})
        assert resp.status_code == 200
        assert resp.json['id'] == source_user.id

    old_token_count = OAuthToken.query.count()
    merge_users(source_user, dummy_user)

    # source user should not have any leftover app links
    assert not source_user.oauth_app_links.count()
    # two app links on the target user
    assert dummy_user.oauth_app_links.count() == 2
    # dummy app has one token from each user
    assert dummy_user.oauth_app_links.filter_by(application=dummy_application).one().tokens.count() == 2
    # test app has 3 tokens coming from source user
    assert dummy_user.oauth_app_links.filter_by(application=test_app).one().tokens.count() == 3
    # the total number of tokens didn't change (we do not delete surplus tokens during merge anyway)
    assert OAuthToken.query.count() == old_token_count

    # all tokens point to the target user
    for token in (dummy_token._plaintext_token, token_string, token_string2):
        resp = test_client.get('/api/user/', headers={'Authorization': f'Bearer {token}'})
        assert resp.status_code == 200
        assert resp.json['id'] == dummy_user.id
def test_get_request_user_oauth_querystring(db, dummy_user, app, test_client):
    # TODO: remove this once indico-checkin no longer sends tokens in the query string!
    from indico.core.oauth.models.applications import OAuthApplication, OAuthApplicationUserLink, SystemAppType
    from indico.core.oauth.models.tokens import OAuthToken

    @oauth_scope('registrants')
    class RHTest(RH):
        def _process(self):
            user, source = get_request_user()
            assert session.user == user
            if not user:
                return 'none'
            return f'{user.id}|{source}'

    app.add_url_rule('/test/registrants',
                     'test_registrants',
                     make_view_func(RHTest),
                     methods=('GET', 'POST'))

    checkin_app = OAuthApplication.query.filter_by(
        system_app_type=SystemAppType.checkin).one()
    app_link = OAuthApplicationUserLink(application=checkin_app,
                                        user=dummy_user,
                                        scopes=['registrants'])
    token_string = 'x' * 40
    OAuthToken(access_token=token_string,
               app_user_link=app_link,
               scopes=['registrants'])
    db.session.flush()

    resp = test_client.get('/test/registrants',
                           headers={'Authorization': f'Bearer {token_string}'})
    assert resp.status_code == 200
    assert resp.data == b'1337|oauth'

    resp = test_client.post(
        '/test/registrants',
        headers={'Authorization': f'Bearer {token_string}'})
    assert resp.status_code == 200
    assert resp.data == b'1337|oauth'

    resp = test_client.get(f'/test/registrants?access_token={token_string}')
    assert resp.status_code == 200
    assert resp.data == b'1337|oauth'

    resp = test_client.post(f'/test/registrants?access_token={token_string}')
    assert resp.status_code == 200
    assert resp.data == b'1337|oauth'
def test_checkin_app_querystring_tokens(db, test_client, dummy_user):
    checkin_app = OAuthApplication.query.filter_by(
        system_app_type=SystemAppType.checkin).one()
    checkin_app.allowed_scopes = ['read:user']
    app_link = OAuthApplicationUserLink(application=checkin_app,
                                        user=dummy_user,
                                        scopes=['read:user'])
    token_string = generate_token()
    OAuthToken(access_token=token_string,
               app_user_link=app_link,
               scopes=['read:user'])
    db.session.flush()
    resp = test_client.get('/api/user/',
                           headers={'Authorization': f'Bearer {token_string}'})
    assert resp.status_code == 200
    resp = test_client.get(f'/api/user/?access_token={token_string}')
    assert resp.status_code == 200