예제 #1
0
class TestEndpoint(object):
    @pytest.fixture(autouse=True)
    def create_endpoint(self):
        conf = {
            "issuer": "https://example.com/",
            "password": "******",
            "token_expires_in": 600,
            "grant_expires_in": 300,
            "refresh_token_expires_in": 86400,
            "verify_ssl": False,
            "capabilities": CAPABILITIES,
            "jwks": {
                "uri_path": "static/jwks.json",
                "key_defs": KEYDEFS
            },
            "id_token": {
                "class": IDToken,
                "kwargs": {
                    "default_claims": {
                        "email": {
                            "essential": True
                        },
                        "email_verified": {
                            "essential": True
                        },
                    }
                },
            },
            "endpoint": {
                "authorization": {
                    "path": "{}/authorization",
                    "class": Authorization,
                    "kwargs": {
                        "response_types_supported":
                        [" ".join(x) for x in RESPONSE_TYPES_SUPPORTED],
                        "response_modes_supported":
                        ["query", "fragment", "form_post"],
                        "claims_parameter_supported":
                        True,
                        "request_parameter_supported":
                        True,
                        "request_uri_parameter_supported":
                        True,
                        "request_cls":
                        JWTSecuredAuthorizationRequest,
                    },
                }
            },
            "authentication": {
                "anon": {
                    "acr": "http://www.swamid.se/policy/assurance/al1",
                    "class": "oidcendpoint.user_authn.user.NoAuthn",
                    "kwargs": {
                        "user": "******"
                    },
                }
            },
            "userinfo": {
                "class": UserInfo,
                "kwargs": {
                    "db": USERINFO_db
                }
            },
            "template_dir": "template",
            "cookie_dealer": {
                "class": CookieDealer,
                "kwargs": {
                    "sign_key":
                    "ghsNKDDLshZTPn974nOsIGhedULrsqnsGoBFBLwUKuJhE2ch",
                    "default_values": {
                        "name": "oidcop",
                        "domain": "127.0.0.1",
                        "path": "/",
                        "max_age": 3600,
                    },
                },
            },
        }
        endpoint_context = EndpointContext(conf)
        _clients = yaml.safe_load(io.StringIO(client_yaml))
        endpoint_context.cdb = _clients["clients"]
        endpoint_context.keyjar.import_jwks(
            endpoint_context.keyjar.export_jwks(True, ""), conf["issuer"])
        self.endpoint = endpoint_context.endpoint["authorization"]

        self.rp_keyjar = KeyJar()
        self.rp_keyjar.add_symmetric("client_1", "hemligtkodord1234567890")
        self.endpoint.endpoint_context.keyjar.add_symmetric(
            "client_1", "hemligtkodord1234567890")

    def test_parse_request_parameter(self):
        _jwt = JWT(key_jar=self.rp_keyjar, iss="client_1", sign_alg="HS256")
        _jws = _jwt.pack(
            AUTH_REQ_DICT,
            aud=self.endpoint.endpoint_context.provider_info["issuer"])
        # -----------------
        _req = self.endpoint.parse_request({
            "request":
            _jws,
            "redirect_uri":
            AUTH_REQ.get("redirect_uri"),
            "response_type":
            AUTH_REQ.get("response_type"),
            "client_id":
            AUTH_REQ.get("client_id"),
            "scope":
            AUTH_REQ.get("scope"),
        })
        assert "__verified_request" in _req

    def test_parse_request_uri(self):
        _jwt = JWT(key_jar=self.rp_keyjar, iss="client_1", sign_alg="HS256")
        _jws = _jwt.pack(
            AUTH_REQ_DICT,
            aud=self.endpoint.endpoint_context.provider_info["issuer"])

        request_uri = "https://client.example.com/req"
        # -----------------
        with responses.RequestsMock() as rsps:
            rsps.add("GET", request_uri, body=_jws, status=200)
            _req = self.endpoint.parse_request({
                "request_uri":
                request_uri,
                "redirect_uri":
                AUTH_REQ.get("redirect_uri"),
                "response_type":
                AUTH_REQ.get("response_type"),
                "client_id":
                AUTH_REQ.get("client_id"),
                "scope":
                AUTH_REQ.get("scope"),
            })

        assert "__verified_request" in _req
예제 #2
0
class TestUserAuthn(object):
    @pytest.fixture(autouse=True)
    def create_endpoint_context(self):
        conf = {
            "issuer": "https://example.com/",
            "password": "******",
            "token_expires_in": 600,
            "grant_expires_in": 300,
            "refresh_token_expires_in": 86400,
            "verify_ssl": False,
            "endpoint": {
                "authorization": {
                    "path": "{}/authorization",
                    "class": Authorization,
                    "kwargs": {
                        "response_types_supported": [" ".join(x) for x in RESPONSE_TYPES_SUPPORTED],
                        "response_modes_supported": ["query", "fragment", "form_post"],
                        "claims_parameter_supported": True,
                        "request_parameter_supported": True,
                        "request_uri_parameter_supported": True,
                    },
                }
            },
            "keys": {"uri_path": "static/jwks.json", "key_defs": KEYDEFS},
            "authentication": {
                "anon": {"acr": UNSPECIFIED, "class": NoAuthn, "kwargs": {"user": "******"},},
            },
            "cookie_handler": {
                "class": "oidcop.cookie_handler.CookieHandler",
                "kwargs": {
                    "sign_key": "ghsNKDDLshZTPn974nOsIGhedULrsqnsGoBFBLwUKuJhE2ch",
                    "name": {
                        "session": "oidc_op",
                        "register": "oidc_op_reg",
                        "session_management": "oidc_op_sman",
                    },
                },
            },
            "template_dir": "template",
        }
        server = Server(OPConfiguration(conf=conf, base_path=BASEDIR), cwd=BASEDIR)

        endpoint_context = server.endpoint_context
        _clients = yaml.safe_load(io.StringIO(client_yaml))
        endpoint_context.cdb = _clients["oidc_clients"]
        endpoint_context.keyjar.import_jwks(
            endpoint_context.keyjar.export_jwks(True, ""), conf["issuer"]
        )
        self.endpoint = server.server_get("endpoint", "authorization")

        self.rp_keyjar = KeyJar()
        self.rp_keyjar.add_symmetric("client_1", "hemligtkodord1234567890")
        endpoint_context.keyjar.add_symmetric("client_1", "hemligtkodord1234567890")

    def test_sso(self):
        request = self.endpoint.parse_request(AUTH_REQ_DICT)
        redirect_uri = request["redirect_uri"]
        cinfo = self.endpoint.server_get("endpoint_context").cdb[request["client_id"]]
        info = self.endpoint.setup_auth(request, redirect_uri, cinfo, cookie=None)
        # info = self.endpoint.process_request(request)

        assert "user" in info

        res = self.endpoint.authz_part2(request, info["session_id"], cookie="")
        assert res
        cookies_1 = res["cookie"]

        # second login - from 2nd client
        request = self.endpoint.parse_request(AUTH_REQ_2.to_dict())
        redirect_uri = request["redirect_uri"]
        cinfo = self.endpoint.server_get("endpoint_context").cdb[request["client_id"]]
        info = self.endpoint.setup_auth(request, redirect_uri, cinfo, cookie=None)
        sid2 = info["session_id"]

        assert set(info.keys()) == {"session_id", "identity", "user"}
        assert info["user"] == "diana"

        res = self.endpoint.authz_part2(request, info["session_id"], cookie="")
        cookies_2 = res["cookie"]

        # third login - from 3rd client
        request = self.endpoint.parse_request(AUTH_REQ_3.to_dict())
        redirect_uri = request["redirect_uri"]
        cinfo = self.endpoint.server_get("endpoint_context").cdb[request["client_id"]]
        info = self.endpoint.setup_auth(request, redirect_uri, cinfo, cookie=None)

        assert set(info.keys()) == {"session_id", "identity", "user"}
        assert info["user"] == "diana"

        res = self.endpoint.authz_part2(request, info["session_id"], cookie="")
        cookies_3 = res["cookie"]

        # fourth login - from 1st client
        request = self.endpoint.parse_request(AUTH_REQ_4.to_dict())
        redirect_uri = request["redirect_uri"]
        cinfo = self.endpoint.server_get("endpoint_context").cdb[request["client_id"]]
        info = self.endpoint.setup_auth(request, redirect_uri, cinfo, cookie=cookies_1)

        assert set(info.keys()) == {"session_id", "identity", "user"}
        assert info["user"] == "diana"

        self.endpoint.authz_part2(request, info["session_id"], cookie="")

        # Fifth login - from 2nd client - wrong cookie
        request = self.endpoint.parse_request(AUTH_REQ_2.to_dict())
        redirect_uri = request["redirect_uri"]
        cinfo = self.endpoint.server_get("endpoint_context").cdb[request["client_id"]]
        info = self.endpoint.setup_auth(request, redirect_uri, cinfo, cookie=cookies_1)
        # No valid login cookie so new session
        assert info["session_id"] != sid2

        user_session_info = self.endpoint.server_get("endpoint_context").session_manager.get(
            ["diana"]
        )
        assert len(user_session_info.subordinate) == 3
        assert set(user_session_info.subordinate) == {
            "client_1",
            "client_2",
            "client_3",
        }

        # Should be one grant for each of client_2 and client_3 and
        # 2 grants for client_1

        csi1 = self.endpoint.server_get("endpoint_context").session_manager.get(
            ["diana", "client_1"]
        )
        csi2 = self.endpoint.server_get("endpoint_context").session_manager.get(
            ["diana", "client_2"]
        )
        csi3 = self.endpoint.server_get("endpoint_context").session_manager.get(
            ["diana", "client_3"]
        )

        assert len(csi1.subordinate) == 2
        assert len(csi2.subordinate) == 1
        assert len(csi3.subordinate) == 1
예제 #3
0
class TestEndpoint(object):
    @pytest.fixture(autouse=True)
    def create_endpoint(self):
        conf = {
            "issuer": "https://example.com/",
            "password": "******",
            "token_expires_in": 600,
            "grant_expires_in": 300,
            "refresh_token_expires_in": 86400,
            "verify_ssl": False,
            "capabilities": CAPABILITIES,
            "jwks": {"uri_path": "static/jwks.json", "key_defs": KEYDEFS},
            "id_token": {
                "class": IDToken,
                "kwargs": {
                    "default_claims": {
                        "email": {"essential": True},
                        "email_verified": {"essential": True},
                    }
                },
            },
            "endpoint": {
                "authorization": {
                    "path": "{}/authorization",
                    "class": Authorization,
                    "kwargs": {
                        "response_types_supported": [
                            " ".join(x) for x in RESPONSE_TYPES_SUPPORTED
                        ],
                        "response_modes_supported": ["query", "fragment", "form_post"],
                        "claims_parameter_supported": True,
                        "request_parameter_supported": True,
                        "request_uri_parameter_supported": True,
                    },
                }
            },
            "authentication": {
                "anon": {
                    "acr": "http://www.swamid.se/policy/assurance/al1",
                    "class": "oidcendpoint.user_authn.user.NoAuthn",
                    "kwargs": {"user": "******"},
                }
            },
            "userinfo": {"class": UserInfo, "kwargs": {"db": USERINFO_db}},
            "template_dir": "template",
            "cookie_dealer": {
                "class": CookieDealer,
                "kwargs": {
                    "sign_key": "ghsNKDDLshZTPn974nOsIGhedULrsqnsGoBFBLwUKuJhE2ch",
                    "default_values": {
                        "name": "oidcop",
                        "domain": "127.0.0.1",
                        "path": "/",
                        "max_age": 3600,
                    },
                },
            },
        }
        endpoint_context = EndpointContext(conf)
        _clients = yaml.safe_load(io.StringIO(client_yaml))
        endpoint_context.cdb = _clients["clients"]
        endpoint_context.keyjar.import_jwks(
            endpoint_context.keyjar.export_jwks(True, ""), conf["issuer"]
        )
        self.endpoint = endpoint_context.endpoint["authorization"]

        self.rp_keyjar = KeyJar()
        self.rp_keyjar.add_symmetric("client_1", "hemligtkodord1234567890")
        self.endpoint.endpoint_context.keyjar.add_symmetric(
            "client_1", "hemligtkodord1234567890"
        )

    def test_init(self):
        assert self.endpoint

    def test_parse(self):
        _req = self.endpoint.parse_request(AUTH_REQ_DICT)

        assert isinstance(_req, AuthorizationRequest)
        assert set(_req.keys()) == set(AUTH_REQ.keys())

    def test_process_request(self):
        _pr_resp = self.endpoint.parse_request(AUTH_REQ_DICT)
        _resp = self.endpoint.process_request(_pr_resp)
        assert set(_resp.keys()) == {
            "response_args",
            "fragment_enc",
            "return_uri",
            "cookie",
        }

    def test_do_response_code(self):
        _pr_resp = self.endpoint.parse_request(AUTH_REQ_DICT)
        _resp = self.endpoint.process_request(_pr_resp)
        msg = self.endpoint.do_response(**_resp)
        assert isinstance(msg, dict)
        _msg = parse_qs(msg["response"])
        assert _msg
        part = urlparse(msg["response"])
        assert part.fragment == ""
        assert part.query
        _query = parse_qs(part.query)
        assert _query
        assert "code" in _query

    def test_do_response_code_token(self):
        _orig_req = AUTH_REQ_DICT.copy()
        _orig_req["response_type"] = "code token"
        _pr_resp = self.endpoint.parse_request(_orig_req)
        _resp = self.endpoint.process_request(_pr_resp)
        msg = self.endpoint.do_response(response_msg=_resp)
        assert isinstance(msg, dict)
        assert msg["response"]["error"] == "invalid_request"

    def test_verify_uri_unknown_client(self):
        request = {"redirect_uri": "https://rp.example.com/cb"}
        with pytest.raises(UnknownClient):
            verify_uri(self.endpoint.endpoint_context, request, "redirect_uri")

    def test_verify_uri_fragment(self):
        _ec = self.endpoint.endpoint_context
        _ec.cdb["client_id"] = {"redirect_uri": ["https://rp.example.com/auth_cb"]}
        request = {"redirect_uri": "https://rp.example.com/cb#foobar"}
        with pytest.raises(URIError):
            verify_uri(_ec, request, "redirect_uri", "client_id")

    def test_verify_uri_noregistered(self):
        _ec = self.endpoint.endpoint_context
        request = {"redirect_uri": "https://rp.example.com/cb"}

        with pytest.raises(ValueError):
            verify_uri(_ec, request, "redirect_uri", "client_id")

    def test_verify_uri_unregistered(self):
        _ec = self.endpoint.endpoint_context
        _ec.cdb["client_id"] = {
            "redirect_uris": [("https://rp.example.com/auth_cb", {})]
        }

        request = {"redirect_uri": "https://rp.example.com/cb"}

        with pytest.raises(RedirectURIError):
            verify_uri(_ec, request, "redirect_uri", "client_id")

    def test_verify_uri_qp_match(self):
        _ec = self.endpoint.endpoint_context
        _ec.cdb["client_id"] = {
            "redirect_uris": [("https://rp.example.com/cb", {"foo": ["bar"]})]
        }

        request = {"redirect_uri": "https://rp.example.com/cb?foo=bar"}

        verify_uri(_ec, request, "redirect_uri", "client_id")

    def test_verify_uri_qp_mismatch(self):
        _ec = self.endpoint.endpoint_context
        _ec.cdb["client_id"] = {
            "redirect_uris": [("https://rp.example.com/cb", {"foo": ["bar"]})]
        }

        request = {"redirect_uri": "https://rp.example.com/cb?foo=bob"}
        with pytest.raises(ValueError):
            verify_uri(_ec, request, "redirect_uri", "client_id")

        request = {"redirect_uri": "https://rp.example.com/cb?foo=bar&foo=kex"}
        with pytest.raises(ValueError):
            verify_uri(_ec, request, "redirect_uri", "client_id")

        request = {"redirect_uri": "https://rp.example.com/cb"}
        with pytest.raises(ValueError):
            verify_uri(_ec, request, "redirect_uri", "client_id")

        request = {"redirect_uri": "https://rp.example.com/cb?foo=bar&level=low"}
        with pytest.raises(ValueError):
            verify_uri(_ec, request, "redirect_uri", "client_id")

    def test_verify_uri_qp_missing(self):
        _ec = self.endpoint.endpoint_context
        _ec.cdb["client_id"] = {
            "redirect_uris": [
                ("https://rp.example.com/cb", {"foo": ["bar"], "state": ["low"]})
            ]
        }

        request = {"redirect_uri": "https://rp.example.com/cb?foo=bar"}
        with pytest.raises(ValueError):
            verify_uri(_ec, request, "redirect_uri", "client_id")

    def test_verify_uri_qp_missing_val(self):
        _ec = self.endpoint.endpoint_context
        _ec.cdb["client_id"] = {
            "redirect_uris": [("https://rp.example.com/cb", {"foo": ["bar", "low"]})]
        }

        request = {"redirect_uri": "https://rp.example.com/cb?foo=bar"}
        with pytest.raises(ValueError):
            verify_uri(_ec, request, "redirect_uri", "client_id")

    def test_verify_uri_no_registered_qp(self):
        _ec = self.endpoint.endpoint_context
        _ec.cdb["client_id"] = {"redirect_uris": [("https://rp.example.com/cb", {})]}

        request = {"redirect_uri": "https://rp.example.com/cb?foo=bob"}
        with pytest.raises(ValueError):
            verify_uri(_ec, request, "redirect_uri", "client_id")

    def test_get_uri(self):
        _ec = self.endpoint.endpoint_context
        _ec.cdb["client_id"] = {"redirect_uris": [("https://rp.example.com/cb", {})]}

        request = {
            "redirect_uri": "https://rp.example.com/cb",
            "client_id": "client_id",
        }

        assert get_uri(_ec, request, "redirect_uri") == "https://rp.example.com/cb"

    def test_get_uri_no_redirect_uri(self):
        _ec = self.endpoint.endpoint_context
        _ec.cdb["client_id"] = {"redirect_uris": [("https://rp.example.com/cb", {})]}

        request = {"client_id": "client_id"}

        assert get_uri(_ec, request, "redirect_uri") == "https://rp.example.com/cb"

    def test_get_uri_no_registered(self):
        _ec = self.endpoint.endpoint_context
        _ec.cdb["client_id"] = {"redirect_uris": [("https://rp.example.com/cb", {})]}

        request = {"client_id": "client_id"}

        with pytest.raises(ParameterError):
            get_uri(_ec, request, "post_logout_redirect_uri")

    def test_get_uri_more_then_one_registered(self):
        _ec = self.endpoint.endpoint_context
        _ec.cdb["client_id"] = {
            "redirect_uris": [
                ("https://rp.example.com/cb", {}),
                ("https://rp.example.org/authz_cb", {"foo": "bar"}),
            ]
        }

        request = {"client_id": "client_id"}

        with pytest.raises(ParameterError):
            get_uri(_ec, request, "redirect_uri")

    def test_create_authn_response(self):
        request = AuthorizationRequest(
            client_id="client_id",
            redirect_uri="https://rp.example.com/cb",
            response_type=["id_token"],
            state="state",
            nonce="nonce",
            scope="openid",
        )

        _ec = self.endpoint.endpoint_context
        _ec.sdb["session_id"] = SessionInfo(
            authn_req=request,
            uid="diana",
            sub="abcdefghijkl",
            authn_event={
                "authn_info": "loa1",
                "uid": "diana",
                "authn_time": utc_time_sans_frac(),
            },
        )
        _ec.cdb["client_id"] = {
            "client_id": "client_id",
            "redirect_uris": [("https://rp.example.com/cb", {})],
            "id_token_signed_response_alg": "ES256",
        }

        resp = create_authn_response(self.endpoint, request, "session_id")
        assert isinstance(resp["response_args"], AuthorizationErrorResponse)

    def test_setup_auth(self):
        request = AuthorizationRequest(
            client_id="client_id",
            redirect_uri="https://rp.example.com/cb",
            response_type=["id_token"],
            state="state",
            nonce="nonce",
            scope="openid",
        )
        redirect_uri = request["redirect_uri"]
        cinfo = {
            "client_id": "client_id",
            "redirect_uris": [("https://rp.example.com/cb", {})],
            "id_token_signed_response_alg": "RS256",
        }

        kaka = self.endpoint.endpoint_context.cookie_dealer.create_cookie(
            "value", "sso"
        )

        res = self.endpoint.setup_auth(request, redirect_uri, cinfo, kaka)
        assert set(res.keys()) == {"authn_event", "identity", "user"}

    def test_setup_auth_error(self):
        request = AuthorizationRequest(
            client_id="client_id",
            redirect_uri="https://rp.example.com/cb",
            response_type=["id_token"],
            state="state",
            nonce="nonce",
            scope="openid",
        )
        redirect_uri = request["redirect_uri"]
        cinfo = {
            "client_id": "client_id",
            "redirect_uris": [("https://rp.example.com/cb", {})],
            "id_token_signed_response_alg": "RS256",
        }

        item = self.endpoint.endpoint_context.authn_broker.db["anon"]
        item["method"].fail = NoSuchAuthentication

        res = self.endpoint.setup_auth(request, redirect_uri, cinfo, None)
        assert set(res.keys()) == {"function", "args"}

        item["method"].fail = ToOld

        res = self.endpoint.setup_auth(request, redirect_uri, cinfo, None)
        assert set(res.keys()) == {"function", "args"}

        item["method"].file = ""

    def test_setup_auth_user(self):
        request = AuthorizationRequest(
            client_id="client_id",
            redirect_uri="https://rp.example.com/cb",
            response_type=["id_token"],
            state="state",
            nonce="nonce",
            scope="openid",
        )
        redirect_uri = request["redirect_uri"]
        cinfo = {
            "client_id": "client_id",
            "redirect_uris": [("https://rp.example.com/cb", {})],
            "id_token_signed_response_alg": "RS256",
        }
        _ec = self.endpoint.endpoint_context
        _ec.sdb["session_id"] = SessionInfo(
            authn_req=request,
            uid="diana",
            sub="abcdefghijkl",
            authn_event={
                "authn_info": "loa1",
                "uid": "diana",
                "authn_time": utc_time_sans_frac(),
            },
        )

        item = _ec.authn_broker.db["anon"]
        item["method"].user = b64e(
            as_bytes(json.dumps({"uid": "krall", "sid": "session_id"}))
        )

        res = self.endpoint.setup_auth(request, redirect_uri, cinfo, None)
        assert set(res.keys()) == {"authn_event", "identity", "user"}
        assert res["identity"]["uid"] == "krall"

    def test_setup_auth_session_revoked(self):
        request = AuthorizationRequest(
            client_id="client_id",
            redirect_uri="https://rp.example.com/cb",
            response_type=["id_token"],
            state="state",
            nonce="nonce",
            scope="openid",
        )
        redirect_uri = request["redirect_uri"]
        cinfo = {
            "client_id": "client_id",
            "redirect_uris": [("https://rp.example.com/cb", {})],
            "id_token_signed_response_alg": "RS256",
        }
        _ec = self.endpoint.endpoint_context
        _ec.sdb["session_id"] = SessionInfo(
            authn_req=request,
            uid="diana",
            sub="abcdefghijkl",
            authn_event={
                "authn_info": "loa1",
                "uid": "diana",
                "authn_time": utc_time_sans_frac(),
            },
            revoked=True,
        )

        item = _ec.authn_broker.db["anon"]
        item["method"].user = b64e(
            as_bytes(json.dumps({"uid": "krall", "sid": "session_id"}))
        )

        res = self.endpoint.setup_auth(request, redirect_uri, cinfo, None)
        assert set(res.keys()) == {"args", "function"}

    def test_response_mode_form_post(self):
        request = {"response_mode": "form_post"}
        info = {
            "response_args": AuthorizationResponse(foo="bar"),
            "return_uri": "https://example.com/cb",
        }
        info = self.endpoint.response_mode(request, **info)
        assert set(info.keys()) == {"response_args", "return_uri", "response_msg",
                                    "content_type", "response_placement"}
        assert info["response_msg"] == FORM_POST.format(
            action="https://example.com/cb",
            inputs='<input type="hidden" name="foo" value="bar"/>',
        )

    def test_response_mode_fragment(self):
        request = {"response_mode": "fragment"}
        self.endpoint.response_mode(request, fragment_enc=True)

        with pytest.raises(InvalidRequest):
            self.endpoint.response_mode(request, fragment_enc=False)

        info = self.endpoint.response_mode(request)
        assert set(info.keys()) == {"fragment_enc"}
예제 #4
0
class TestEndpoint(object):
    @pytest.fixture(autouse=True)
    def create_endpoint(self):
        conf = {
            "issuer": "https://example.com/",
            "password": "******",
            "token_expires_in": 600,
            "grant_expires_in": 300,
            "refresh_token_expires_in": 86400,
            "verify_ssl": False,
            "capabilities": CAPABILITIES,
            "jwks": {
                "uri_path": "static/jwks.json",
                "key_defs": KEYDEFS
            },
            "id_token": {
                "class": IDToken,
                "kwargs": {
                    "default_claims": {
                        "email": {
                            "essential": True
                        },
                        "email_verified": {
                            "essential": True
                        },
                    }
                },
            },
            "endpoint": {
                "provider_config": {
                    "path": "{}/.well-known/openid-configuration",
                    "class": ProviderConfiguration,
                    "kwargs": {},
                },
                "registration": {
                    "path": "{}/registration",
                    "class": Registration,
                    "kwargs": {},
                },
                "authorization": {
                    "path": "{}/authorization",
                    "class": Authorization,
                    "kwargs": {
                        "response_types_supported":
                        [" ".join(x) for x in RESPONSE_TYPES_SUPPORTED],
                        "response_modes_supported":
                        ["query", "fragment", "form_post"],
                        "claims_parameter_supported":
                        True,
                        "request_parameter_supported":
                        True,
                        "request_uri_parameter_supported":
                        True,
                    },
                },
                "token": {
                    "path": "token",
                    "class": AccessToken,
                    "kwargs": {
                        "client_authn_method": [
                            "client_secret_post",
                            "client_secret_basic",
                            "client_secret_jwt",
                            "private_key_jwt",
                        ]
                    },
                },
                "userinfo": {
                    "path": "userinfo",
                    "class": userinfo.UserInfo,
                    "kwargs": {
                        "db_file":
                        "users.json",
                        "claim_types_supported": [
                            "normal",
                            "aggregated",
                            "distributed",
                        ],
                    },
                },
            },
            "authentication": {
                "anon": {
                    "acr": "http://www.swamid.se/policy/assurance/al1",
                    "class": "oidcendpoint.user_authn.user.NoAuthn",
                    "kwargs": {
                        "user": "******"
                    },
                }
            },
            "userinfo": {
                "class": UserInfo,
                "kwargs": {
                    "db": USERINFO_db
                }
            },
            "template_dir": "template",
            "cookie_dealer": {
                "class": CookieDealer,
                "kwargs": {
                    "sign_key":
                    "ghsNKDDLshZTPn974nOsIGhedULrsqnsGoBFBLwUKuJhE2ch",
                    "default_values": {
                        "name": "oidcop",
                        "domain": "127.0.0.1",
                        "path": "/",
                        "max_age": 3600,
                    },
                },
            },
            "login_hint2acrs": {
                "class": LoginHint2Acrs,
                "kwargs": {
                    "scheme_map": {
                        "email": [INTERNETPROTOCOLPASSWORD]
                    }
                },
            },
        }
        endpoint_context = EndpointContext(conf)
        _clients = yaml.safe_load(io.StringIO(client_yaml))
        endpoint_context.cdb = _clients["oidc_clients"]
        endpoint_context.keyjar.import_jwks(
            endpoint_context.keyjar.export_jwks(True, ""), conf["issuer"])
        self.endpoint = endpoint_context.endpoint["authorization"]

        self.rp_keyjar = KeyJar()
        self.rp_keyjar.add_symmetric("client_1", "hemligtkodord1234567890")
        self.endpoint.endpoint_context.keyjar.add_symmetric(
            "client_1", "hemligtkodord1234567890")

    def test_init(self):
        assert self.endpoint

    def test_parse(self):
        _req = self.endpoint.parse_request(AUTH_REQ_DICT)

        assert isinstance(_req, AuthorizationRequest)
        assert set(_req.keys()) == set(AUTH_REQ.keys())

    def test_process_request(self):
        _pr_resp = self.endpoint.parse_request(AUTH_REQ_DICT)
        _resp = self.endpoint.process_request(_pr_resp)
        assert set(_resp.keys()) == {
            "response_args",
            "fragment_enc",
            "return_uri",
            "cookie",
        }

    def test_do_response_code(self):
        _pr_resp = self.endpoint.parse_request(AUTH_REQ_DICT)
        _resp = self.endpoint.process_request(_pr_resp)
        msg = self.endpoint.do_response(**_resp)
        assert isinstance(msg, dict)
        _msg = parse_qs(msg["response"])
        assert _msg
        part = urlparse(msg["response"])
        assert part.fragment == ""
        assert part.query
        _query = parse_qs(part.query)
        assert _query
        assert "code" in _query

    def test_do_response_id_token_no_nonce(self):
        _orig_req = AUTH_REQ_DICT.copy()
        _orig_req["response_type"] = "id_token"
        _pr_resp = self.endpoint.parse_request(_orig_req)
        # Missing nonce
        assert isinstance(_pr_resp, ResponseMessage)

    def test_do_response_id_token(self):
        _orig_req = AUTH_REQ_DICT.copy()
        _orig_req["response_type"] = "id_token"
        _orig_req["nonce"] = "rnd_nonce"
        _pr_resp = self.endpoint.parse_request(_orig_req)
        _resp = self.endpoint.process_request(_pr_resp)
        msg = self.endpoint.do_response(**_resp)
        assert isinstance(msg, dict)
        part = urlparse(msg["response"])
        assert part.query == ""
        assert part.fragment
        _frag_msg = parse_qs(part.fragment)
        assert _frag_msg
        assert "id_token" in _frag_msg
        assert "code" not in _frag_msg
        assert "token" not in _frag_msg

    def test_do_response_id_token_token(self):
        _orig_req = AUTH_REQ_DICT.copy()
        _orig_req["response_type"] = "id_token token"
        _orig_req["nonce"] = "rnd_nonce"
        _pr_resp = self.endpoint.parse_request(_orig_req)
        _resp = self.endpoint.process_request(_pr_resp)
        msg = self.endpoint.do_response(response_msg=_resp)
        assert isinstance(msg, dict)
        assert msg["response"]["error"] == "invalid_request"

    def test_do_response_code_token(self):
        _orig_req = AUTH_REQ_DICT.copy()
        _orig_req["response_type"] = "code token"
        _pr_resp = self.endpoint.parse_request(_orig_req)
        _resp = self.endpoint.process_request(_pr_resp)
        msg = self.endpoint.do_response(response_msg=_resp)
        assert isinstance(msg, dict)
        assert msg["response"]["error"] == "invalid_request"

    def test_do_response_code_id_token(self):
        _orig_req = AUTH_REQ_DICT.copy()
        _orig_req["response_type"] = "code id_token"
        _orig_req["nonce"] = "rnd_nonce"
        _pr_resp = self.endpoint.parse_request(_orig_req)
        _resp = self.endpoint.process_request(_pr_resp)
        msg = self.endpoint.do_response(**_resp)
        assert isinstance(msg, dict)
        part = urlparse(msg["response"])
        assert part.query == ""
        assert part.fragment
        _frag_msg = parse_qs(part.fragment)
        assert _frag_msg
        assert "id_token" in _frag_msg
        assert "code" in _frag_msg
        assert "access_token" not in _frag_msg

    def test_do_response_code_id_token_token(self):
        _orig_req = AUTH_REQ_DICT.copy()
        _orig_req["response_type"] = "code id_token token"
        _orig_req["nonce"] = "rnd_nonce"
        _pr_resp = self.endpoint.parse_request(_orig_req)
        _resp = self.endpoint.process_request(_pr_resp)
        msg = self.endpoint.do_response(**_resp)
        assert isinstance(msg, dict)
        part = urlparse(msg["response"])
        assert part.query == ""
        assert part.fragment
        _frag_msg = parse_qs(part.fragment)
        assert _frag_msg
        assert "id_token" in _frag_msg
        assert "code" in _frag_msg
        assert "access_token" in _frag_msg

    def test_id_token_claims(self):
        _req = AUTH_REQ_DICT.copy()
        _req["claims"] = CLAIMS
        _req["response_type"] = "code id_token token"
        _req["nonce"] = "rnd_nonce"
        _pr_resp = self.endpoint.parse_request(_req)
        _resp = self.endpoint.process_request(_pr_resp)
        idt = verify_id_token(_resp["response_args"],
                              keyjar=self.endpoint.endpoint_context.keyjar)
        assert idt
        # from claims
        assert "given_name" in _resp["response_args"]["__verified_id_token"]
        # from config
        assert "email" in _resp["response_args"]["__verified_id_token"]

    def test_re_authenticate(self):
        request = {"prompt": "login"}
        authn = UserAuthnMethod(self.endpoint.endpoint_context)
        assert re_authenticate(request, authn)

    def test_id_token_acr(self):
        _req = AUTH_REQ_DICT.copy()
        _req["claims"] = {
            "id_token": {
                "acr": {
                    "value": "http://www.swamid.se/policy/assurance/al1"
                }
            }
        }
        _req["response_type"] = "code id_token token"
        _req["nonce"] = "rnd_nonce"
        _pr_resp = self.endpoint.parse_request(_req)
        _resp = self.endpoint.process_request(_pr_resp)
        res = verify_id_token(_resp["response_args"],
                              keyjar=self.endpoint.endpoint_context.keyjar)
        assert res
        res = _resp["response_args"][verified_claim_name("id_token")]
        assert res["acr"] == "http://www.swamid.se/policy/assurance/al1"

    def test_verify_uri_unknown_client(self):
        request = {"redirect_uri": "https://rp.example.com/cb"}
        with pytest.raises(UnknownClient):
            verify_uri(self.endpoint.endpoint_context, request, "redirect_uri")

    def test_verify_uri_fragment(self):
        _ec = self.endpoint.endpoint_context
        _ec.cdb["client_id"] = {
            "redirect_uri": ["https://rp.example.com/auth_cb"]
        }
        request = {"redirect_uri": "https://rp.example.com/cb#foobar"}
        with pytest.raises(URIError):
            verify_uri(_ec, request, "redirect_uri", "client_id")

    def test_verify_uri_noregistered(self):
        _ec = self.endpoint.endpoint_context
        request = {"redirect_uri": "https://rp.example.com/cb"}

        with pytest.raises(ValueError):
            verify_uri(_ec, request, "redirect_uri", "client_id")

    def test_verify_uri_unregistered(self):
        _ec = self.endpoint.endpoint_context
        _ec.cdb["client_id"] = {
            "redirect_uris": [("https://rp.example.com/auth_cb", {})]
        }

        request = {"redirect_uri": "https://rp.example.com/cb"}

        with pytest.raises(RedirectURIError):
            verify_uri(_ec, request, "redirect_uri", "client_id")

    def test_verify_uri_qp_match(self):
        _ec = self.endpoint.endpoint_context
        _ec.cdb["client_id"] = {
            "redirect_uris": [("https://rp.example.com/cb", {
                "foo": ["bar"]
            })]
        }

        request = {"redirect_uri": "https://rp.example.com/cb?foo=bar"}

        verify_uri(_ec, request, "redirect_uri", "client_id")

    def test_verify_uri_qp_mismatch(self):
        _ec = self.endpoint.endpoint_context
        _ec.cdb["client_id"] = {
            "redirect_uris": [("https://rp.example.com/cb", {
                "foo": ["bar"]
            })]
        }

        request = {"redirect_uri": "https://rp.example.com/cb?foo=bob"}
        with pytest.raises(ValueError):
            verify_uri(_ec, request, "redirect_uri", "client_id")

        request = {"redirect_uri": "https://rp.example.com/cb?foo=bar&foo=kex"}
        with pytest.raises(ValueError):
            verify_uri(_ec, request, "redirect_uri", "client_id")

        request = {"redirect_uri": "https://rp.example.com/cb"}
        with pytest.raises(ValueError):
            verify_uri(_ec, request, "redirect_uri", "client_id")

        request = {
            "redirect_uri": "https://rp.example.com/cb?foo=bar&level=low"
        }
        with pytest.raises(ValueError):
            verify_uri(_ec, request, "redirect_uri", "client_id")

    def test_verify_uri_qp_missing(self):
        _ec = self.endpoint.endpoint_context
        _ec.cdb["client_id"] = {
            "redirect_uris": [("https://rp.example.com/cb", {
                "foo": ["bar"],
                "state": ["low"]
            })]
        }

        request = {"redirect_uri": "https://rp.example.com/cb?foo=bar"}
        with pytest.raises(ValueError):
            verify_uri(_ec, request, "redirect_uri", "client_id")

    def test_verify_uri_qp_missing_val(self):
        _ec = self.endpoint.endpoint_context
        _ec.cdb["client_id"] = {
            "redirect_uris": [("https://rp.example.com/cb", {
                "foo": ["bar", "low"]
            })]
        }

        request = {"redirect_uri": "https://rp.example.com/cb?foo=bar"}
        with pytest.raises(ValueError):
            verify_uri(_ec, request, "redirect_uri", "client_id")

    def test_verify_uri_no_registered_qp(self):
        _ec = self.endpoint.endpoint_context
        _ec.cdb["client_id"] = {
            "redirect_uris": [("https://rp.example.com/cb", {})]
        }

        request = {"redirect_uri": "https://rp.example.com/cb?foo=bob"}
        with pytest.raises(ValueError):
            verify_uri(_ec, request, "redirect_uri", "client_id")

    def test_get_uri(self):
        _ec = self.endpoint.endpoint_context
        _ec.cdb["client_id"] = {
            "redirect_uris": [("https://rp.example.com/cb", {})]
        }

        request = {
            "redirect_uri": "https://rp.example.com/cb",
            "client_id": "client_id",
        }

        assert get_uri(_ec, request,
                       "redirect_uri") == "https://rp.example.com/cb"

    def test_get_uri_no_redirect_uri(self):
        _ec = self.endpoint.endpoint_context
        _ec.cdb["client_id"] = {
            "redirect_uris": [("https://rp.example.com/cb", {})]
        }

        request = {"client_id": "client_id"}

        assert get_uri(_ec, request,
                       "redirect_uri") == "https://rp.example.com/cb"

    def test_get_uri_no_registered(self):
        _ec = self.endpoint.endpoint_context
        _ec.cdb["client_id"] = {
            "redirect_uris": [("https://rp.example.com/cb", {})]
        }

        request = {"client_id": "client_id"}

        with pytest.raises(ParameterError):
            get_uri(_ec, request, "post_logout_redirect_uri")

    def test_get_uri_more_then_one_registered(self):
        _ec = self.endpoint.endpoint_context
        _ec.cdb["client_id"] = {
            "redirect_uris": [
                ("https://rp.example.com/cb", {}),
                ("https://rp.example.org/authz_cb", {
                    "foo": "bar"
                }),
            ]
        }

        request = {"client_id": "client_id"}

        with pytest.raises(ParameterError):
            get_uri(_ec, request, "redirect_uri")

    def test_create_authn_response(self):
        request = AuthorizationRequest(
            client_id="client_id",
            redirect_uri="https://rp.example.com/cb",
            response_type=["id_token"],
            state="state",
            nonce="nonce",
            scope="openid",
        )

        _ec = self.endpoint.endpoint_context
        _ec.sdb["session_id"] = SessionInfo(
            authn_req=request,
            uid="diana",
            sub="abcdefghijkl",
            authn_event={
                "authn_info": "loa1",
                "uid": "diana",
                "authn_time": utc_time_sans_frac(),
            },
        )
        _ec.cdb["client_id"] = {
            "client_id": "client_id",
            "redirect_uris": [("https://rp.example.com/cb", {})],
            "id_token_signed_response_alg": "ES256",
        }

        resp = create_authn_response(self.endpoint, request, "session_id")
        assert isinstance(resp["response_args"], AuthorizationErrorResponse)

    def test_setup_auth(self):
        request = AuthorizationRequest(
            client_id="client_id",
            redirect_uri="https://rp.example.com/cb",
            response_type=["id_token"],
            state="state",
            nonce="nonce",
            scope="openid",
        )
        redirect_uri = request["redirect_uri"]
        cinfo = {
            "client_id": "client_id",
            "redirect_uris": [("https://rp.example.com/cb", {})],
            "id_token_signed_response_alg": "RS256",
        }

        kaka = self.endpoint.endpoint_context.cookie_dealer.create_cookie(
            "value", "sso")

        res = self.endpoint.setup_auth(request, redirect_uri, cinfo, kaka)
        assert set(res.keys()) == {"authn_event", "identity", "user"}

    def test_setup_auth_error(self):
        request = AuthorizationRequest(
            client_id="client_id",
            redirect_uri="https://rp.example.com/cb",
            response_type=["id_token"],
            state="state",
            nonce="nonce",
            scope="openid",
        )
        redirect_uri = request["redirect_uri"]
        cinfo = {
            "client_id": "client_id",
            "redirect_uris": [("https://rp.example.com/cb", {})],
            "id_token_signed_response_alg": "RS256",
        }

        item = self.endpoint.endpoint_context.authn_broker.db["anon"]
        item["method"].fail = NoSuchAuthentication

        res = self.endpoint.setup_auth(request, redirect_uri, cinfo, None)
        assert set(res.keys()) == {"function", "args"}

        item["method"].fail = ToOld

        res = self.endpoint.setup_auth(request, redirect_uri, cinfo, None)
        assert set(res.keys()) == {"function", "args"}

        item["method"].file = ""

    def test_setup_auth_user(self):
        request = AuthorizationRequest(
            client_id="client_id",
            redirect_uri="https://rp.example.com/cb",
            response_type=["id_token"],
            state="state",
            nonce="nonce",
            scope="openid",
        )
        redirect_uri = request["redirect_uri"]
        cinfo = {
            "client_id": "client_id",
            "redirect_uris": [("https://rp.example.com/cb", {})],
            "id_token_signed_response_alg": "RS256",
        }
        _ec = self.endpoint.endpoint_context
        _ec.sdb["session_id"] = SessionInfo(
            authn_req=request,
            uid="diana",
            sub="abcdefghijkl",
            authn_event={
                "authn_info": "loa1",
                "uid": "diana",
                "authn_time": utc_time_sans_frac(),
            },
        )

        item = _ec.authn_broker.db["anon"]
        item["method"].user = b64e(
            as_bytes(json.dumps({
                "uid": "krall",
                "sid": "session_id"
            })))

        res = self.endpoint.setup_auth(request, redirect_uri, cinfo, None)
        assert set(res.keys()) == {"authn_event", "identity", "user"}
        assert res["identity"]["uid"] == "krall"

    def test_setup_auth_session_revoked(self):
        request = AuthorizationRequest(
            client_id="client_id",
            redirect_uri="https://rp.example.com/cb",
            response_type=["id_token"],
            state="state",
            nonce="nonce",
            scope="openid",
        )
        redirect_uri = request["redirect_uri"]
        cinfo = {
            "client_id": "client_id",
            "redirect_uris": [("https://rp.example.com/cb", {})],
            "id_token_signed_response_alg": "RS256",
        }
        _ec = self.endpoint.endpoint_context
        _ec.sdb["session_id"] = SessionInfo(
            authn_req=request,
            uid="diana",
            sub="abcdefghijkl",
            authn_event={
                "authn_info": "loa1",
                "uid": "diana",
                "authn_time": utc_time_sans_frac(),
            },
            revoked=True,
        )

        item = _ec.authn_broker.db["anon"]
        item["method"].user = b64e(
            as_bytes(json.dumps({
                "uid": "krall",
                "sid": "session_id"
            })))

        res = self.endpoint.setup_auth(request, redirect_uri, cinfo, None)
        assert set(res.keys()) == {"args", "function"}

    def test_response_mode_form_post(self):
        request = {"response_mode": "form_post"}
        info = {
            "response_args": AuthorizationResponse(foo="bar"),
            "return_uri": "https://example.com/cb",
        }
        info = self.endpoint.response_mode(request, **info)
        assert set(info.keys()) == {
            "response_args", "return_uri", "response_msg", "content_type",
            "response_placement"
        }
        assert info["response_msg"] == FORM_POST.format(
            action="https://example.com/cb",
            inputs='<input type="hidden" name="foo" value="bar"/>',
        )

    def test_do_response_code_form_post(self):
        _req = AUTH_REQ_DICT.copy()
        _req["response_mode"] = "form_post"
        _pr_resp = self.endpoint.parse_request(_req)
        _resp = self.endpoint.process_request(_pr_resp)
        msg = self.endpoint.do_response(**_resp)
        assert ('Content-type', 'text/html') in msg["http_headers"]
        assert "response_placement" in msg

    def test_response_mode_fragment(self):
        request = {"response_mode": "fragment"}
        self.endpoint.response_mode(request, fragment_enc=True)

        with pytest.raises(InvalidRequest):
            self.endpoint.response_mode(request, fragment_enc=False)

        info = self.endpoint.response_mode(request)
        assert set(info.keys()) == {"fragment_enc"}

    def test_check_session_iframe(self):
        self.endpoint.endpoint_context.provider_info[
            "check_session_iframe"] = "https://example.com/csi"
        _pr_resp = self.endpoint.parse_request(AUTH_REQ_DICT)
        _resp = self.endpoint.process_request(_pr_resp)
        assert "session_state" in _resp["response_args"]

    def test_setup_auth_login_hint(self):
        request = AuthorizationRequest(
            client_id="client_id",
            redirect_uri="https://rp.example.com/cb",
            response_type=["id_token"],
            state="state",
            nonce="nonce",
            scope="openid",
            login_hint="tel:0907865204",
        )
        redirect_uri = request["redirect_uri"]
        cinfo = {
            "client_id": "client_id",
            "redirect_uris": [("https://rp.example.com/cb", {})],
            "id_token_signed_response_alg": "RS256",
        }

        item = self.endpoint.endpoint_context.authn_broker.db["anon"]
        item["method"].fail = NoSuchAuthentication

        res = self.endpoint.setup_auth(request, redirect_uri, cinfo, None)
        assert set(res.keys()) == {"function", "args"}
        assert "login_hint" in res["args"]

    def test_setup_auth_login_hint2acrs(self):
        request = AuthorizationRequest(
            client_id="client_id",
            redirect_uri="https://rp.example.com/cb",
            response_type=["id_token"],
            state="state",
            nonce="nonce",
            scope="openid",
            login_hint="email:foo@bar",
        )
        redirect_uri = request["redirect_uri"]

        method_spec = {
            "acr": INTERNETPROTOCOLPASSWORD,
            "kwargs": {
                "user": "******"
            },
            "class": NoAuthn,
        }
        self.endpoint.endpoint_context.authn_broker["foo"] = init_method(
            method_spec, None)

        item = self.endpoint.endpoint_context.authn_broker.db["anon"]
        item["method"].fail = NoSuchAuthentication
        item = self.endpoint.endpoint_context.authn_broker.db["foo"]
        item["method"].fail = NoSuchAuthentication

        res = self.endpoint.pick_authn_method(request, redirect_uri)
        assert set(res.keys()) == {"method", "acr"}
        assert res["acr"] == INTERNETPROTOCOLPASSWORD
        assert isinstance(res["method"], NoAuthn)
        assert res["method"].user == "knoll"

    def test_post_logout_uri(self):
        pass

    def test_parse_request(self):
        _jwt = JWT(key_jar=self.rp_keyjar, iss="client_1", sign_alg="HS256")
        _jws = _jwt.pack(
            AUTH_REQ_DICT,
            aud=self.endpoint.endpoint_context.provider_info["issuer"])
        # -----------------
        _req = self.endpoint.parse_request({
            "request":
            _jws,
            "redirect_uri":
            AUTH_REQ.get("redirect_uri"),
            "response_type":
            AUTH_REQ.get("response_type"),
            "client_id":
            AUTH_REQ.get("client_id"),
            "scope":
            AUTH_REQ.get("scope"),
        })
        assert "__verified_request" in _req

    def test_parse_request_uri(self):
        _jwt = JWT(key_jar=self.rp_keyjar, iss="client_1", sign_alg="HS256")
        _jws = _jwt.pack(
            AUTH_REQ_DICT,
            aud=self.endpoint.endpoint_context.provider_info["issuer"])

        request_uri = "https://client.example.com/req"
        # -----------------
        with responses.RequestsMock() as rsps:
            rsps.add("GET", request_uri, body=_jws, status=200)
            _req = self.endpoint.parse_request({
                "request_uri":
                request_uri,
                "redirect_uri":
                AUTH_REQ.get("redirect_uri"),
                "response_type":
                AUTH_REQ.get("response_type"),
                "client_id":
                AUTH_REQ.get("client_id"),
                "scope":
                AUTH_REQ.get("scope"),
            })

        assert "__verified_request" in _req
class TestEndpoint(object):
    @pytest.fixture(autouse=True)
    def create_endpoint(self):
        conf = {
            "issuer": "https://example.com/",
            "password": "******",
            "verify_ssl": False,
            "capabilities": CAPABILITIES,
            "keys": {"uri_path": "static/jwks.json", "key_defs": KEYDEFS},
            "token_handler_args": {
                "jwks_file": "private/token_jwks.json",
                "code": {"kwargs": {"lifetime": 600}},
                "token": {
                    "class": "oidcop.token.jwt_token.JWTToken",
                    "kwargs": {
                        "lifetime": 3600,
                        "add_claims_by_scope": True,
                        "aud": ["https://example.org/appl"],
                    },
                },
                "refresh": {
                    "class": "oidcop.token.jwt_token.JWTToken",
                    "kwargs": {"lifetime": 3600, "aud": ["https://example.org/appl"],},
                },
                "id_token": {
                    "class": "oidcop.token.id_token.IDToken",
                    "kwargs": {
                        "base_claims": {
                            "email": {"essential": True},
                            "email_verified": {"essential": True},
                            "given_name": {"essential": True},
                            "nickname": None,
                        }
                    },
                },
            },
            "endpoint": {
                "provider_config": {
                    "path": "{}/.well-known/openid-configuration",
                    "class": ProviderConfiguration,
                    "kwargs": {},
                },
                "registration": {"path": "{}/registration", "class": Registration, "kwargs": {},},
                "authorization": {
                    "path": "{}/authorization",
                    "class": Authorization,
                    "kwargs": {
                        "response_types_supported": [" ".join(x) for x in RESPONSE_TYPES_SUPPORTED],
                        "response_modes_supported": ["query", "fragment", "form_post"],
                        "claims_parameter_supported": True,
                        "request_parameter_supported": True,
                        "request_uri_parameter_supported": True,
                    },
                },
                "token": {
                    "path": "token",
                    "class": Token,
                    "kwargs": {
                        "client_authn_method": [
                            "client_secret_post",
                            "client_secret_basic",
                            "client_secret_jwt",
                            "private_key_jwt",
                        ]
                    },
                },
                "userinfo": {
                    "path": "userinfo",
                    "class": userinfo.UserInfo,
                    "kwargs": {
                        "db_file": "users.json",
                        "claim_types_supported": ["normal", "aggregated", "distributed",],
                    },
                },
            },
            "authentication": {
                "anon": {
                    "acr": "http://www.swamid.se/policy/assurance/al1",
                    "class": "oidcop.user_authn.user.NoAuthn",
                    "kwargs": {"user": "******"},
                }
            },
            "userinfo": {"class": UserInfo, "kwargs": {"db": USERINFO_db}},
            "template_dir": "template",
            "authz": {
                "class": AuthzHandling,
                "kwargs": {
                    "grant_config": {
                        "usage_rules": {
                            "authorization_code": {
                                "supports_minting": ["access_token", "refresh_token", "id_token",],
                                "max_usage": 1,
                            },
                            "access_token": {},
                            "refresh_token": {
                                "supports_minting": ["access_token", "refresh_token"],
                            },
                        },
                        "expires_in": 43200,
                    }
                },
            },
            "cookie_handler": {
                "class": CookieHandler,
                "kwargs": {
                    "sign_key": "ghsNKDDLshZTPn974nOsIGhedULrsqnsGoBFBLwUKuJhE2ch",
                    "name": {
                        "session": "oidc_op",
                        "register": "oidc_op_reg",
                        "session_management": "oidc_op_sman",
                    },
                },
            },
            "login_hint2acrs": {
                "class": LoginHint2Acrs,
                "kwargs": {"scheme_map": {"email": [INTERNETPROTOCOLPASSWORD]}},
            },
        }
        server = Server(OPConfiguration(conf=conf, base_path=BASEDIR), cwd=BASEDIR)

        endpoint_context = server.endpoint_context

        _clients = yaml.safe_load(io.StringIO(client_yaml))
        endpoint_context.cdb = _clients["oidc_clients"]
        endpoint_context.keyjar.import_jwks(
            endpoint_context.keyjar.export_jwks(True, ""), conf["issuer"]
        )
        self.endpoint = server.server_get("endpoint", "authorization")
        self.session_manager = endpoint_context.session_manager
        self.user_id = "diana"

        self.rp_keyjar = KeyJar()
        self.rp_keyjar.add_symmetric("client_1", "hemligtkodord1234567890")
        endpoint_context.keyjar.add_symmetric("client_1", "hemligtkodord1234567890")

    def test_init(self):
        assert self.endpoint

    def _create_session(self, auth_req, sub_type="public", sector_identifier=""):
        if sector_identifier:
            authz_req = auth_req.copy()
            authz_req["sector_identifier_uri"] = sector_identifier
        else:
            authz_req = auth_req
        client_id = authz_req["client_id"]
        ae = create_authn_event(self.user_id)
        return self.session_manager.create_session(
            ae, authz_req, self.user_id, client_id=client_id, sub_type=sub_type
        )

    def test_parse(self):
        _req = self.endpoint.parse_request(AUTH_REQ_DICT)

        assert isinstance(_req, AuthorizationRequest)
        assert set(_req.keys()) == set(AUTH_REQ.keys())

    def test_process_request(self):
        _pr_resp = self.endpoint.parse_request(AUTH_REQ_DICT)
        _resp = self.endpoint.process_request(_pr_resp)
        assert set(_resp.keys()) == {
            "response_args",
            "fragment_enc",
            "return_uri",
            "cookie",
            "session_id",
        }

    def test_do_response_code(self):
        _pr_resp = self.endpoint.parse_request(AUTH_REQ_DICT)
        _resp = self.endpoint.process_request(_pr_resp)
        msg = self.endpoint.do_response(**_resp)
        assert isinstance(msg, dict)
        _msg = parse_qs(msg["response"])
        assert _msg
        part = urlparse(msg["response"])
        assert part.fragment == ""
        assert part.query
        _query = parse_qs(part.query)
        assert _query
        assert "code" in _query

    def test_do_response_id_token_no_nonce(self):
        _orig_req = AUTH_REQ_DICT.copy()
        _orig_req["response_type"] = "id_token"
        _pr_resp = self.endpoint.parse_request(_orig_req)
        # Missing nonce
        assert isinstance(_pr_resp, ResponseMessage)

    def test_do_response_id_token(self):
        _orig_req = AUTH_REQ_DICT.copy()
        _orig_req["response_type"] = "id_token"
        _orig_req["nonce"] = "rnd_nonce"
        _pr_resp = self.endpoint.parse_request(_orig_req)
        _resp = self.endpoint.process_request(_pr_resp)
        msg = self.endpoint.do_response(**_resp)
        assert isinstance(msg, dict)
        part = urlparse(msg["response"])
        assert part.query == ""
        assert part.fragment
        _frag_msg = parse_qs(part.fragment)
        assert _frag_msg
        assert "id_token" in _frag_msg
        assert "code" not in _frag_msg
        assert "token" not in _frag_msg

    def test_do_response_id_token_token(self):
        _orig_req = AUTH_REQ_DICT.copy()
        _orig_req["response_type"] = "id_token token"
        _orig_req["nonce"] = "rnd_nonce"
        _pr_resp = self.endpoint.parse_request(_orig_req)
        assert isinstance(_pr_resp, AuthorizationErrorResponse)
        assert _pr_resp["error"] == "invalid_request"

    def test_do_response_code_token(self):
        _orig_req = AUTH_REQ_DICT.copy()
        _orig_req["response_type"] = "code token"
        _pr_resp = self.endpoint.parse_request(_orig_req)
        assert isinstance(_pr_resp, AuthorizationErrorResponse)
        assert _pr_resp["error"] == "invalid_request"

    def test_do_response_code_id_token(self):
        _orig_req = AUTH_REQ_DICT.copy()
        _orig_req["response_type"] = "code id_token"
        _orig_req["nonce"] = "rnd_nonce"
        _pr_resp = self.endpoint.parse_request(_orig_req)
        _resp = self.endpoint.process_request(_pr_resp)
        msg = self.endpoint.do_response(**_resp)
        assert isinstance(msg, dict)
        part = urlparse(msg["response"])
        assert part.query == ""
        assert part.fragment
        _frag_msg = parse_qs(part.fragment)
        assert _frag_msg
        assert "id_token" in _frag_msg
        assert "code" in _frag_msg
        assert "access_token" not in _frag_msg

    def test_do_response_code_id_token_token(self):
        _orig_req = AUTH_REQ_DICT.copy()
        _orig_req["response_type"] = "code id_token token"
        _orig_req["nonce"] = "rnd_nonce"
        _pr_resp = self.endpoint.parse_request(_orig_req)
        _resp = self.endpoint.process_request(_pr_resp)
        msg = self.endpoint.do_response(**_resp)
        assert isinstance(msg, dict)
        part = urlparse(msg["response"])
        assert part.query == ""
        assert part.fragment
        _frag_msg = parse_qs(part.fragment)
        assert _frag_msg
        assert "id_token" in _frag_msg
        assert "code" in _frag_msg
        assert "access_token" in _frag_msg

    def test_id_token_claims(self):
        _req = AUTH_REQ_DICT.copy()
        _req["claims"] = CLAIMS
        _req["response_type"] = "code id_token token"
        _req["nonce"] = "rnd_nonce"
        _pr_resp = self.endpoint.parse_request(_req)
        _resp = self.endpoint.process_request(_pr_resp)
        idt = verify_id_token(
            _resp["response_args"], keyjar=self.endpoint.server_get("endpoint_context").keyjar,
        )
        assert idt
        # from config
        assert "given_name" in _resp["response_args"]["__verified_id_token"]
        assert "nickname" in _resp["response_args"]["__verified_id_token"]
        # Could have gotten email but didn't ask for it
        assert "email" in _resp["response_args"]["__verified_id_token"]

    def test_re_authenticate(self):
        request = {"prompt": "login"}
        authn = UserAuthnMethod(self.endpoint.server_get("endpoint_context"))
        assert re_authenticate(request, authn)

    def test_id_token_acr(self):
        _req = AUTH_REQ_DICT.copy()
        _req["claims"] = {
            "id_token": {"acr": {"value": "http://www.swamid.se/policy/assurance/al1"}}
        }
        _req["response_type"] = "code id_token token"
        _req["nonce"] = "rnd_nonce"
        _pr_resp = self.endpoint.parse_request(_req)
        _resp = self.endpoint.process_request(_pr_resp)
        res = verify_id_token(
            _resp["response_args"], keyjar=self.endpoint.server_get("endpoint_context").keyjar,
        )
        assert res
        res = _resp["response_args"][verified_claim_name("id_token")]
        assert res["acr"] == "http://www.swamid.se/policy/assurance/al1"

    def test_verify_uri_unknown_client(self):
        request = {"redirect_uri": "https://rp.example.com/cb"}
        with pytest.raises(UnknownClient):
            verify_uri(self.endpoint.server_get("endpoint_context"), request, "redirect_uri")

    def test_verify_uri_fragment(self):
        _ec = self.endpoint.server_get("endpoint_context")
        _ec.cdb["client_id"] = {"redirect_uri": ["https://rp.example.com/auth_cb"]}
        request = {"redirect_uri": "https://rp.example.com/cb#foobar"}
        with pytest.raises(URIError):
            verify_uri(_ec, request, "redirect_uri", "client_id")

    def test_verify_uri_noregistered(self):
        _ec = self.endpoint.server_get("endpoint_context")
        request = {"redirect_uri": "https://rp.example.com/cb"}

        with pytest.raises(KeyError):
            verify_uri(_ec, request, "redirect_uri", "client_id")

    def test_verify_uri_unregistered(self):
        _ec = self.endpoint.server_get("endpoint_context")
        _ec.cdb["client_id"] = {"redirect_uris": [("https://rp.example.com/auth_cb", {})]}

        request = {"redirect_uri": "https://rp.example.com/cb"}

        with pytest.raises(RedirectURIError):
            verify_uri(_ec, request, "redirect_uri", "client_id")

    def test_verify_uri_qp_match(self):
        _ec = self.endpoint.server_get("endpoint_context")
        _ec.cdb["client_id"] = {"redirect_uris": [("https://rp.example.com/cb", {"foo": ["bar"]})]}

        request = {"redirect_uri": "https://rp.example.com/cb?foo=bar"}

        verify_uri(_ec, request, "redirect_uri", "client_id")

    def test_verify_uri_qp_mismatch(self):
        _ec = self.endpoint.server_get("endpoint_context")
        _ec.cdb["client_id"] = {"redirect_uris": [("https://rp.example.com/cb", {"foo": ["bar"]})]}

        request = {"redirect_uri": "https://rp.example.com/cb?foo=bob"}
        with pytest.raises(ValueError):
            verify_uri(_ec, request, "redirect_uri", "client_id")

        request = {"redirect_uri": "https://rp.example.com/cb?foo=bar&foo=kex"}
        with pytest.raises(ValueError):
            verify_uri(_ec, request, "redirect_uri", "client_id")

        request = {"redirect_uri": "https://rp.example.com/cb"}
        with pytest.raises(ValueError):
            verify_uri(_ec, request, "redirect_uri", "client_id")

        request = {"redirect_uri": "https://rp.example.com/cb?foo=bar&level=low"}
        with pytest.raises(ValueError):
            verify_uri(_ec, request, "redirect_uri", "client_id")

    def test_verify_uri_qp_missing(self):
        _ec = self.endpoint.server_get("endpoint_context")
        _ec.cdb["client_id"] = {
            "redirect_uris": [("https://rp.example.com/cb", {"foo": ["bar"], "state": ["low"]})]
        }

        request = {"redirect_uri": "https://rp.example.com/cb?foo=bar"}
        with pytest.raises(ValueError):
            verify_uri(_ec, request, "redirect_uri", "client_id")

    def test_verify_uri_qp_missing_val(self):
        _ec = self.endpoint.server_get("endpoint_context")
        _ec.cdb["client_id"] = {
            "redirect_uris": [("https://rp.example.com/cb", {"foo": ["bar", "low"]})]
        }

        request = {"redirect_uri": "https://rp.example.com/cb?foo=bar"}
        with pytest.raises(ValueError):
            verify_uri(_ec, request, "redirect_uri", "client_id")

    def test_verify_uri_no_registered_qp(self):
        _ec = self.endpoint.server_get("endpoint_context")
        _ec.cdb["client_id"] = {"redirect_uris": [("https://rp.example.com/cb", {})]}

        request = {"redirect_uri": "https://rp.example.com/cb?foo=bob"}
        with pytest.raises(ValueError):
            verify_uri(_ec, request, "redirect_uri", "client_id")

    def test_get_uri(self):
        _ec = self.endpoint.server_get("endpoint_context")
        _ec.cdb["client_id"] = {"redirect_uris": [("https://rp.example.com/cb", {})]}

        request = {
            "redirect_uri": "https://rp.example.com/cb",
            "client_id": "client_id",
        }

        assert get_uri(_ec, request, "redirect_uri") == "https://rp.example.com/cb"

    def test_get_uri_no_redirect_uri(self):
        _ec = self.endpoint.server_get("endpoint_context")
        _ec.cdb["client_id"] = {"redirect_uris": [("https://rp.example.com/cb", {})]}

        request = {"client_id": "client_id"}

        assert get_uri(_ec, request, "redirect_uri") == "https://rp.example.com/cb"

    def test_get_uri_no_registered(self):
        _ec = self.endpoint.server_get("endpoint_context")
        _ec.cdb["client_id"] = {"redirect_uris": [("https://rp.example.com/cb", {})]}

        request = {"client_id": "client_id"}

        with pytest.raises(ParameterError):
            get_uri(_ec, request, "post_logout_redirect_uri")

    def test_get_uri_more_then_one_registered(self):
        _ec = self.endpoint.server_get("endpoint_context")
        _ec.cdb["client_id"] = {
            "redirect_uris": [
                ("https://rp.example.com/cb", {}),
                ("https://rp.example.org/authz_cb", {"foo": "bar"}),
            ]
        }

        request = {"client_id": "client_id"}

        with pytest.raises(ParameterError):
            get_uri(_ec, request, "redirect_uri")

    def test_create_authn_response(self):
        request = AuthorizationRequest(
            client_id="client_id",
            redirect_uri="https://rp.example.com/cb",
            response_type=["id_token"],
            state="state",
            nonce="nonce",
            scope="openid",
        )

        _ec = self.endpoint.server_get("endpoint_context")
        _ec.cdb["client_id"] = {
            "client_id": "client_id",
            "redirect_uris": [("https://rp.example.com/cb", {})],
            "id_token_signed_response_alg": "ES256",
        }

        session_id = self._create_session(request)

        resp = self.endpoint.create_authn_response(request, session_id)
        assert isinstance(resp["response_args"], AuthorizationResponse)

    def test_setup_auth(self):
        request = AuthorizationRequest(
            client_id="client_id",
            redirect_uri="https://rp.example.com/cb",
            response_type=["id_token"],
            state="state",
            nonce="nonce",
            scope="openid",
        )
        redirect_uri = request["redirect_uri"]
        cinfo = {
            "client_id": "client_id",
            "redirect_uris": [("https://rp.example.com/cb", {})],
            "id_token_signed_response_alg": "RS256",
        }

        kaka = self.endpoint.server_get("endpoint_context").cookie_handler.make_cookie_content(
            "value", "sso"
        )

        res = self.endpoint.setup_auth(request, redirect_uri, cinfo, [kaka])
        assert set(res.keys()) == {"session_id", "identity", "user"}

    def test_setup_auth_error(self):
        request = AuthorizationRequest(
            client_id="client_id",
            redirect_uri="https://rp.example.com/cb",
            response_type=["id_token"],
            state="state",
            nonce="nonce",
            scope="openid",
        )
        redirect_uri = request["redirect_uri"]
        cinfo = {
            "client_id": "client_id",
            "redirect_uris": [("https://rp.example.com/cb", {})],
            "id_token_signed_response_alg": "RS256",
        }

        item = self.endpoint.server_get("endpoint_context").authn_broker.db["anon"]
        item["method"].fail = NoSuchAuthentication

        res = self.endpoint.setup_auth(request, redirect_uri, cinfo, None)
        assert set(res.keys()) == {"function", "args"}

        item["method"].fail = ToOld

        res = self.endpoint.setup_auth(request, redirect_uri, cinfo, None)
        assert set(res.keys()) == {"function", "args"}

        item["method"].file = ""

    def test_setup_auth_user(self):
        request = AuthorizationRequest(
            client_id="client_id",
            redirect_uri="https://rp.example.com/cb",
            response_type=["id_token"],
            state="state",
            nonce="nonce",
            scope="openid",
        )
        redirect_uri = request["redirect_uri"]
        cinfo = {
            "client_id": "client_id",
            "redirect_uris": [("https://rp.example.com/cb", {})],
            "id_token_signed_response_alg": "RS256",
        }
        _ec = self.endpoint.server_get("endpoint_context")

        session_id = self._create_session(request)

        item = _ec.authn_broker.db["anon"]
        item["method"].user = b64e(as_bytes(json.dumps({"uid": "krall", "sid": session_id})))

        res = self.endpoint.setup_auth(request, redirect_uri, cinfo, None)
        assert set(res.keys()) == {"session_id", "identity", "user"}
        assert res["identity"]["uid"] == "krall"

    def test_setup_auth_session_revoked(self):
        request = AuthorizationRequest(
            client_id="client_id",
            redirect_uri="https://rp.example.com/cb",
            response_type=["id_token"],
            state="state",
            nonce="nonce",
            scope="openid",
        )
        redirect_uri = request["redirect_uri"]
        cinfo = {
            "client_id": "client_id",
            "redirect_uris": [("https://rp.example.com/cb", {})],
            "id_token_signed_response_alg": "RS256",
        }
        _ec = self.endpoint.server_get("endpoint_context")

        session_id = self._create_session(request)

        item = _ec.authn_broker.db["anon"]
        item["method"].user = b64e(as_bytes(json.dumps({"uid": "krall", "sid": session_id})))

        grant = _ec.session_manager[session_id]
        grant.revoked = True

        res = self.endpoint.setup_auth(request, redirect_uri, cinfo, None)
        assert set(res.keys()) == {"args", "function"}

    def test_check_session_iframe(self):
        self.endpoint.server_get("endpoint_context").provider_info[
            "check_session_iframe"
        ] = "https://example.com/csi"
        _pr_resp = self.endpoint.parse_request(AUTH_REQ_DICT)
        _resp = self.endpoint.process_request(_pr_resp)
        assert "session_state" in _resp["response_args"]

    def test_setup_auth_login_hint(self):
        request = AuthorizationRequest(
            client_id="client_id",
            redirect_uri="https://rp.example.com/cb",
            response_type=["id_token"],
            state="state",
            nonce="nonce",
            scope="openid",
            login_hint="tel:0907865204",
        )
        redirect_uri = request["redirect_uri"]
        cinfo = {
            "client_id": "client_id",
            "redirect_uris": [("https://rp.example.com/cb", {})],
            "id_token_signed_response_alg": "RS256",
        }

        item = self.endpoint.server_get("endpoint_context").authn_broker.db["anon"]
        item["method"].fail = NoSuchAuthentication

        res = self.endpoint.setup_auth(request, redirect_uri, cinfo, None)
        assert set(res.keys()) == {"function", "args"}
        assert "login_hint" in res["args"]

    def test_setup_auth_login_hint2acrs(self):
        request = AuthorizationRequest(
            client_id="client_id",
            redirect_uri="https://rp.example.com/cb",
            response_type=["id_token"],
            state="state",
            nonce="nonce",
            scope="openid",
            login_hint="email:foo@bar",
        )
        redirect_uri = request["redirect_uri"]

        method_spec = {
            "acr": INTERNETPROTOCOLPASSWORD,
            "kwargs": {"user": "******"},
            "class": NoAuthn,
        }
        self.endpoint.server_get("endpoint_context").authn_broker["foo"] = init_method(
            method_spec, None
        )

        item = self.endpoint.server_get("endpoint_context").authn_broker.db["anon"]
        item["method"].fail = NoSuchAuthentication
        item = self.endpoint.server_get("endpoint_context").authn_broker.db["foo"]
        item["method"].fail = NoSuchAuthentication

        res = self.endpoint.pick_authn_method(request, redirect_uri)
        assert set(res.keys()) == {"method", "acr"}
        assert res["acr"] == INTERNETPROTOCOLPASSWORD
        assert isinstance(res["method"], NoAuthn)
        assert res["method"].user == "knoll"

    def test_post_logout_uri(self):
        pass

    def test_parse_request(self):
        _jwt = JWT(key_jar=self.rp_keyjar, iss="client_1", sign_alg="HS256")
        _jws = _jwt.pack(
            AUTH_REQ_DICT, aud=self.endpoint.server_get("endpoint_context").provider_info["issuer"],
        )
        # -----------------
        _req = self.endpoint.parse_request(
            {
                "request": _jws,
                "redirect_uri": AUTH_REQ.get("redirect_uri"),
                "response_type": AUTH_REQ.get("response_type"),
                "client_id": AUTH_REQ.get("client_id"),
                "scope": AUTH_REQ.get("scope"),
            }
        )
        assert "__verified_request" in _req

    def test_parse_request_uri(self):
        _jwt = JWT(key_jar=self.rp_keyjar, iss="client_1", sign_alg="HS256")
        _jws = _jwt.pack(
            AUTH_REQ_DICT, aud=self.endpoint.server_get("endpoint_context").provider_info["issuer"],
        )

        request_uri = "https://client.example.com/req"
        # -----------------
        with responses.RequestsMock() as rsps:
            rsps.add("GET", request_uri, body=_jws, status=200)
            _req = self.endpoint.parse_request(
                {
                    "request_uri": request_uri,
                    "redirect_uri": AUTH_REQ.get("redirect_uri"),
                    "response_type": AUTH_REQ.get("response_type"),
                    "client_id": AUTH_REQ.get("client_id"),
                    "scope": AUTH_REQ.get("scope"),
                }
            )

        assert "__verified_request" in _req

    def test_verify_response_type(self):
        request = AuthorizationRequest(
            client_id="client_id",
            redirect_uri="https://rp.example.com/cb",
            response_type=["id_token token"],
            state="state",
            nonce="nonce",
            scope="openid",
        )
        client_info = {
            "client_id": "client_id",
            "redirect_uris": [("https://rp.example.com/cb", {})],
            "id_token_signed_response_alg": "RS256",
            "policy_uri": "https://example.com/policy.html",
        }

        assert self.endpoint.verify_response_type(request, client_info) is False

        client_info["response_types"] = [
            "code",
            "code id_token",
            "id_token",
            "id_token token",
        ]

        assert self.endpoint.verify_response_type(request, client_info) is True

    @pytest.mark.parametrize("exp_in", [360, "360", 0])
    def test_mint_token_exp_at(self, exp_in):
        grant = Grant()
        grant.usage_rules = {"authorization_code": {"expires_in": exp_in}}

        DUMMY_SESSION_ID = self.session_manager.encrypted_session_id(
            "user_id", "client_id", "grant.id"
        )

        code = self.endpoint.mint_token("authorization_code", grant, DUMMY_SESSION_ID)
        if exp_in in [360, "360"]:
            assert code.expires_at
        else:
            assert code.expires_at == 0

    def test_do_request_uri(self):
        request = AuthorizationRequest(
            redirect_uri="https://rp.example.com/cb", request_uri="https://example.com/request",
        )

        orig_request = AuthorizationRequest(
            client_id="client_id",
            redirect_uri="https://rp.example.com/cb",
            response_type=["id_token token"],
            state="state",
            nonce="nonce",
            scope="openid",
        )
        _jwt = JWT(key_jar=self.rp_keyjar, iss="client_1", sign_alg="HS256")
        _jws = _jwt.pack(
            orig_request.to_dict(),
            aud=self.endpoint.server_get("endpoint_context").provider_info["issuer"],
        )

        endpoint_context = self.endpoint.server_get("endpoint_context")
        endpoint_context.cdb["client_1"]["request_uris"] = [("https://example.com/request", {})]

        with responses.RequestsMock() as rsps:
            rsps.add(
                "GET",
                request["request_uri"],
                body=_jws,
                adding_headers={"Content-Type": "application/jose"},
                status=200,
            )

            self.endpoint._do_request_uri(request, "client_1", endpoint_context)

        request["request_uri"] = "https://example.com/request#1"

        with responses.RequestsMock() as rsps:
            rsps.add(
                "GET",
                request["request_uri"],
                body=_jws,
                adding_headers={"Content-Type": "application/jose"},
                status=200,
            )

            self.endpoint._do_request_uri(request, "client_1", endpoint_context)

        request["request_uri"] = "https://example.com/another"
        with pytest.raises(ValueError):
            self.endpoint._do_request_uri(request, "client_1", endpoint_context)

        endpoint_context.provider_info["request_uri_parameter_supported"] = False
        with pytest.raises(ServiceError):
            self.endpoint._do_request_uri(request, "client_1", endpoint_context)

    def test_post_parse_request(self):
        endpoint_context = self.endpoint.server_get("endpoint_context")
        msg = self.endpoint._post_parse_request(None, "client_1", endpoint_context)
        assert "error" in msg

        request = AuthorizationRequest(
            client_id="client_X",
            response_type=["code"],
            state="state",
            nonce="nonce",
            scope="openid",
        )

        msg = self.endpoint._post_parse_request(request, "client_X", endpoint_context)
        assert "error" in msg
        assert msg["error_description"] == "unknown client"

        request["client_id"] = "client_1"
        endpoint_context.cdb["client_1"]["redirect_uris"] = [
            ("https://example.com/cb", ""),
            ("https://example.com/2nd_cb", ""),
        ]

        msg = self.endpoint._post_parse_request(request, "client_1", endpoint_context)
        assert "error" in msg
        assert msg["error"] == "invalid_request"

    @pytest.mark.parametrize("response_mode", ["form_post", "fragment", "query"])
    def test_response_mode(self, response_mode):
        request = AuthorizationRequest(
            client_id="client_1",
            response_type=["code"],
            redirect_uri="https://example.com/cb",
            state="state",
            scope="openid",
            response_mode=response_mode,
        )

        response_args = AuthorizationResponse(scope="openid", code="abcdefghijklmnop")

        if response_mode == "fragment":
            info = self.endpoint.response_mode(
                request, response_args, request["redirect_uri"], fragment_enc=True
            )
        else:
            info = self.endpoint.response_mode(request, response_args, request["redirect_uri"])

        if response_mode == "form_post":
            assert set(info.keys()) == {
                "response_msg",
                "content_type",
                "response_placement",
            }
        elif response_mode == "fragment":
            assert set(info.keys()) == {"response_args", "return_uri", "fragment_enc"}
        elif response_mode == "query":
            assert set(info.keys()) == {"response_args", "return_uri"}

    def test_post_authentication(self):
        request = AuthorizationRequest(
            client_id="client_1",
            response_type=["code"],
            redirect_uri="https://example.com/cb",
            state="state",
            scope="openid",
        )
        session_id = self._create_session(request)
        resp = self.endpoint.post_authentication(request, session_id)
        assert resp

    def test_do_request_user(self):
        request = AuthorizationRequest(
            client_id="client_id",
            redirect_uri="https://rp.example.com/cb",
            response_type=["id_token"],
            state="state",
            nonce="nonce",
            scope="openid",
        )
        assert self.endpoint.do_request_user(request) == {}

        # With login_hint
        request["login_hint"] = "mail:[email protected]"
        assert self.endpoint.do_request_user(request) == {}

        endpoint_context = self.endpoint.server_get("endpoint_context")
        # userinfo
        _userinfo = init_user_info(
            {"class": "oidcop.user_info.UserInfo", "kwargs": {"db_file": full_path("users.json")},},
            "",
        )
        # login_hint
        endpoint_context.login_hint_lookup = init_service(
            {"class": "oidcop.login_hint.LoginHintLookup"}, None
        )
        endpoint_context.login_hint_lookup.userinfo = _userinfo

        # With login_hint and login_hint_lookup
        assert self.endpoint.do_request_user(request) == {"req_user": "******"}
예제 #6
0
class TestEndpoint(object):
    @pytest.fixture(autouse=True)
    def create_endpoint(self):
        conf = {
            "issuer": "https://example.com/",
            "password": "******",
            "verify_ssl": False,
            "capabilities": CAPABILITIES,
            "keys": {"uri_path": "static/jwks.json", "key_defs": KEYDEFS},
            "token_handler_args": {
                "jwks_def": {
                    "private_path": "private/token_jwks.json",
                    "read_only": False,
                    "key_defs": [{"type": "oct", "bytes": "24", "use": ["enc"], "kid": "code"}],
                },
                "code": {"kwargs": {"lifetime": 600}},
                "token": {
                    "class": "oidcop.token.jwt_token.JWTToken",
                    "kwargs": {
                        "lifetime": 3600,
                        "add_claims_by_scope": True,
                        "aud": ["https://example.org/appl"],
                    },
                },
                "refresh": {
                    "class": "oidcop.token.jwt_token.JWTToken",
                    "kwargs": {"lifetime": 3600, "aud": ["https://example.org/appl"],},
                },
                "id_token": {
                    "class": "oidcop.token.id_token.IDToken",
                    "kwargs": {
                        "base_claims": {
                            "email": {"essential": True},
                            "email_verified": {"essential": True},
                        }
                    },
                },
            },
            "endpoint": {
                "authorization": {
                    "path": "{}/authorization",
                    "class": Authorization,
                    "kwargs": {
                        "response_types_supported": [" ".join(x) for x in RESPONSE_TYPES_SUPPORTED],
                        "response_modes_supported": ["query", "fragment", "form_post"],
                        "claims_parameter_supported": True,
                        "request_parameter_supported": True,
                        "request_uri_parameter_supported": True,
                    },
                }
            },
            "authentication": {
                "anon": {
                    "acr": "http://www.swamid.se/policy/assurance/al1",
                    "class": "oidcop.user_authn.user.NoAuthn",
                    "kwargs": {"user": "******"},
                }
            },
            "userinfo": {"class": UserInfo, "kwargs": {"db": USERINFO_db}},
            "template_dir": "template",
            "cookie_handler": {
                "class": CookieHandler,
                "kwargs": {
                    "keys": {"key_defs": COOKIE_KEYDEFS},
                    "name": {
                        "session": "oidc_op",
                        "register": "oidc_op_reg",
                        "session_management": "oidc_op_sman",
                    },
                },
            },
            "authz": {
                "class": AuthzHandling,
                "kwargs": {
                    "grant_config": {
                        "usage_rules": {
                            "authorization_code": {
                                "supports_minting": ["access_token", "refresh_token", "id_token",],
                                "max_usage": 1,
                            },
                            "access_token": {},
                            "refresh_token": {
                                "supports_minting": ["access_token", "refresh_token", "id_token",],
                            },
                        },
                        "expires_in": 43200,
                    }
                },
            },
        }
        server = Server(ASConfiguration(conf=conf, base_path=BASEDIR), cwd=BASEDIR)

        endpoint_context = server.endpoint_context
        _clients = yaml.safe_load(io.StringIO(client_yaml))
        endpoint_context.cdb = _clients["clients"]
        endpoint_context.keyjar.import_jwks(
            endpoint_context.keyjar.export_jwks(True, ""), conf["issuer"]
        )
        self.endpoint = server.server_get("endpoint", "authorization")
        self.session_manager = endpoint_context.session_manager
        self.user_id = "diana"

        self.rp_keyjar = KeyJar()
        self.rp_keyjar.add_symmetric("client_1", "hemligtkodord1234567890")
        self.endpoint.server_get("endpoint_context").keyjar.add_symmetric(
            "client_1", "hemligtkodord1234567890"
        )

    def _create_session(self, auth_req, sub_type="public", sector_identifier=""):
        if sector_identifier:
            areq = auth_req.copy()
            areq["sector_identifier_uri"] = sector_identifier
        else:
            areq = auth_req

        client_id = areq["client_id"]
        ae = create_authn_event(self.user_id)
        return self.session_manager.create_session(
            ae, areq, self.user_id, client_id=client_id, sub_type=sub_type
        )

    def test_init(self):
        assert self.endpoint

    def test_parse(self):
        _req = self.endpoint.parse_request(AUTH_REQ_DICT)
        assert isinstance(_req, AuthorizationRequest)
        assert set(_req.keys()) == set(AUTH_REQ.keys())

    def test_process_request(self):
        _pr_resp = self.endpoint.parse_request(AUTH_REQ_DICT)
        _resp = self.endpoint.process_request(_pr_resp)
        assert set(_resp.keys()) == {
            "response_args",
            "fragment_enc",
            "return_uri",
            "cookie",
            "session_id",
        }

    def test_do_response_code(self):
        _pr_resp = self.endpoint.parse_request(AUTH_REQ_DICT)
        _resp = self.endpoint.process_request(_pr_resp)
        msg = self.endpoint.do_response(**_resp)
        assert isinstance(msg, dict)
        _msg = parse_qs(msg["response"])
        assert _msg
        part = urlparse(msg["response"])
        assert part.fragment == ""
        assert part.query
        _query = parse_qs(part.query)
        assert _query
        assert "code" in _query

    def test_do_response_code_token(self):
        """UnAuthorized Client
        """
        _orig_req = AUTH_REQ_DICT.copy()
        _orig_req["response_type"] = "code token"
        msg = ""
        _pr_resp = self.endpoint.parse_request(_orig_req)
        assert isinstance(_pr_resp, AuthorizationErrorResponse)
        assert _pr_resp["error"] == "invalid_request"

    def test_verify_uri_unknown_client(self):
        request = {"redirect_uri": "https://rp.example.com/cb"}
        with pytest.raises(UnknownClient):
            verify_uri(self.endpoint.server_get("endpoint_context"), request, "redirect_uri")

    def test_verify_uri_fragment(self):
        _context = self.endpoint.server_get("endpoint_context")
        _context.cdb["client_id"] = {"redirect_uri": ["https://rp.example.com/auth_cb"]}
        request = {"redirect_uri": "https://rp.example.com/cb#foobar"}
        with pytest.raises(URIError):
            verify_uri(_context, request, "redirect_uri", "client_id")

    def test_verify_uri_noregistered(self):
        _context = self.endpoint.server_get("endpoint_context")
        request = {"redirect_uri": "https://rp.example.com/cb"}

        with pytest.raises(KeyError):
            verify_uri(_context, request, "redirect_uri", "client_id")

    def test_verify_uri_unregistered(self):
        _context = self.endpoint.server_get("endpoint_context")
        _context.cdb["client_id"] = {"redirect_uris": [("https://rp.example.com/auth_cb", {})]}

        request = {"redirect_uri": "https://rp.example.com/cb"}

        with pytest.raises(RedirectURIError):
            verify_uri(_context, request, "redirect_uri", "client_id")

    def test_verify_uri_qp_match(self):
        _context = self.endpoint.server_get("endpoint_context")
        _context.cdb["client_id"] = {
            "redirect_uris": [("https://rp.example.com/cb", {"foo": ["bar"]})]
        }

        request = {"redirect_uri": "https://rp.example.com/cb?foo=bar"}

        verify_uri(_context, request, "redirect_uri", "client_id")

    def test_verify_uri_qp_mismatch(self):
        _context = self.endpoint.server_get("endpoint_context")
        _context.cdb["client_id"] = {
            "redirect_uris": [("https://rp.example.com/cb", {"foo": ["bar"]})]
        }

        request = {"redirect_uri": "https://rp.example.com/cb?foo=bob"}
        with pytest.raises(ValueError):
            verify_uri(_context, request, "redirect_uri", "client_id")

        request = {"redirect_uri": "https://rp.example.com/cb?foo=bar&foo=kex"}
        with pytest.raises(ValueError):
            verify_uri(_context, request, "redirect_uri", "client_id")

        request = {"redirect_uri": "https://rp.example.com/cb"}
        with pytest.raises(ValueError):
            verify_uri(_context, request, "redirect_uri", "client_id")

        request = {"redirect_uri": "https://rp.example.com/cb?foo=bar&level=low"}
        with pytest.raises(ValueError):
            verify_uri(_context, request, "redirect_uri", "client_id")

    def test_verify_uri_qp_missing(self):
        _context = self.endpoint.server_get("endpoint_context")
        _context.cdb["client_id"] = {
            "redirect_uris": [("https://rp.example.com/cb", {"foo": ["bar"], "state": ["low"]})]
        }

        request = {"redirect_uri": "https://rp.example.com/cb?foo=bar"}
        with pytest.raises(ValueError):
            verify_uri(_context, request, "redirect_uri", "client_id")

    def test_verify_uri_qp_missing_val(self):
        _context = self.endpoint.server_get("endpoint_context")
        _context.cdb["client_id"] = {
            "redirect_uris": [("https://rp.example.com/cb", {"foo": ["bar", "low"]})]
        }

        request = {"redirect_uri": "https://rp.example.com/cb?foo=bar"}
        with pytest.raises(ValueError):
            verify_uri(_context, request, "redirect_uri", "client_id")

    def test_verify_uri_no_registered_qp(self):
        _context = self.endpoint.server_get("endpoint_context")
        _context.cdb["client_id"] = {"redirect_uris": [("https://rp.example.com/cb", {})]}

        request = {"redirect_uri": "https://rp.example.com/cb?foo=bob"}
        with pytest.raises(ValueError):
            verify_uri(_context, request, "redirect_uri", "client_id")

    def test_verify_uri_wrong_uri_type(self):
        _context = self.endpoint.server_get("endpoint_context")
        _context.cdb["client_id"] = {"redirect_uris": [("https://rp.example.com/cb", {})]}

        request = {"redirect_uri": "https://rp.example.com/cb?foo=bob"}
        with pytest.raises(ValueError):
            verify_uri(_context, request, "post_logout_redirect_uri", "client_id")

    def test_verify_uri_none_registered(self):
        _context = self.endpoint.server_get("endpoint_context")
        _context.cdb["client_id"] = {
            "post_logout_redirect_uri": [("https://rp.example.com/plrc", {})]
        }

        request = {"redirect_uri": "https://rp.example.com/cb"}
        with pytest.raises(ValueError):
            verify_uri(_context, request, "redirect_uri", "client_id")

    def test_get_uri(self):
        _context = self.endpoint.server_get("endpoint_context")
        _context.cdb["client_id"] = {"redirect_uris": [("https://rp.example.com/cb", {})]}

        request = {
            "redirect_uri": "https://rp.example.com/cb",
            "client_id": "client_id",
        }

        assert get_uri(_context, request, "redirect_uri") == "https://rp.example.com/cb"

    def test_get_uri_no_redirect_uri(self):
        _context = self.endpoint.server_get("endpoint_context")
        _context.cdb["client_id"] = {"redirect_uris": [("https://rp.example.com/cb", {})]}

        request = {"client_id": "client_id"}

        assert get_uri(_context, request, "redirect_uri") == "https://rp.example.com/cb"

    def test_get_uri_no_registered(self):
        _context = self.endpoint.server_get("endpoint_context")
        _context.cdb["client_id"] = {"redirect_uris": [("https://rp.example.com/cb", {})]}

        request = {"client_id": "client_id"}

        with pytest.raises(ParameterError):
            get_uri(_context, request, "post_logout_redirect_uri")

    def test_get_uri_more_then_one_registered(self):
        _context = self.endpoint.server_get("endpoint_context")
        _context.cdb["client_id"] = {
            "redirect_uris": [
                ("https://rp.example.com/cb", {}),
                ("https://rp.example.org/authz_cb", {"foo": "bar"}),
            ]
        }

        request = {"client_id": "client_id"}

        with pytest.raises(ParameterError):
            get_uri(_context, request, "redirect_uri")

    def test_create_authn_response(self):
        request = AuthorizationRequest(
            client_id="client_id",
            redirect_uri="https://rp.example.com/cb",
            response_type=["id_token"],
            state="state",
            nonce="nonce",
            scope="openid",
        )

        self.endpoint.server_get("endpoint_context").cdb["client_id"] = {
            "client_id": "client_id",
            "redirect_uris": [("https://rp.example.com/cb", {})],
            "id_token_signed_response_alg": "ES256",
        }

        session_id = self._create_session(request)

        resp = self.endpoint.create_authn_response(request, session_id)
        assert isinstance(resp["response_args"], AuthorizationErrorResponse)

    def test_setup_auth(self):
        request = AuthorizationRequest(
            client_id="client_id",
            redirect_uri="https://rp.example.com/cb",
            response_type=["id_token"],
            state="state",
            nonce="nonce",
            scope="openid",
        )
        redirect_uri = request["redirect_uri"]
        cinfo = {
            "client_id": "client_id",
            "redirect_uris": [("https://rp.example.com/cb", {})],
            "id_token_signed_response_alg": "RS256",
        }

        kaka = self.endpoint.server_get("endpoint_context").cookie_handler.make_cookie_content(
            "value", "sso"
        )

        res = self.endpoint.setup_auth(request, redirect_uri, cinfo, [kaka])
        assert set(res.keys()) == {"session_id", "identity", "user"}

    def test_setup_auth_error(self):
        request = AuthorizationRequest(
            client_id="client_id",
            redirect_uri="https://rp.example.com/cb",
            response_type=["id_token"],
            state="state",
            nonce="nonce",
            scope="openid",
        )
        redirect_uri = request["redirect_uri"]
        cinfo = {
            "client_id": "client_id",
            "redirect_uris": [("https://rp.example.com/cb", {})],
            "id_token_signed_response_alg": "RS256",
        }

        item = self.endpoint.server_get("endpoint_context").authn_broker.db["anon"]
        item["method"].fail = NoSuchAuthentication

        res = self.endpoint.setup_auth(request, redirect_uri, cinfo, None)
        assert set(res.keys()) == {"function", "args"}

        item["method"].fail = ToOld

        res = self.endpoint.setup_auth(request, redirect_uri, cinfo, None)
        assert set(res.keys()) == {"function", "args"}

        item["method"].file = ""

    def test_setup_auth_invalid_scope(self):
        request = AuthorizationRequest(
            client_id="client_id",
            redirect_uri="https://rp.example.com/cb",
            response_type=["id_token"],
            state="state",
            nonce="nonce",
            scope="openid THAT-BLOODY_SCOPE",
        )
        redirect_uri = request["redirect_uri"]
        cinfo = {
            "client_id": "client_id",
            "redirect_uris": [("https://rp.example.com/cb", {})],
            "id_token_signed_response_alg": "RS256",
        }

        _context = self.endpoint.server_get("endpoint_context")
        _context.cdb["client_id"] = cinfo

        kaka = _context.cookie_handler.make_cookie_content("value", "sso")

        # force to 400 Http Error message if the release scope policy is heavy!
        _context.conf["capabilities"]["deny_unknown_scopes"] = True
        excp = None
        try:
            res = self.endpoint.process_request(request, http_info={"headers": {"cookie": [kaka]}})
        except UnAuthorizedClientScope as e:
            excp = e
        assert excp
        assert isinstance(excp, UnAuthorizedClientScope)

    def test_setup_auth_user(self):
        request = AuthorizationRequest(
            client_id="client_id",
            redirect_uri="https://rp.example.com/cb",
            response_type=["id_token"],
            state="state",
            nonce="nonce",
            scope="openid",
        )
        redirect_uri = request["redirect_uri"]
        cinfo = {
            "client_id": "client_id",
            "redirect_uris": [("https://rp.example.com/cb", {})],
            "id_token_signed_response_alg": "RS256",
        }

        session_id = self._create_session(request)

        item = self.endpoint.server_get("endpoint_context").authn_broker.db["anon"]
        item["method"].user = b64e(as_bytes(json.dumps({"uid": "krall", "sid": session_id})))

        res = self.endpoint.setup_auth(request, redirect_uri, cinfo, None)
        assert set(res.keys()) == {"session_id", "identity", "user"}
        assert res["identity"]["uid"] == "krall"

    def test_setup_auth_session_revoked(self):
        request = AuthorizationRequest(
            client_id="client_id",
            redirect_uri="https://rp.example.com/cb",
            response_type=["id_token"],
            state="state",
            nonce="nonce",
            scope="openid",
        )
        redirect_uri = request["redirect_uri"]
        cinfo = {
            "client_id": "client_id",
            "redirect_uris": [("https://rp.example.com/cb", {})],
            "id_token_signed_response_alg": "RS256",
        }

        session_id = self._create_session(request)

        _context = self.endpoint.server_get("endpoint_context")
        _mngr = _context.session_manager
        _csi = _mngr[session_id]
        _csi.revoked = True

        item = _context.authn_broker.db["anon"]
        item["method"].user = b64e(as_bytes(json.dumps({"uid": "krall", "sid": session_id})))

        res = self.endpoint.setup_auth(request, redirect_uri, cinfo, None)
        assert set(res.keys()) == {"args", "function"}

    def test_response_mode_form_post(self):
        request = {"response_mode": "form_post"}
        info = {
            "response_args": AuthorizationResponse(foo="bar"),
            "return_uri": "https://example.com/cb",
        }
        info = self.endpoint.response_mode(request, **info)
        assert set(info.keys()) == {
            "response_msg",
            "content_type",
            "response_placement",
        }
        assert info["response_msg"] == FORM_POST.format(
            action="https://example.com/cb", inputs='<input type="hidden" name="foo" value="bar"/>',
        )

    def test_response_mode_fragment(self):
        request = {"response_mode": "fragment"}
        self.endpoint.response_mode(request, fragment_enc=True)

        with pytest.raises(InvalidRequest):
            self.endpoint.response_mode(request, fragment_enc=False)

        info = self.endpoint.response_mode(request)
        assert set(info.keys()) == {"return_uri", "response_args", "fragment_enc"}

    def test_req_user(self):
        request = AuthorizationRequest(
            client_id="client_id",
            redirect_uri="https://rp.example.com/cb",
            response_type=["id_token"],
            state="state",
            nonce="nonce",
            scope="openid",
        )
        redirect_uri = request["redirect_uri"]
        cinfo = {
            "client_id": "client_id",
            "redirect_uris": [("https://rp.example.com/cb", {})],
            "id_token_signed_response_alg": "RS256",
        }
        res = self.endpoint.setup_auth(request, redirect_uri, cinfo, None, req_user="******")
        assert "function" in res

    def test_req_user_no_prompt(self):
        request = AuthorizationRequest(
            client_id="client_id",
            redirect_uri="https://rp.example.com/cb",
            response_type=["id_token"],
            state="state",
            nonce="nonce",
            scope="openid",
            prompt="none",
        )
        redirect_uri = request["redirect_uri"]
        cinfo = {
            "client_id": "client_id",
            "redirect_uris": [("https://rp.example.com/cb", {})],
            "id_token_signed_response_alg": "RS256",
        }
        res = self.endpoint.setup_auth(request, redirect_uri, cinfo, None, req_user="******")
        assert "error" in res