def test_complete_secret_auth():
    consumer = Consumer(SessionDB(), CONFIG, CLIENT_CONFIG, SERVER_INFO)
    mfos = MyFakeOICServer("http://localhost:8088")
    mfos.keyjar = SRVKEYS
    consumer.http_request = mfos.http_request
    consumer.redirect_uris = ["http://example.com/authz"]
    consumer.state = "state0"
    consumer.nonce = rndstr()
    consumer.client_secret = "hemlig"
    consumer.secret_type = "basic"
    del consumer.config["password"]

    args = {
        "client_id": consumer.client_id,
        "response_type": "code",
        "scope": ["openid"],
    }

    result = consumer.do_authorization_request(state=consumer.state,
                                               request_args=args)
    assert result.status_code == 302
    assert result.headers["location"].startswith(consumer.redirect_uris[0])
    _, query = result.headers["location"].split("?")

    consumer.parse_response(AuthorizationResponse, info=query,
                            sformat="urlencoded")

    resp = consumer.complete()
    print resp
    assert resp.type() == "AccessTokenResponse"
    print resp.keys()
    assert _eq(resp.keys(), ['token_type', 'state', 'access_token',
                             'scope', 'expires_in', 'refresh_token'])

    assert resp["state"] == consumer.state
def test_faulty_idtoken_from_accesstoken_endpoint():
    consumer = Consumer(SessionDB(SERVER_INFO["issuer"]), CONFIG,
                        CLIENT_CONFIG, SERVER_INFO)
    consumer.keyjar = CLIKEYS
    mfos = MITMServer("http://localhost:8088")
    mfos.keyjar = SRVKEYS
    consumer.http_request = mfos.http_request
    consumer.redirect_uris = ["http://example.com/authz"]
    _state = "state0"
    consumer.nonce = rndstr()
    consumer.client_secret = "hemlig"
    consumer.secret_type = "basic"
    consumer.config["response_type"] = ["id_token"]

    args = {
        "client_id": consumer.client_id,
        "response_type": consumer.config["response_type"],
        "scope": ["openid"],
    }

    result = consumer.do_authorization_request(state=_state,
                                               request_args=args)
    consumer._backup("state0")

    assert result.status_code == 302
    # assert result.location.startswith(consumer.redirect_uri[0])
    _, query = result.headers["location"].split("?")
    print query
    try:
        consumer.parse_authz(query=query)
    except BadSignature:
        pass
    else:
        assert False
Exemple #3
0
def test_complete_secret_auth():
    consumer = Consumer(SessionDB(), CONFIG, CLIENT_CONFIG, SERVER_INFO)
    mfos = MyFakeOICServer("http://localhost:8088")
    mfos.keyjar = SRVKEYS
    consumer.http_request = mfos.http_request
    consumer.redirect_uris = ["http://example.com/authz"]
    consumer.state = "state0"
    consumer.nonce = rndstr()
    consumer.client_secret = "hemlig"
    consumer.secret_type = "basic"
    del consumer.config["password"]

    args = {
        "client_id": consumer.client_id,
        "response_type": "code",
        "scope": ["openid"],
    }

    result = consumer.do_authorization_request(state=consumer.state,
                                               request_args=args)
    assert result.status_code == 302
    assert result.headers["location"].startswith(consumer.redirect_uris[0])
    _, query = result.headers["location"].split("?")

    consumer.parse_response(AuthorizationResponse, info=query,
                            sformat="urlencoded")

    resp = consumer.complete()
    print resp
    assert resp.type() == "AccessTokenResponse"
    print resp.keys()
    assert _eq(resp.keys(), ['token_type', 'state', 'access_token',
                             'scope', 'expires_in', 'refresh_token'])

    assert resp["state"] == consumer.state
def test_faulty_idtoken_from_accesstoken_endpoint():
    consumer = Consumer(SessionDB(SERVER_INFO["issuer"]), CONFIG,
                        CLIENT_CONFIG, SERVER_INFO)
    consumer.keyjar = CLIKEYS
    mfos = MITMServer("http://localhost:8088")
    mfos.keyjar = SRVKEYS
    consumer.http_request = mfos.http_request
    consumer.redirect_uris = ["http://example.com/authz"]
    _state = "state0"
    consumer.nonce = rndstr()
    consumer.client_secret = "hemlig"
    consumer.secret_type = "basic"
    consumer.config["response_type"] = ["id_token"]

    args = {
        "client_id": consumer.client_id,
        "response_type": consumer.config["response_type"],
        "scope": ["openid"],
    }

    result = consumer.do_authorization_request(state=_state, request_args=args)
    consumer._backup("state0")

    assert result.status_code == 302
    # assert result.location.startswith(consumer.redirect_uri[0])
    _, query = result.headers["location"].split("?")
    print query
    try:
        consumer.parse_authz(query=query)
    except BadSignature:
        pass
    else:
        assert False
def test_userinfo():
    consumer = Consumer(SessionDB(SERVER_INFO["issuer"]), CONFIG,
                        CLIENT_CONFIG, SERVER_INFO)
    consumer.keyjar = CLIKEYS
    mfos = MyFakeOICServer("http://localhost:8088")
    mfos.keyjar = SRVKEYS
    consumer.http_request = mfos.http_request
    consumer.redirect_uris = ["http://example.com/authz"]
    _state = "state0"
    consumer.nonce = rndstr()
    consumer.secret_type = "basic"
    consumer.set_client_secret("hemligt")
    consumer.keyjar = CLIKEYS

    args = {
        "client_id": consumer.client_id,
        "response_type": "code",
        "scope": ["openid"],
    }

    result = consumer.do_authorization_request(state=_state, request_args=args)
    assert result.status_code == 302
    assert result.headers["location"].startswith(consumer.redirect_uris[0])
    _, query = result.headers["location"].split("?")

    consumer.parse_response(AuthorizationResponse,
                            info=query,
                            sformat="urlencoded")

    consumer.complete(_state)

    result = consumer.get_user_info(_state)
    print result
    assert result.type() == "OpenIDSchema"
    assert _eq(result.keys(), ['name', 'email', 'verified', 'nickname', 'sub'])
Exemple #6
0
def test_userinfo():
    consumer = Consumer(SessionDB(), CONFIG, CLIENT_CONFIG, SERVER_INFO)
    consumer.keyjar = CLIKEYS
    mfos = MyFakeOICServer("http://localhost:8088")
    mfos.keyjar = SRVKEYS
    consumer.http_request = mfos.http_request
    consumer.redirect_uris = ["http://example.com/authz"]
    consumer.state = "state0"
    consumer.nonce = rndstr()
    consumer.secret_type = "basic"
    consumer.set_client_secret("hemligt")
    consumer.keyjar = CLIKEYS

    args = {
        "client_id": consumer.client_id,
        "response_type": "code",
        "scope": ["openid"],
    }

    result = consumer.do_authorization_request(state=consumer.state,
                                               request_args=args)
    assert result.status_code == 302
    assert result.headers["location"].startswith(consumer.redirect_uris[0])
    _, query = result.headers["location"].split("?")

    consumer.parse_response(AuthorizationResponse, info=query,
                            sformat="urlencoded")

    consumer.complete()

    result = consumer.get_user_info()
    print result
    assert result.type() == "OpenIDSchema"
    assert _eq(result.keys(), ['name', 'email', 'verified', 'nickname', 'sub'])
def test_complete_auth_token_idtoken():
    consumer = Consumer(SessionDB(SERVER_INFO["issuer"]), CONFIG,
                        CLIENT_CONFIG, SERVER_INFO)
    consumer.keyjar = CLIKEYS
    mfos = MyFakeOICServer("http://localhost:8088")
    mfos.keyjar = SRVKEYS
    consumer.http_request = mfos.http_request
    consumer.redirect_uris = ["http://example.com/authz"]
    _state = "state0"
    consumer.nonce = rndstr()
    consumer.client_secret = "hemlig"
    consumer.secret_type = "basic"
    consumer.config["response_type"] = ["id_token", "token"]
    consumer.registration_response = {
        "id_token_signed_response_alg": "RS256",
    }
    consumer.provider_info = {"issuer": "http://localhost:8088/"}  # abs min
    consumer.authz_req = {}  # Store AuthzReq with state as key

    args = {
        "client_id": consumer.client_id,
        "response_type": consumer.config["response_type"],
        "scope": ["openid"],
    }

    result = consumer.do_authorization_request(state=_state,
                                               request_args=args)
    # consumer._backup("state0")

    assert result.status_code == 302
    #assert result.location.startswith(consumer.redirect_uri[0])
    _, query = result.headers["location"].split("?")
    print query
    part = consumer.parse_authz(query=query,
                                algs=consumer.sign_enc_algs("id_token"))
    print part
    auth = part[0]
    atr = part[1]
    assert part[2] is None


    #print auth.dictionary()
    #print acc.dictionary()
    assert auth is None
    assert atr.type() == "AccessTokenResponse"
    assert _eq(atr.keys(), ['access_token', 'id_token', 'expires_in',
                            'token_type', 'state', 'scope'])

    consumer.verify_id_token(atr["id_token"], consumer.authz_req[atr["state"]])
def test_complete_auth_token_idtoken():
    consumer = Consumer(SessionDB(SERVER_INFO["issuer"]), CONFIG,
                        CLIENT_CONFIG, SERVER_INFO)
    consumer.keyjar = CLIKEYS
    mfos = MyFakeOICServer("http://localhost:8088")
    mfos.keyjar = SRVKEYS
    consumer.http_request = mfos.http_request
    consumer.redirect_uris = ["http://example.com/authz"]
    _state = "state0"
    consumer.nonce = rndstr()
    consumer.client_secret = "hemlig"
    consumer.secret_type = "basic"
    consumer.config["response_type"] = ["id_token", "token"]
    consumer.registration_response = {
        "id_token_signed_response_alg": "RS256",
    }
    consumer.provider_info = {"issuer": "http://localhost:8088/"}  # abs min
    consumer.authz_req = {}  # Store AuthzReq with state as key

    args = {
        "client_id": consumer.client_id,
        "response_type": consumer.config["response_type"],
        "scope": ["openid"],
    }

    result = consumer.do_authorization_request(state=_state, request_args=args)
    # consumer._backup("state0")

    assert result.status_code == 302
    #assert result.location.startswith(consumer.redirect_uri[0])
    _, query = result.headers["location"].split("?")
    print query
    part = consumer.parse_authz(query=query,
                                algs=consumer.sign_enc_algs("id_token"))
    print part
    auth = part[0]
    atr = part[1]
    assert part[2] is None

    #print auth.dictionary()
    #print acc.dictionary()
    assert auth is None
    assert atr.type() == "AccessTokenResponse"
    assert _eq(atr.keys(), [
        'access_token', 'id_token', 'expires_in', 'token_type', 'state',
        'scope'
    ])

    consumer.verify_id_token(atr["id_token"], consumer.authz_req[atr["state"]])
def test_sign_userinfo():
    consumer = Consumer(SessionDB(SERVER_INFO["issuer"]), CONFIG,
                        CLIENT_CONFIG, SERVER_INFO)
    consumer.keyjar = CLIKEYS

    mfos = MyFakeOICServer("http://localhost:8088")
    mfos.keyjar = SRVKEYS
    mfos.userinfo_signed_response_alg = "RS256"

    consumer.http_request = mfos.http_request
    consumer.redirect_uris = ["http://example.com/authz"]
    _state = "state0"
    consumer.nonce = rndstr()
    consumer.secret_type = "basic"
    consumer.set_client_secret("hemligt")
    consumer.keyjar = CLIKEYS
    consumer.client_prefs = {"userinfo_signed_response_alg": "RS256"}
    consumer.provider_info = {
        "userinfo_endpoint": "http://localhost:8088/userinfo",
        "issuer": "http://localhost:8088/"}
    del consumer.config["request_method"]

    args = {
        "client_id": consumer.client_id,
        "response_type": "code",
        "scope": ["openid"],
    }

    sid, location = consumer.begin("openid", "code")
    print location

    result = consumer.do_authorization_request(state=_state,
                                               request_args=args)
    assert result.status_code == 302
    assert result.headers["location"].startswith(consumer.redirect_uris[0])
    _, query = result.headers["location"].split("?")

    consumer.parse_response(AuthorizationResponse, info=query,
                            sformat="urlencoded")

    consumer.complete(_state)

    result = consumer.get_user_info(_state)
    print result
    assert result.type() == "OpenIDSchema"
    assert _eq(result.keys(), ['name', 'email', 'verified', 'nickname', 'sub'])
def test_complete_auth_token():
    consumer = Consumer(SessionDB(SERVER_INFO["issuer"]), CONFIG,
                        CLIENT_CONFIG, SERVER_INFO)
    mfos = MyFakeOICServer("http://localhost:8088")
    mfos.keyjar = SRVKEYS
    consumer.http_request = mfos.http_request
    consumer.redirect_uris = ["http://example.com/authz"]
    _state = "state0"
    consumer.nonce = rndstr()
    consumer.client_secret = "hemlig"
    consumer.secret_type = "basic"
    consumer.config["response_type"] = ["code", "token"]

    args = {
        "client_id": consumer.client_id,
        "response_type": consumer.config["response_type"],
        "scope": ["openid"],
    }

    result = consumer.do_authorization_request(state=_state, request_args=args)
    consumer._backup("state0")

    assert result.status_code == 302
    # assert result.location.startswith(consumer.redirect_uri[0])
    _, query = result.headers["location"].split("?")
    print query
    part = consumer.parse_authz(query=query)
    print part
    auth = part[0]
    acc = part[1]
    assert part[2] is None

    #print auth.dictionary()
    #print acc.dictionary()
    assert auth.type() == "AuthorizationResponse"
    assert acc.type() == "AccessTokenResponse"
    print auth.keys()
    assert _eq(auth.keys(), [
        'code', 'access_token', 'expires_in', 'token_type', 'state', 'scope',
        'refresh_token'
    ])
    assert _eq(acc.keys(), [
        'token_type', 'state', 'access_token', 'scope', 'expires_in',
        'refresh_token'
    ])
Exemple #11
0
def test_complete_auth_token():
    consumer = Consumer(SessionDB(), CONFIG, CLIENT_CONFIG, SERVER_INFO)
    mfos = MyFakeOICServer("http://localhost:8088")
    mfos.keyjar = SRVKEYS
    consumer.http_request = mfos.http_request
    consumer.redirect_uris = ["http://example.com/authz"]
    consumer.state = "state0"
    consumer.nonce = rndstr()
    consumer.client_secret = "hemlig"
    consumer.secret_type = "basic"
    consumer.config["response_type"] = ["code", "token"]
    
    args = {
        "client_id": consumer.client_id,
        "response_type": consumer.config["response_type"],
        "scope": ["openid"],
    }

    result = consumer.do_authorization_request(state=consumer.state,
                                               request_args=args)
    consumer._backup("state0")

    assert result.status_code == 302
    #assert result.location.startswith(consumer.redirect_uri[0])
    _, query = result.headers["location"].split("?")
    print query
    environ = redirect_environment(query)

    part = consumer.parse_authz(environ, start_response)
    print part
    auth = part[0]
    acc = part[1]
    assert part[2] is None

    #print auth.dictionary()
    #print acc.dictionary()
    assert auth.type() == "AuthorizationResponse"
    assert acc.type() == "AccessTokenResponse"
    print auth.keys()
    assert _eq(auth.keys(), ['nonce', 'code', 'access_token', 'expires_in',
                             'token_type', 'state', 'scope', 'refresh_token'])
    assert _eq(acc.keys(), ['token_type', 'state', 'access_token', 'scope',
                            'expires_in', 'refresh_token'])
class TestOICConsumer():
    def setup_class(self):
        self.consumer = Consumer(SessionDB(SERVER_INFO["issuer"]), CONFIG,
                                 CLIENT_CONFIG, SERVER_INFO)
        self.consumer.behaviour = {
            "request_object_signing_alg": DEF_SIGN_ALG["openid_request_object"]
        }
        self.consumer.client_secret = CLIENT_SECRET

    def test_init(self):
        assert self.consumer

    def test_backup_keys(self):
        keys = self.consumer.__dict__.keys()
        print keys
        _dict = self.consumer.dictionary()
        print _dict.keys()
        dkeys = [key for key in keys if key not in _dict.keys()]
        print dkeys
        assert _eq(dkeys, IGNORE)

    def test_backup_restore(self):
        _dict = self.consumer.__dict__.items()

        self.consumer._backup("sid")
        self.consumer.restore("sid")

        assert _dict == self.consumer.__dict__.items()

        self.consumer.authorization_endpoint = AUTHZ_URL

        assert _dict != self.consumer.__dict__.items()

        self.consumer.restore("sid")

        assert _dict == self.consumer.__dict__.items()

    def test_backup_restore_update(self):
        self.consumer.authorization_endpoint = AUTHZ_URL
        self.consumer.token_endpoint = "http://example.com/token"
        self.consumer.userinfo_endpoint = "http://example.com/userinfo"

        self.consumer._backup("sid")

        self.consumer.authorization_endpoint = AUTHZ_ORG_URL
        self.consumer.token_endpoint = "http://example.org/token"
        self.consumer.userinfo_endpoint = ""

        assert self.consumer.authorization_endpoint == AUTHZ_ORG_URL
        assert self.consumer.token_endpoint == "http://example.org/token"
        assert self.consumer.userinfo_endpoint == ""

        self.consumer.update("sid")

        assert self.consumer.authorization_endpoint == AUTHZ_ORG_URL
        assert self.consumer.token_endpoint == "http://example.org/token"
        assert self.consumer.userinfo_endpoint == "http://example.com/userinfo"

    def test_begin(self):
        self.consumer.authorization_endpoint = AUTHZ_URL
        self.consumer.keyjar[""].append(KC_RSA)
        # self.consumer.keyjar.set_sign_key(rsapub, "rsa")
        #self.consumer.keyjar.set_verify_key(rsapub, "rsa")

        srv = Server()
        srv.keyjar = SRVKEYS
        print "redirect_uris", self.consumer.redirect_uris
        print "config", self.consumer.config
        sid, location = self.consumer.begin("openid", "code")
        print location
        authreq = srv.parse_authorization_request(url=location)
        print authreq.keys()
        assert _eq(authreq.keys(), [
            'request', 'state', 'max_age', 'claims', 'response_type',
            'client_id', 'scope', 'redirect_uri'
        ])

        assert authreq["state"] == sid
        assert authreq["scope"] == self.consumer.config["scope"]
        assert authreq["client_id"] == self.consumer.client_id

    def test_begin_file(self):
        tempdir = tempfile.mkdtemp()
        self.consumer.config["request_method"] = "file"
        self.consumer.config["temp_dir"] = tempdir
        self.consumer.config["temp_path"] = tempdir
        self.consumer.config["authz_page"] = "/authz"
        srv = Server()
        srv.keyjar = SRVKEYS

        sid, location = self.consumer.begin("openid",
                                            "code",
                                            path="http://localhost:8087")
        print location
        # vkeys = {".":srv.keyjar.get_verify_key()}
        authreq = srv.parse_authorization_request(url=location)
        print authreq.keys()
        assert _eq(authreq.keys(), [
            'max_age', 'state', 'redirect_uri', 'response_type', 'client_id',
            'scope', 'claims', 'request_uri'
        ])

        assert authreq["state"] == sid
        assert authreq["scope"] == self.consumer.config["scope"]
        assert authreq["client_id"] == self.consumer.client_id
        assert authreq["redirect_uri"].startswith(
            "http://localhost:8087/authz")
        # Cleanup the file we have created
        shutil.rmtree(tempdir)

    def test_complete(self):
        mfos = MyFakeOICServer("http://localhost:8088")
        mfos.keyjar = SRVKEYS

        self.consumer.http_request = mfos.http_request
        _state = "state0"
        self.consumer.nonce = rndstr()
        self.consumer.redirect_uris = ["https://example.com/cb"]
        args = {
            "client_id": self.consumer.client_id,
            "response_type": "code",
            "scope": ["openid"],
        }

        result = self.consumer.do_authorization_request(state=_state,
                                                        request_args=args)
        assert result.status_code == 302
        print "redirect_uris", self.consumer.redirect_uris
        print result.headers["location"]

        assert result.headers["location"].startswith(
            self.consumer.redirect_uris[0])
        _, query = result.headers["location"].split("?")

        # vkeys = {".": self.consumer.keyjar.get_verify_key()}

        self.consumer.parse_response(AuthorizationResponse,
                                     info=query,
                                     sformat="urlencoded")

        resp = self.consumer.complete(_state)
        print resp
        assert resp.type() == "AccessTokenResponse"
        print resp.keys()
        assert _eq(resp.keys(), [
            'token_type', 'state', 'access_token', 'scope', 'expires_in',
            'refresh_token'
        ])

        assert resp["state"] == _state

    def test_parse_authz(self):
        mfos = MyFakeOICServer("http://localhost:8088")
        mfos.keyjar = SRVKEYS

        self.consumer.http_request = mfos.http_request
        _state = "state0"
        self.consumer.nonce = rndstr()
        args = {
            "client_id": self.consumer.client_id,
            "response_type": "code",
            "scope": ["openid"],
        }

        result = self.consumer.do_authorization_request(state=_state,
                                                        request_args=args)

        print self.consumer.sdb["state0"].keys()
        part = self.consumer.parse_authz(query=result.headers["location"])
        print part
        atr = part[0]
        assert part[1] is None
        assert part[2] is None

        assert atr.type() == "AuthorizationResponse"
        assert atr["state"] == _state
        assert "code" in atr

    def test_parse_authz_implicit(self):
        mfos = MyFakeOICServer("http://localhost:8088")
        mfos.keyjar = SRVKEYS

        self.consumer.http_request = mfos.http_request
        self.consumer.config["response_type"] = ["token"]
        _state = "statxxx"
        args = {
            "client_id": self.consumer.client_id,
            "response_type": "implicit",
            "scope": ["openid"],
            "redirect_uri": "http://localhost:8088/cb"
        }

        result = self.consumer.do_authorization_request(state=_state,
                                                        request_args=args)

        part = self.consumer.parse_authz(query=result.headers["location"])
        print part
        assert part[0] is None
        atr = part[1]
        assert part[2] is None

        assert atr.type() == "AccessTokenResponse"
        assert atr["state"] == _state
        assert "access_token" in atr
Exemple #13
0
class TestOICConsumer():
    @pytest.fixture(autouse=True)
    def setup_consumer(self):
        client_id = "client_1"
        client_config = {
            "client_id": client_id,
            "client_authn_method": CLIENT_AUTHN_METHOD,
            #'config': {}
        }

        self.consumer = Consumer(SessionDB(SERVER_INFO["issuer"]),
                                 CONFIG, client_config, SERVER_INFO)
        self.consumer.behaviour = {
            "request_object_signing_alg": DEF_SIGN_ALG["openid_request_object"]}
        self.consumer.client_secret = "abcdefghijklmnop"
        self.consumer.keyjar = CLIKEYS
        self.consumer.redirect_uris = ["https://example.com/cb"]
        self.consumer.authorization_endpoint = "http://example.com/authorization"
        self.consumer.token_endpoint = "http://example.com/token"
        self.consumer.userinfo_endpoint = "http://example.com/userinfo"
        self.consumer.client_secret = "hemlig"
        self.consumer.secret_type = "basic"

        mfos = MyFakeOICServer("http://*****:*****@connect-op.heroku.com"
        res = c.discover(principal)
        assert isinstance(res, ProviderConfigurationResponse)
        assert _eq(res.keys(), ['registration_endpoint', 'scopes_supported',
                                'identifiers_supported', 'token_endpoint',
                                'flows_supported', 'version',
                                'userinfo_endpoint',
                                'authorization_endpoint', 'x509_url', 'issuer'])
        assert res.version == "3.0"
        assert _eq(res.flows_supported, ['code', 'token', 'id_token',
                                         'code token', 'code id_token',
                                         'id_token token'])

    def test_discover(self):
        c = Consumer(None, None)
        mfos = MyFakeOICServer("http://*****:*****@example.com"
        res = c.discover(principal)
        assert res == "http://*****:*****@example.com"

        res = c.discover(principal)
        info = c.provider_config(res)
        assert isinstance(info, ProviderConfigurationResponse)
        assert _eq(info.keys(), ['registration_endpoint', 'jwks_uri',
                                 'check_session_endpoint',
                                 'refresh_session_endpoint',
                                 'register_endpoint',
                                 'subject_types_supported',
                                 'token_endpoint_auth_methods_supported',
                                 'id_token_signing_alg_values_supported',
                                 'grant_types_supported', 'user_info_endpoint',
                                 'claims_parameter_supported',
                                 'request_parameter_supported',
                                 'discovery_endpoint', 'issuer',
                                 'authorization_endpoint', 'scopes_supported',
                                 'require_request_uri_registration',
                                 'identifiers_supported', 'token_endpoint',
                                 'request_uri_parameter_supported', 'version',
                                 'response_types_supported',
                                 'end_session_endpoint', 'flows_supported'])

        assert info["end_session_endpoint"] == "http://example.com/end_session"

    def test_client_register(self):
        c = Consumer(None, None)

        c.application_type = "web"
        c.application_name = "My super service"
        c.redirect_uris = ["http://example.com/authz"]
        c.contact = ["*****@*****.**"]

        mfos = MyFakeOICServer("http://example.com")
        mfos.keyjar = SRVKEYS
        c.http_request = mfos.http_request
        location = c.discover("*****@*****.**")
        info = c.provider_config(location)

        c.register(info["registration_endpoint"])
        assert c.client_id is not None
        assert c.client_secret is not None
        assert c.registration_expires > utc_time_sans_frac()

    def _faulty_id_token(self):
        idval = {'nonce': 'KUEYfRM2VzKDaaKD', 'sub': 'EndUserSubject',
                 'iss': 'https://alpha.cloud.nds.rub.de', 'exp': 1420823073,
                 'iat': 1420822473, 'aud': 'TestClient'}
        idts = IdToken(**idval)

        _signed_jwt = idts.to_jwt(key=[SYMKey(key="TestPassword")],
                                  algorithm="HS256")

        # Mess with the signed id_token
        p = _signed_jwt.split(".")
        p[2] = "aaa"

        return ".".join(p)

    def test_faulty_id_token(self):
        _faulty_signed_jwt = self._faulty_id_token()

        with pytest.raises(BadSignature):
            IdToken().from_jwt(_faulty_signed_jwt,
                               key=[SYMKey(key="TestPassword")])

        # What if no verification key is given ?
        # Should also result in an exception
        with pytest.raises(MissingSigningKey):
            _ = IdToken().from_jwt(_faulty_signed_jwt)

    def test_faulty_id_token_in_access_token_response(self):
        c = Consumer(None, None)
        c.keyjar.add_symmetric("", "TestPassword", ["sig"])

        _info = {"access_token": "accessTok",
                 "id_token": self._faulty_id_token(),
                 "token_type": "Bearer"}

        _json = json.dumps(_info)
        with pytest.raises(BadSignature):
            c.parse_response(AccessTokenResponse, _json, sformat="json")

    def test_faulty_idtoken_from_accesstoken_endpoint(self):
        mfos = MITMServer("http://localhost:8088")
        mfos.keyjar = SRVKEYS
        self.consumer.http_request = mfos.http_request
        _state = "state0"
        self.consumer.consumer_config["response_type"] = ["id_token"]

        args = {
            "client_id": self.consumer.client_id,
            "response_type": self.consumer.consumer_config["response_type"],
            "scope": ["openid"],
        }

        result = self.consumer.do_authorization_request(state=_state,
                                                        request_args=args)
        self.consumer._backup("state0")

        assert result.status_code == 302
        query = urlparse(result.headers["location"]).query
        with pytest.raises(BadSignature):
            self.consumer.parse_authz(query=query)
Exemple #14
0
class TestOICConsumer():
    @pytest.fixture(autouse=True)
    def setup_consumer(self, fake_oic_server, session_db_factory):
        client_id = "client_1"
        client_config = {
            "client_id": client_id,
            "client_authn_method": CLIENT_AUTHN_METHOD,
            # 'config': {}
        }

        self.consumer = Consumer(session_db_factory(SERVER_INFO["issuer"]),
                                 CONFIG, client_config, SERVER_INFO)
        self.consumer.behaviour = {
            "request_object_signing_alg": DEF_SIGN_ALG["openid_request_object"]
        }
        self.consumer.client_secret = "abcdefghijklmnop"
        self.consumer.keyjar = CLIKEYS
        self.consumer.redirect_uris = ["https://example.com/cb"]
        self.consumer.authorization_endpoint = \
            "http://example.com/authorization"
        self.consumer.token_endpoint = "http://example.com/token"
        self.consumer.userinfo_endpoint = "http://example.com/userinfo"
        self.consumer.client_secret = "hemlig"
        self.consumer.secret_type = "basic"

        mfos = fake_oic_server("http://*****:*****@connect-op.heroku.com"
        res = c.discover(principal)
        assert isinstance(res, ProviderConfigurationResponse)
        assert _eq(res.keys(), [
            'registration_endpoint', 'scopes_supported',
            'identifiers_supported', 'token_endpoint', 'flows_supported',
            'version', 'userinfo_endpoint', 'authorization_endpoint',
            'x509_url', 'issuer'
        ])
        assert res.version == "3.0"
        assert _eq(res.flows_supported, [
            'code', 'token', 'id_token', 'code token', 'code id_token',
            'id_token token'
        ])

    def test_discover(self, fake_oic_server):
        c = Consumer(None, None)
        mfos = fake_oic_server("https://*****:*****@example.com"
        res = c.discover(principal)
        assert res == "https://*****:*****@example.com"

        res = c.discover(principal)
        info = c.provider_config(res)
        assert isinstance(info, ProviderConfigurationResponse)
        assert _eq(info.keys(), [
            'registration_endpoint', 'jwks_uri', 'check_session_endpoint',
            'refresh_session_endpoint', 'register_endpoint',
            'subject_types_supported', 'token_endpoint_auth_methods_supported',
            'id_token_signing_alg_values_supported', 'grant_types_supported',
            'user_info_endpoint', 'claims_parameter_supported',
            'request_parameter_supported', 'discovery_endpoint', 'issuer',
            'authorization_endpoint', 'scopes_supported',
            'require_request_uri_registration', 'identifiers_supported',
            'token_endpoint', 'request_uri_parameter_supported', 'version',
            'response_types_supported', 'end_session_endpoint',
            'flows_supported'
        ])

        assert info[
            "end_session_endpoint"] == "https://example.com/end_session"

    def test_client_register(self, fake_oic_server):
        c = Consumer(None, None)

        c.application_type = "web"
        c.application_name = "My super service"
        c.redirect_uris = ["https://example.com/authz"]
        c.contact = ["*****@*****.**"]
        mfos = fake_oic_server("https://example.com")
        mfos.keyjar = SRVKEYS
        c.http_request = mfos.http_request
        location = c.discover("*****@*****.**")
        info = c.provider_config(location)

        c.register(info["registration_endpoint"])
        assert c.client_id is not None
        assert c.client_secret is not None
        assert c.registration_expires > utc_time_sans_frac()

    def _faulty_id_token(self):
        idval = {
            'nonce': 'KUEYfRM2VzKDaaKD',
            'sub': 'EndUserSubject',
            'iss': 'https://alpha.cloud.nds.rub.de',
            'exp': 1420823073,
            'iat': 1420822473,
            'aud': 'TestClient'
        }
        idts = IdToken(**idval)

        _signed_jwt = idts.to_jwt(key=[SYMKey(key="TestPassword")],
                                  algorithm="HS256")

        # Mess with the signed id_token
        p = _signed_jwt.split(".")
        p[2] = "aaa"

        return ".".join(p)

    def test_faulty_id_token(self):
        _faulty_signed_jwt = self._faulty_id_token()

        with pytest.raises(BadSignature):
            IdToken().from_jwt(_faulty_signed_jwt,
                               key=[SYMKey(key="TestPassword")])

        # What if no verification key is given ?
        # Should also result in an exception
        with pytest.raises(MissingSigningKey):
            IdToken().from_jwt(_faulty_signed_jwt)

    def test_faulty_id_token_in_access_token_response(self):
        c = Consumer(None, None)
        c.keyjar.add_symmetric("", "TestPassword", ["sig"])

        _info = {
            "access_token": "accessTok",
            "id_token": self._faulty_id_token(),
            "token_type": "Bearer"
        }

        _json = json.dumps(_info)
        with pytest.raises(BadSignature):
            c.parse_response(AccessTokenResponse, _json, sformat="json")

    def test_faulty_idtoken_from_accesstoken_endpoint(self, mitm_server):
        mfos = mitm_server("http://localhost:8088")
        mfos.keyjar = SRVKEYS
        self.consumer.http_request = mfos.http_request
        _state = "state0"
        self.consumer.consumer_config["response_type"] = ["id_token"]

        args = {
            "client_id": self.consumer.client_id,
            "response_type": self.consumer.consumer_config["response_type"],
            "scope": ["openid"],
        }

        result = self.consumer.do_authorization_request(state=_state,
                                                        request_args=args)
        self.consumer._backup("state0")

        assert result.status_code == 302
        query = urlparse(result.headers["location"]).query
        with pytest.raises(BadSignature):
            self.consumer.parse_authz(query=query)
Exemple #15
0
class TestOICConsumer():
    def setup_class(self):
        self.consumer = Consumer(SessionDB(), CONFIG, CLIENT_CONFIG,
                                 SERVER_INFO)
        self.consumer.client_secret = CLIENT_SECRET

    def test_init(self):
        assert self.consumer

    def test_backup_keys(self):
        keys = self.consumer.__dict__.keys()
        print keys
        _dict = self.consumer.dictionary()
        print _dict.keys()
        dkeys = [key for key in keys if key not in _dict.keys()]
        print dkeys
        assert _eq(dkeys, IGNORE)

    def test_backup_restore(self):
        _dict = self.consumer.__dict__.items()

        self.consumer._backup("sid")
        self.consumer.restore("sid")

        assert _dict == self.consumer.__dict__.items()

        self.consumer.authorization_endpoint = AUTHZ_URL

        assert _dict != self.consumer.__dict__.items()

        self.consumer.restore("sid")

        assert _dict == self.consumer.__dict__.items()

    def test_backup_restore_update(self):
        self.consumer.authorization_endpoint = AUTHZ_URL
        self.consumer.token_endpoint = "http://example.com/token"
        self.consumer.userinfo_endpoint = "http://example.com/userinfo"

        self.consumer._backup("sid")

        self.consumer.authorization_endpoint = AUTHZ_ORG_URL
        self.consumer.token_endpoint = "http://example.org/token"
        self.consumer.userinfo_endpoint = ""

        assert self.consumer.authorization_endpoint == AUTHZ_ORG_URL
        assert self.consumer.token_endpoint == "http://example.org/token"
        assert self.consumer.userinfo_endpoint == ""

        self.consumer.update("sid")

        assert self.consumer.authorization_endpoint == AUTHZ_ORG_URL
        assert self.consumer.token_endpoint == "http://example.org/token"
        assert self.consumer.userinfo_endpoint == "http://example.com/userinfo"

    def test_begin(self):
        self.consumer.authorization_endpoint = AUTHZ_URL
        self.consumer.keyjar[""].append(KC_RSA)
        #self.consumer.keyjar.set_sign_key(rsapub, "rsa")
        #self.consumer.keyjar.set_verify_key(rsapub, "rsa")

        srv = Server()
        srv.keyjar = SRVKEYS
        print "redirect_uris", self.consumer.redirect_uris
        print "config", self.consumer.config
        location = self.consumer.begin("openid", "code")
        print location
        authreq = srv.parse_authorization_request(url=location)
        print authreq.keys()
        assert _eq(authreq.keys(), ['request', 'state', 'max_age', 'claims',
                                    'response_type', 'client_id', 'scope',
                                    'redirect_uri'])

        assert authreq["state"] == self.consumer.state
        assert authreq["scope"] == self.consumer.config["scope"]
        assert authreq["client_id"] == self.consumer.client_id

    def test_begin_file(self):
        self.consumer.config["request_method"] = "file"
        self.consumer.config["temp_dir"] = "./file"
        self.consumer.config["temp_path"] = "/tmp/"
        self.consumer.config["authz_page"] = "/authz"
        srv = Server()
        srv.keyjar = SRVKEYS

        location = self.consumer.begin("openid", "code",
                                       path="http://localhost:8087")
        print location
        #vkeys = {".":srv.keyjar.get_verify_key()}
        authreq = srv.parse_authorization_request(url=location)
        print authreq.keys()
        assert _eq(authreq.keys(), ['max_age', 'state', 'redirect_uri',
                                    'response_type', 'client_id', 'scope',
                                    'claims', 'request_uri'])

        assert authreq["state"] == self.consumer.state
        assert authreq["scope"] == self.consumer.config["scope"]
        assert authreq["client_id"] == self.consumer.client_id
        assert authreq["redirect_uri"].startswith("http://localhost:8087/authz")

    def test_complete(self):
        mfos = MyFakeOICServer("http://localhost:8088")
        mfos.keyjar = SRVKEYS

        self.consumer.http_request = mfos.http_request
        self.consumer.state = "state0"
        self.consumer.nonce = rndstr()
        self.consumer.redirect_uris = ["https://example.com/cb"]
        args = {
            "client_id": self.consumer.client_id,
            "response_type": "code",
            "scope": ["openid"],
        }

        result = self.consumer.do_authorization_request(
            state=self.consumer.state, request_args=args)
        assert result.status_code == 302
        print "redirect_uris", self.consumer.redirect_uris
        print result.headers["location"]

        assert result.headers["location"].startswith(
            self.consumer.redirect_uris[0])
        _, query = result.headers["location"].split("?")

        #vkeys = {".": self.consumer.keyjar.get_verify_key()}

        self.consumer.parse_response(AuthorizationResponse, info=query,
                                     sformat="urlencoded")

        resp = self.consumer.complete()
        print resp
        assert resp.type() == "AccessTokenResponse"
        print resp.keys()
        assert _eq(resp.keys(), ['token_type', 'state', 'access_token',
                                 'scope', 'expires_in', 'refresh_token'])

        assert resp["state"] == self.consumer.state

    def test_parse_authz(self):
        mfos = MyFakeOICServer("http://localhost:8088")
        mfos.keyjar = SRVKEYS

        self.consumer.http_request = mfos.http_request
        self.consumer.state = "state0"
        self.consumer.nonce = rndstr()
        args = {
            "client_id": self.consumer.client_id,
            "response_type": "code",
            "scope": ["openid"],
        }

        result = self.consumer.do_authorization_request(
            state=self.consumer.state, request_args=args)

        print self.consumer.sdb.keys()
        print self.consumer.sdb["state0"].keys()
        part = self.consumer.parse_authz(query=result.headers["location"])
        print part
        atr = part[0]
        assert part[1] is None
        assert part[2] is None

        assert atr.type() == "AuthorizationResponse"
        assert atr["state"] == "state0"
        assert "code" in atr

    def test_parse_authz_implicit(self):
        self.consumer.config["response_type"] = "implicit"

        args = {
            "client_id": self.consumer.client_id,
            "response_type": "implicit",
            "scope": ["openid"],
        }

        result = self.consumer.do_authorization_request(
            state=self.consumer.state, request_args=args)

        part = self.consumer.parse_authz(query=result.headers["location"])
        print part
        assert part[0] is None
        atr = part[1]
        assert part[2] is None

        assert atr.type() == "AccessTokenResponse"
        assert atr["state"] == "state0"
        assert "access_token" in atr
class TestOICConsumer:
    @pytest.fixture(autouse=True)
    def setup_consumer(self, session_db_factory):
        client_id = "client_1"
        client_config = {
            "client_id": client_id,
            "client_authn_method": CLIENT_AUTHN_METHOD,
        }

        self.consumer = Consumer(DictSessionBackend(), CONFIG, client_config,
                                 SERVER_INFO)
        self.consumer.behaviour = {
            "request_object_signing_alg": DEF_SIGN_ALG["openid_request_object"]
        }
        self.consumer.keyjar = CLIKEYS
        self.consumer.redirect_uris = ["https://example.com/cb"]
        self.consumer.authorization_endpoint = "https://example.com/authorization"
        self.consumer.token_endpoint = "https://example.com/token"
        self.consumer.userinfo_endpoint = "https://example.com/userinfo"  # type: ignore
        self.consumer.client_secret = "hemlig"
        self.consumer.secret_type = "basic"

    def test_backup_keys(self):
        keys = self.consumer.__dict__.keys()
        _dict = self.consumer.dictionary()
        dkeys = [key for key in keys if key not in _dict.keys()]
        assert _eq(dkeys, IGNORE)

    def test_backup_restore(self):
        authz_org_url = "http://example.org/authorization"

        _dict = sorted(list(self.consumer.__dict__.items()))

        self.consumer._backup("sid")
        self.consumer.restore("sid")
        assert sorted(_dict) == sorted(list(self.consumer.__dict__.items()))

        self.consumer.authorization_endpoint = authz_org_url
        assert _dict != sorted(list(self.consumer.__dict__.items()))

        self.consumer.restore("sid")
        assert _dict == sorted(list(self.consumer.__dict__.items()))

    def test_backup_restore_update(self):
        authz_org_url = "http://example.org/authorization"

        self.consumer._backup("sid")

        self.consumer.authorization_endpoint = authz_org_url
        self.consumer.token_endpoint = "https://example.org/token"
        self.consumer.userinfo_endpoint = ""  # type: ignore

        assert self.consumer.authorization_endpoint == authz_org_url
        assert self.consumer.token_endpoint == "https://example.org/token"
        assert self.consumer.userinfo_endpoint == ""  # type: ignore

        self.consumer.update("sid")

        assert self.consumer.authorization_endpoint == authz_org_url
        assert self.consumer.token_endpoint == "https://example.org/token"
        assert (self.consumer.userinfo_endpoint  # type: ignore
                == "https://example.com/userinfo")

    def test_begin(self):
        srv = Server()
        srv.keyjar = SRVKEYS
        sid, location = self.consumer.begin("openid", "code")
        authreq = srv.parse_authorization_request(url=location)
        assert _eq(
            list(authreq.keys()),
            [
                "state",
                "max_age",
                "claims",
                "response_type",
                "client_id",
                "scope",
                "redirect_uri",
            ],
        )

        assert authreq["state"] == sid
        assert authreq["scope"] == self.consumer.consumer_config["scope"]
        assert authreq["client_id"] == self.consumer.client_id

    def test_begin_file(self, tmpdir):
        path = tmpdir.strpath
        external_path = "/exported"
        self.consumer.consumer_config["request_method"] = "file"
        self.consumer.consumer_config["temp_dir"] = path
        self.consumer.consumer_config["temp_path"] = external_path
        self.consumer.consumer_config["authz_page"] = "/authz"
        srv = Server()
        srv.keyjar = SRVKEYS

        sid, location = self.consumer.begin("openid",
                                            "code",
                                            path="http://*****:*****@example.com",
                    "nickname": "Ilja",
                    "verified": True,
                },
            )

            result = self.consumer.do_authorization_request(state=_state,
                                                            request_args=args)
            parsed = urlparse(result.headers["location"])

            self.consumer.parse_response(AuthorizationResponse,
                                         info=parsed.query,
                                         sformat="urlencoded")

            self.consumer.complete(_state)

            result = self.consumer.get_user_info(_state)
        assert isinstance(result, OpenIDSchema)
        assert _eq(result.keys(),
                   ["name", "email", "verified", "nickname", "sub"])

    def test_sign_userinfo(self):
        _state = "state0"
        self.consumer.client_prefs = {"userinfo_signed_response_alg": "RS256"}
        del self.consumer.consumer_config["request_method"]

        args = {
            "client_id": self.consumer.client_id,
            "response_type": "code",
            "scope": ["openid"],
        }

        location = "https://example.com/cb?code=code&state=state0"
        with responses.RequestsMock() as rsps:
            rsps.add(
                responses.GET,
                "https://example.com/authorization",
                status=302,
                headers={"location": location},
            )
            rsps.add(
                responses.POST,
                "https://example.com/token",
                content_type="application/json",
                json={
                    "access_token": "some_token",
                    "token_type": "bearer",
                    "state": "state0",
                    "scope": "openid",
                },
            )
            rsps.add(
                responses.POST,
                "https://example.com/userinfo",
                content_type="application/json",
                json={
                    "name": "Ilja",
                    "sub": "some_sub",
                    "email": "*****@*****.**",
                    "nickname": "Ilja",
                    "verified": True,
                },
            )
            self.consumer.begin("openid", "code")
            result = self.consumer.do_authorization_request(state=_state,
                                                            request_args=args)
            parsed = urlparse(result.headers["location"])
            self.consumer.parse_response(AuthorizationResponse,
                                         info=parsed.query,
                                         sformat="urlencoded")

            self.consumer.complete(_state)

            result = self.consumer.get_user_info(_state)
        assert isinstance(result, OpenIDSchema)
        assert _eq(result.keys(),
                   ["name", "email", "verified", "nickname", "sub"])

    def test_get_userinfo_claims(self):
        _state = "state0"

        args = {
            "client_id": self.consumer.client_id,
            "response_type": "code",
            "scope": ["openid"],
        }

        location = "https://example.com/cb?code=code&state=state0"
        with responses.RequestsMock() as rsps:
            rsps.add(
                responses.GET,
                "https://example.com/authorization",
                status=302,
                headers={"location": location},
            )
            rsps.add(
                responses.POST,
                "https://example.com/token",
                content_type="application/json",
                json={
                    "access_token": "some_token",
                    "token_type": "bearer",
                    "state": "state0",
                    "scope": "openid",
                },
            )
            rsps.add(
                responses.POST,
                "https://example.com/userinfo",
                content_type="application/json",
                json={
                    "name": "Ilja",
                    "sub": "some_sub",
                    "email": "*****@*****.**",
                    "nickname": "Ilja",
                    "verified": True,
                },
            )

            result = self.consumer.do_authorization_request(state=_state,
                                                            request_args=args)
            parsed = urlparse(result.headers["location"])
            self.consumer.parse_response(AuthorizationResponse,
                                         info=parsed.query,
                                         sformat="urlencoded")
            response = self.consumer.complete(_state)
            result = self.consumer.get_userinfo_claims(
                response["access_token"],
                self.consumer.userinfo_endpoint,  # type: ignore
            )
        assert isinstance(result, OpenIDSchema)
        assert _eq(result.keys(),
                   ["name", "email", "verified", "nickname", "sub"])

    def real_test_discover(self):
        c = Consumer(None, None)
        principal = "*****@*****.**"
        res = c.discover(principal)
        assert isinstance(res, ProviderConfigurationResponse)
        assert _eq(
            res.keys(),
            [
                "registration_endpoint",
                "scopes_supported",
                "identifiers_supported",
                "token_endpoint",
                "flows_supported",
                "version",
                "userinfo_endpoint",
                "authorization_endpoint",
                "x509_url",
                "issuer",
            ],
        )
        assert res.version == "3.0"  # type: ignore
        assert _eq(
            res.flows_supported,  # type: ignore
            [
                "code",
                "token",
                "id_token",
                "code token",
                "code id_token",
                "id_token token",
            ],
        )

    def test_discover(self):
        c = Consumer(None, None)
        webfinger = {
            "subject":
            "acct:[email protected]",
            "links": [{
                "rel": "http://openid.net/specs/connect/1.0/issuer",
                "href": "https://*****:*****@example.com"
        with responses.RequestsMock() as rsps:
            rsps.add(
                responses.GET,
                "https://example.com/.well-known/webfinger"
                "?resource=acct%3Afoo%40example.com&rel=http%3A%2F%2Fopenid.net%2Fspecs%2Fconnect%2F1.0%2Fissuer",
                json=webfinger,
            )
            res = c.discover(principal)
        assert res == "https://localhost:8088/"

    def test_client_register(self):
        c = Consumer(None, None)
        c.redirect_uris = ["https://example.com/authz"]
        reg_resp = {
            "client_id": "some_client",
            "client_secret": "super_secret",
            "client_secret_expires_at": 123456789,
            "redirect_uris": ["https://example.com/authz"],
        }
        with responses.RequestsMock() as rsps:
            rsps.add(responses.POST,
                     "https://example.com/register/",
                     json=reg_resp)
            c.register("https://example.com/register/")
            assert json.loads(rsps.calls[0].request.body) == {
                "application_type": "web",
                "response_types": ["code"],
                "redirect_uris": ["https://example.com/authz"],
                "grant_types": ["authorization_code"],
            }
        assert c.client_id == "some_client"
        assert c.client_secret == "super_secret"
        assert c.registration_expires == 123456789

    def test_client_register_token(self):
        c = Consumer(None, None)

        c.redirect_uris = ["https://example.com/authz"]

        client_info = {
            "client_id": "clientid",
            "redirect_uris": ["https://example.com/authz"],
        }

        with responses.RequestsMock() as rsps:
            rsps.add(
                rsps.POST,
                "https://provider.example.com/registration/",
                json=client_info,
            )
            c.register(
                "https://provider.example.com/registration/",
                registration_token="initial_registration_token",
            )
            header = rsps.calls[0].request.headers["Authorization"]
            assert header == "Bearer aW5pdGlhbF9yZWdpc3RyYXRpb25fdG9rZW4="

    def test_client_register_token_b64(self):
        c = Consumer(None, None)

        c.redirect_uris = ["https://example.com/authz"]

        client_info = {
            "client_id": "clientid",
            "redirect_uris": ["https://example.com/authz"],
        }
        registration_token = (
            "eyJhbGciOiJIUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6IC"
            "JlYjc1N2M3Yy00MWRlLTRmZDYtOTkwNy1hNGFiMDY1ZjEzMmEifQ.eyJqdGkiOiI2ZWY0MDZi"
            "MC02YzA3LTQ0NzctOWU1YS1hY2FiZjNiMWNiMjgiLCJleHAiOjAsIm5iZiI6MCwiaWF0Ijox"
            "NTczNzMxNjg5LCJpc3MiOiJodHRwczovL29wZW5pZC1wcm92aWRlci5leGFtcGxlLmNvbS9h"
            "dXRoL3JlYWxtcy9tYXN0ZXIiLCJhdWQiOiJodHRwczovL29wZW5pZC1wcm92aWRlci5leGFt"
            "cGxlLmNvbS9hdXRoL3JlYWxtcy9tYXN0ZXIiLCJ0eXAiOiJJbml0aWFsQWNjZXNzVG9rZW4i"
            "fQ.0XTlit_JcxPZeIy8A4BzrHn1NvegVP7ws8KI0ySFex8")
        with responses.RequestsMock() as rsps:
            rsps.add(
                rsps.POST,
                "https://provider.example.com/registration/",
                json=client_info,
            )
            c.register(
                "https://provider.example.com/registration/",
                registration_token=registration_token,
            )
            header = rsps.calls[0].request.headers["Authorization"]
            assert header == "Bearer " + registration_token

    def _faulty_id_token(self):
        idval = {
            "nonce": "KUEYfRM2VzKDaaKD",
            "sub": "EndUserSubject",
            "iss": "https://alpha.cloud.nds.rub.de",
            "exp": 1420823073,
            "iat": 1420822473,
            "aud": "TestClient",
        }
        idts = IdToken(**idval)

        _signed_jwt = idts.to_jwt(key=[SYMKey(key="TestPassword")],
                                  algorithm="HS256")

        # Mess with the signed id_token
        p = _signed_jwt.split(".")
        p[2] = "aaa"

        return ".".join(p)

    def test_faulty_id_token(self):
        _faulty_signed_jwt = self._faulty_id_token()

        with pytest.raises(BadSignature):
            IdToken().from_jwt(_faulty_signed_jwt,
                               key=[SYMKey(key="TestPassword")])

        # What if no verification key is given ?
        # Should also result in an exception
        with pytest.raises(MissingSigningKey):
            IdToken().from_jwt(_faulty_signed_jwt)

    def test_faulty_id_token_in_access_token_response(self):
        c = Consumer(None, None)
        c.keyjar.add_symmetric("", "TestPassword", ["sig"])

        _info = {
            "access_token": "accessTok",
            "id_token": self._faulty_id_token(),
            "token_type": "Bearer",
        }

        _json = json.dumps(_info)
        with pytest.raises(ValueError):
            c.parse_response(AccessTokenResponse, _json, sformat="json")

    def test_faulty_idtoken_from_accesstoken_endpoint(self):
        _state = "state0"
        self.consumer.consumer_config["response_type"] = ["id_token"]

        args = {
            "client_id": self.consumer.client_id,
            "response_type": self.consumer.consumer_config["response_type"],
            "scope": ["openid"],
        }

        location = (
            "https://example.com/cb?state=state0&id_token=eyJhbGciOiJSUzI1NiJ9"
            ".eyJpc3MiOiAiaHR0cDovL2xvY2FsaG9zdDo4MDg4IiwgInN1YiI6ICJhNWRkMjRiMmYwOGE2ODZmZDM4NmMyMmM"
            "zZmY4ZWUyODFlZjJmYmZmMWZkZTcwMDg2NjhjZGEzZGVjZmE0NjY5IiwgImF1ZCI6IFsiY2xpZW50XzEiXSwgImV"
            "4cCI6IDE1NzIwOTk5NjAsICJhY3IiOiAiMiIsICJpYXQiOiAxNTcyMDEzNTYwLCAibm9uY2UiOiAibmdFTGZVdmN"
            "PMWoyaXNWcXkwQWNwM0NOYlZnMGdFRDEifQ.aaa")
        with responses.RequestsMock() as rsps:
            rsps.add(
                responses.GET,
                "https://example.com/authorization",
                status=302,
                headers={"location": location},
            )
            result = self.consumer.do_authorization_request(state=_state,
                                                            request_args=args)
        self.consumer._backup("state0")

        assert result.status_code == 302
        query = urlparse(result.headers["location"]).query
        with pytest.raises(BadSignature):
            self.consumer.parse_authz(query=query)

    def test_get_session_management_id(self):
        now = utc_time_sans_frac()
        smid = "session_management_id"
        idval = {
            "nonce": "KUEYfRM2VzKDaaKD",
            "sub": "EndUserSubject",
            "iss": "https://example.com",
            "exp": now + 3600,
            "iat": now,
            "aud": self.consumer.client_id,
            "sid": smid,
        }
        idts = IdToken(**idval)

        _signed_jwt = idts.to_jwt(key=KC_RSA.keys(), algorithm="RS256")

        _state = "state"
        self.consumer.sdb[_state] = {
            "redirect_uris": ["https://example.org/cb"]
        }
        resp = AuthorizationResponse(id_token=_signed_jwt, state=_state)
        self.consumer.consumer_config["response_type"] = ["id_token"]
        self.consumer.parse_authz(resp.to_urlencoded())
        assert self.consumer.sso_db["state"]["smid"] == smid
        assert session_get(self.consumer.sso_db, "smid", smid) == [_state]
Exemple #17
0
class TestOICConsumer:
    @pytest.fixture(autouse=True)
    def setup_consumer(self, session_db_factory):
        client_id = "client_1"
        client_config = {
            "client_id": client_id,
            "client_authn_method": CLIENT_AUTHN_METHOD,
        }

        self.consumer = Consumer(
            session_db_factory(SERVER_INFO["issuer"]),
            CONFIG,
            client_config,
            SERVER_INFO,
        )
        self.consumer.behaviour = {
            "request_object_signing_alg": DEF_SIGN_ALG["openid_request_object"]
        }
        self.consumer.keyjar = CLIKEYS
        self.consumer.redirect_uris = ["https://example.com/cb"]
        self.consumer.authorization_endpoint = "https://example.com/authorization"
        self.consumer.token_endpoint = "https://example.com/token"
        self.consumer.userinfo_endpoint = "https://example.com/userinfo"
        self.consumer.client_secret = "hemlig"
        self.consumer.secret_type = "basic"

    def test_backup_keys(self):
        keys = self.consumer.__dict__.keys()
        _dict = self.consumer.dictionary()
        dkeys = [key for key in keys if key not in _dict.keys()]
        assert _eq(dkeys, IGNORE)

    def test_backup_restore(self):
        authz_org_url = "http://example.org/authorization"

        _dict = sorted(list(self.consumer.__dict__.items()))

        self.consumer._backup("sid")
        self.consumer.restore("sid")
        assert sorted(_dict) == sorted(list(self.consumer.__dict__.items()))

        self.consumer.authorization_endpoint = authz_org_url
        assert _dict != sorted(list(self.consumer.__dict__.items()))

        self.consumer.restore("sid")
        assert _dict == sorted(list(self.consumer.__dict__.items()))

    def test_backup_restore_update(self):
        authz_org_url = "http://example.org/authorization"

        self.consumer._backup("sid")

        self.consumer.authorization_endpoint = authz_org_url
        self.consumer.token_endpoint = "https://example.org/token"
        self.consumer.userinfo_endpoint = ""

        assert self.consumer.authorization_endpoint == authz_org_url
        assert self.consumer.token_endpoint == "https://example.org/token"
        assert self.consumer.userinfo_endpoint == ""

        self.consumer.update("sid")

        assert self.consumer.authorization_endpoint == authz_org_url
        assert self.consumer.token_endpoint == "https://example.org/token"
        assert self.consumer.userinfo_endpoint == "https://example.com/userinfo"

    def test_begin(self):
        srv = Server()
        srv.keyjar = SRVKEYS
        sid, location = self.consumer.begin("openid", "code")
        authreq = srv.parse_authorization_request(url=location)
        assert _eq(
            list(authreq.keys()),
            [
                "state",
                "max_age",
                "claims",
                "response_type",
                "client_id",
                "scope",
                "redirect_uri",
            ],
        )

        assert authreq["state"] == sid
        assert authreq["scope"] == self.consumer.consumer_config["scope"]
        assert authreq["client_id"] == self.consumer.client_id

    def test_begin_file(self, tmpdir):
        path = tmpdir.strpath
        external_path = "/exported"
        self.consumer.consumer_config["request_method"] = "file"
        self.consumer.consumer_config["temp_dir"] = path
        self.consumer.consumer_config["temp_path"] = external_path
        self.consumer.consumer_config["authz_page"] = "/authz"
        srv = Server()
        srv.keyjar = SRVKEYS

        sid, location = self.consumer.begin(
            "openid", "code", path="http://*****:*****@example.com",
                    "nickname": "Ilja",
                    "verified": True,
                },
            )

            result = self.consumer.do_authorization_request(
                state=_state, request_args=args
            )
            parsed = urlparse(result.headers["location"])

            self.consumer.parse_response(
                AuthorizationResponse, info=parsed.query, sformat="urlencoded"
            )

            self.consumer.complete(_state)

            result = self.consumer.get_user_info(_state)
        assert isinstance(result, OpenIDSchema)
        assert _eq(result.keys(), ["name", "email", "verified", "nickname", "sub"])

    def test_sign_userinfo(self):
        _state = "state0"
        self.consumer.client_prefs = {"userinfo_signed_response_alg": "RS256"}
        del self.consumer.consumer_config["request_method"]

        args = {
            "client_id": self.consumer.client_id,
            "response_type": "code",
            "scope": ["openid"],
        }

        location = "https://example.com/cb?code=code&state=state0"
        with responses.RequestsMock() as rsps:
            rsps.add(
                responses.GET,
                "https://example.com/authorization",
                status=302,
                headers={"location": location},
            )
            rsps.add(
                responses.POST,
                "https://example.com/token",
                content_type="application/json",
                json={
                    "access_token": "some_token",
                    "token_type": "bearer",
                    "state": "state0",
                    "scope": "openid",
                },
            )
            rsps.add(
                responses.POST,
                "https://example.com/userinfo",
                content_type="application/json",
                json={
                    "name": "Ilja",
                    "sub": "some_sub",
                    "email": "*****@*****.**",
                    "nickname": "Ilja",
                    "verified": True,
                },
            )
            self.consumer.begin("openid", "code")
            result = self.consumer.do_authorization_request(
                state=_state, request_args=args
            )
            parsed = urlparse(result.headers["location"])
            self.consumer.parse_response(
                AuthorizationResponse, info=parsed.query, sformat="urlencoded"
            )

            self.consumer.complete(_state)

            result = self.consumer.get_user_info(_state)
        assert isinstance(result, OpenIDSchema)
        assert _eq(result.keys(), ["name", "email", "verified", "nickname", "sub"])

    def test_get_userinfo_claims(self):
        _state = "state0"

        args = {
            "client_id": self.consumer.client_id,
            "response_type": "code",
            "scope": ["openid"],
        }

        location = "https://example.com/cb?code=code&state=state0"
        with responses.RequestsMock() as rsps:
            rsps.add(
                responses.GET,
                "https://example.com/authorization",
                status=302,
                headers={"location": location},
            )
            rsps.add(
                responses.POST,
                "https://example.com/token",
                content_type="application/json",
                json={
                    "access_token": "some_token",
                    "token_type": "bearer",
                    "state": "state0",
                    "scope": "openid",
                },
            )
            rsps.add(
                responses.POST,
                "https://example.com/userinfo",
                content_type="application/json",
                json={
                    "name": "Ilja",
                    "sub": "some_sub",
                    "email": "*****@*****.**",
                    "nickname": "Ilja",
                    "verified": True,
                },
            )

            result = self.consumer.do_authorization_request(
                state=_state, request_args=args
            )
            parsed = urlparse(result.headers["location"])
            self.consumer.parse_response(
                AuthorizationResponse, info=parsed.query, sformat="urlencoded"
            )
            response = self.consumer.complete(_state)
            result = self.consumer.get_userinfo_claims(
                response["access_token"], self.consumer.userinfo_endpoint
            )
        assert isinstance(result, OpenIDSchema)
        assert _eq(result.keys(), ["name", "email", "verified", "nickname", "sub"])

    def real_test_discover(self):
        c = Consumer(None, None)
        principal = "*****@*****.**"
        res = c.discover(principal)
        assert isinstance(res, ProviderConfigurationResponse)
        assert _eq(
            res.keys(),
            [
                "registration_endpoint",
                "scopes_supported",
                "identifiers_supported",
                "token_endpoint",
                "flows_supported",
                "version",
                "userinfo_endpoint",
                "authorization_endpoint",
                "x509_url",
                "issuer",
            ],
        )
        assert res.version == "3.0"  # type: ignore
        assert _eq(
            res.flows_supported,  # type: ignore
            [
                "code",
                "token",
                "id_token",
                "code token",
                "code id_token",
                "id_token token",
            ],
        )

    def test_discover(self):
        c = Consumer(None, None)
        webfinger = {
            "subject": "acct:[email protected]",
            "links": [
                {
                    "rel": "http://openid.net/specs/connect/1.0/issuer",
                    "href": "https://*****:*****@example.com"
        with responses.RequestsMock() as rsps:
            rsps.add(
                responses.GET,
                "https://example.com/.well-known/webfinger"
                "?resource=acct%3Afoo%40example.com&rel=http%3A%2F%2Fopenid.net%2Fspecs%2Fconnect%2F1.0%2Fissuer",
                json=webfinger,
            )
            res = c.discover(principal)
        assert res == "https://localhost:8088/"

    def test_client_register(self):
        c = Consumer(None, None)
        c.redirect_uris = ["https://example.com/authz"]
        reg_resp = {
            "client_id": "some_client",
            "client_secret": "super_secret",
            "client_secret_expires_at": 123456789,
            "redirect_uris": ["https://example.com/authz"],
        }
        with responses.RequestsMock() as rsps:
            rsps.add(responses.POST, "https://example.com/register/", json=reg_resp)
            c.register("https://example.com/register/")
            assert json.loads(rsps.calls[0].request.body) == {
                "application_type": "web",
                "response_types": ["code"],
                "redirect_uris": ["https://example.com/authz"],
                "grant_types": ["authorization_code"],
            }
        assert c.client_id == "some_client"
        assert c.client_secret == "super_secret"
        assert c.registration_expires == 123456789

    def test_client_register_token(self):
        c = Consumer(None, None)

        c.redirect_uris = ["https://example.com/authz"]

        client_info = {
            "client_id": "clientid",
            "redirect_uris": ["https://example.com/authz"],
        }

        with responses.RequestsMock() as rsps:
            rsps.add(
                rsps.POST,
                "https://provider.example.com/registration/",
                json=client_info,
            )
            c.register(
                "https://provider.example.com/registration/",
                registration_token="initial_registration_token",
            )
            header = rsps.calls[0].request.headers["Authorization"]
            assert header == "Bearer aW5pdGlhbF9yZWdpc3RyYXRpb25fdG9rZW4="

    def _faulty_id_token(self):
        idval = {
            "nonce": "KUEYfRM2VzKDaaKD",
            "sub": "EndUserSubject",
            "iss": "https://alpha.cloud.nds.rub.de",
            "exp": 1420823073,
            "iat": 1420822473,
            "aud": "TestClient",
        }
        idts = IdToken(**idval)

        _signed_jwt = idts.to_jwt(key=[SYMKey(key="TestPassword")], algorithm="HS256")

        # Mess with the signed id_token
        p = _signed_jwt.split(".")
        p[2] = "aaa"

        return ".".join(p)

    def test_faulty_id_token(self):
        _faulty_signed_jwt = self._faulty_id_token()

        with pytest.raises(BadSignature):
            IdToken().from_jwt(_faulty_signed_jwt, key=[SYMKey(key="TestPassword")])

        # What if no verification key is given ?
        # Should also result in an exception
        with pytest.raises(MissingSigningKey):
            IdToken().from_jwt(_faulty_signed_jwt)

    def test_faulty_id_token_in_access_token_response(self):
        c = Consumer(None, None)
        c.keyjar.add_symmetric("", "TestPassword", ["sig"])

        _info = {
            "access_token": "accessTok",
            "id_token": self._faulty_id_token(),
            "token_type": "Bearer",
        }

        _json = json.dumps(_info)
        with pytest.raises(ValueError):
            c.parse_response(AccessTokenResponse, _json, sformat="json")

    def test_faulty_idtoken_from_accesstoken_endpoint(self, mitm_server):
        mfos = mitm_server("http://localhost:8088")
        mfos.keyjar = SRVKEYS
        self.consumer.http_request = mfos.http_request
        _state = "state0"
        self.consumer.consumer_config["response_type"] = ["id_token"]

        args = {
            "client_id": self.consumer.client_id,
            "response_type": self.consumer.consumer_config["response_type"],
            "scope": ["openid"],
        }

        result = self.consumer.do_authorization_request(state=_state, request_args=args)
        self.consumer._backup("state0")

        assert result.status_code == 302
        query = urlparse(result.headers["location"]).query
        with pytest.raises(BadSignature):
            self.consumer.parse_authz(query=query)