コード例 #1
0
ファイル: __init__.py プロジェクト: HaToHo/IdPproxy
    def phaseN(self, environ, info, server_env, sid):
        session = server_env["CACHE"][sid]

        callback = server_env["base_url"] + self.social_endpoint

        client = Client(client_id=self.client_id,
                        client_authn_method=CLIENT_AUTHN_METHOD)
        response = client.parse_response(AuthorizationResponse, info, "dict")
        logger.info("Response: %s" % response)

        if isinstance(response, ErrorResponse):
            logger.info("%s" % response)
            session["authentication"] = "FAILED"
            return False, "Authentication failed or permission not granted"

        req_args = {
            "redirect_uri": callback,
            "client_secret": self.client_secret,
        }

        client.token_endpoint = self.extra["token_endpoint"]
        tokenresp = client.do_access_token_request(
            scope=self._scope,
            body_type=self.token_response_body_type,
            request_args=req_args,
            authn_method="client_secret_post",
            state=response["state"],
            response_cls=self.access_token_response)

        if isinstance(tokenresp, ErrorResponse):
            logger.info("%s" % tokenresp)
            session["authentication"] = "FAILED"
            return False, "Authentication failed or permission not granted"

        # Download the user profile and cache a local instance of the
        # basic profile info
        result = client.fetch_protected_resource(
            self.userinfo_endpoint(tokenresp), token=tokenresp["access_token"])

        logger.info("Userinfo: %s" % result.text)
        root = ET.fromstring(result.text)
        jsontext = json.dumps(root.attrib)
        profile = json.loads(jsontext)
        profile = self.convert(profile)
        logger.info("PROFILE: %s" % (profile, ))
        session["service"] = self.name
        session["authentication"] = "OK"
        session["status"] = "SUCCESS"
        session["authn_auth"] = self.authenticating_authority
        session["permanent_id"] = profile["uid"]

        server_env["CACHE"][sid] = session

        return True, profile, session
コード例 #2
0
    def phaseN(self, environ, info, server_env, sid):
        session = server_env["CACHE"][sid]

        callback = server_env["base_url"] + self.social_endpoint

        client = Client(client_id=self.client_id,
                        client_authn_method=CLIENT_AUTHN_METHOD)
        response = client.parse_response(AuthorizationResponse, info, "dict")
        logger.info("Response: %s" % response)

        if isinstance(response, ErrorResponse):
            logger.info("%s" % response)
            session["authentication"] = "FAILED"
            return False, "Authentication failed or permission not granted"

        req_args = {
            "redirect_uri": callback,
            "client_secret": self.client_secret,
        }

        client.token_endpoint = self.extra["token_endpoint"]
        tokenresp = client.do_access_token_request(
            scope=self._scope,
            body_type=self.token_response_body_type,
            request_args=req_args,
            authn_method="client_secret_post",
            state=response["state"],
            response_cls=self.access_token_response)

        if isinstance(tokenresp, ErrorResponse):
            logger.info("%s" % tokenresp)
            session["authentication"] = "FAILED"
            return False, "Authentication failed or permission not granted"

        # Download the user profile and cache a local instance of the
        # basic profile info
        result = client.fetch_protected_resource(
            self.userinfo_endpoint(tokenresp), token=tokenresp["access_token"])

        logger.info("Userinfo: %s" % result.text)
        profile = json.loads(result.text)

        logger.info("PROFILE: %s" % (profile, ))
        session["service"] = self.name
        session["authentication"] = "OK"
        session["status"] = "SUCCESS"
        session["authn_auth"] = self.authenticating_authority
        session["permanent_id"] = profile["id"]

        server_env["CACHE"][sid] = session

        return True, self.convert(profile), session
コード例 #3
0
ファイル: __init__.py プロジェクト: dash-dash/pyoidc
    def phaseN(self, environ, query, server_env, session):
        callback = server_env["base_url"] + self.opKey

        client = Client(client_id=self.client_id,
                        client_authn_method=CLIENT_AUTHN_METHOD)
        response = client.parse_response(AuthorizationResponse, query, "dict")
        logger.info("Response: %s" % response)

        if isinstance(response, ErrorResponse):
            logger.info("%s" % response)
            return (False, "Authentication failed or permission not granted")

        req_args = {
            "redirect_uri": callback,
            "client_secret": self.client_secret,
        }

        client.token_endpoint = self.extra["token_endpoint"]
        tokenresp = client.do_access_token_request(
            scope=self._scope,
            body_type=self.token_response_body_type,
            request_args=req_args,
            authn_method="client_secret_post",
            state=response["state"],
            response_cls=self.access_token_response)

        if isinstance(tokenresp, ErrorResponse):
            logger.info("%s" % tokenresp)
            return (False, "Authentication failed or permission not granted")

        # Download the user profile and cache a local instance of the
        # basic profile info
        result = client.fetch_protected_resource(
            self.userinfo_endpoint(tokenresp), token=tokenresp["access_token"])

        logger.info("Userinfo: %s" % result.text)
        profile = json.loads(result.text)

        return True, profile, tokenresp["access_token"], client
コード例 #4
0
class TestClient(object):
    @pytest.fixture(autouse=True)
    def create_client(self):
        self.redirect_uri = "https://example.com/redirect"
        self.authorization_endpoint = "https://example.com/authz"
        self.token_endpoint = "https://example.com/token"

        self.client = Client("1", config={"issuer": "https://example.com/as"})
        self.client.redirect_uris = [self.redirect_uri]
        self.client.authorization_endpoint = self.authorization_endpoint
        self.client.token_endpoint = self.token_endpoint

    def test_construct_authz_req_no_optional_params(self):
        areq = self.client.construct_AuthorizationRequest(
            request_args={"response_type": ["code"]})

        assert areq["redirect_uri"] == self.redirect_uri
        assert areq["response_type"] == ["code"]
        assert areq["client_id"] == "1"
        assert "state" not in areq
        assert "scope" not in areq

    def test_construct_authz_req_no_input(self):
        atr = self.client.construct_AuthorizationRequest()

        assert atr["redirect_uri"] == self.redirect_uri
        assert atr["response_type"] == ["code"]
        assert atr["client_id"] == "1"

    def test_construct_authz_req_optional_params(self):
        req_args = {
            "response_type": ["code"],
            "scope": ["foo", "bar"],
            "state": "abc"
        }
        areq = self.client.construct_AuthorizationRequest(
            request_args=req_args)

        assert areq["redirect_uri"] == self.redirect_uri
        assert areq["response_type"] == ["code"]
        assert areq["client_id"] == "1"
        assert areq["state"] == "abc"
        assert areq["scope"] == ["foo", "bar"]

    def test_construct_authz_req_replace_default_state(self):
        req_args = {
            "response_type": ["code"],
            "scope": ["foo", "bar"],
            "state": "efg"
        }
        areq = self.client.construct_AuthorizationRequest(
            request_args=req_args)

        assert areq["redirect_uri"] == self.redirect_uri
        assert areq["response_type"] == ["code"]
        assert areq["client_id"] == "1"
        assert areq["state"] == "efg"
        assert areq["scope"] == ["foo", "bar"]

    def test_parse_authz_resp_url(self):
        code = "SplxlOBeZQQYbYS6WxSbIA"
        state = "ghi"
        url = "{}?code={}&state={}".format(self.redirect_uri, code, state)
        aresp = self.client.parse_response(AuthorizationResponse,
                                           info=url,
                                           sformat="urlencoded")

        assert aresp["code"] == code
        assert aresp["state"] == state

        assert self.client.grant[state].code == aresp["code"]
        assert self.client.grant[state].grant_expiration_time

    def test_parse_authz_resp_query(self):
        query = "code=SplxlOBeZQQYbYS6WxSbIA&state=hij"
        aresp = self.client.parse_response(AuthorizationResponse,
                                           info=query,
                                           sformat="urlencoded")

        assert aresp["code"] == "SplxlOBeZQQYbYS6WxSbIA"
        assert aresp["state"] == "hij"

        assert self.client.grant["hij"]
        assert self.client.grant["hij"].code == aresp["code"]
        assert self.client.grant["hij"].grant_expiration_time

    def test_parse_authz_resp_query_multi_scope(self):
        code = "SplxlOBeZQQYbYS6WxSbIA"
        states = ["ghi", "hij", "klm"]

        for state in states:
            self.client.parse_response(
                AuthorizationResponse,
                info="code={}&state={}".format(code, state),
                sformat="urlencoded",
            )

        for state in states:
            assert self.client.grant[state].code == code

        assert _eq(self.client.grant.keys(), states)

    def test_parse_authz_resp_query_unknown_parameter(self):
        query = "code=SplxlOBeZQQYbYS6WxSbIA&state=xyz&foo=bar"
        aresp = self.client.parse_response(AuthorizationResponse,
                                           info=query,
                                           sformat="urlencoded")

        assert aresp["code"] == "SplxlOBeZQQYbYS6WxSbIA"
        assert aresp["state"] == "xyz"

        # assert "foo" not in aresp # TODO unknown parameter not discarded

        assert self.client.grant["xyz"]
        assert self.client.grant["xyz"].code == aresp["code"]
        assert self.client.grant["xyz"].grant_expiration_time

    def test_construct_access_token_req(self):
        grant = Grant()
        grant.code = "AbCdEf"
        grant.grant_expiration_time = time_util.utc_time_sans_frac() + 30
        self.client.grant = {"stat": grant}

        # scope is default=""
        atr = self.client.construct_AccessTokenRequest(state="stat")

        assert atr["grant_type"] == "authorization_code"
        assert atr["code"] == "AbCdEf"
        assert atr["redirect_uri"] == self.redirect_uri

    def test_construct_access_token_req_client_credentials(self):
        # scope is default=""
        request_args = {"grant_type": "client_credentials"}
        atr = self.client.construct_AccessTokenRequest(
            state="stat",
            request=CCAccessTokenRequest,
            request_args=request_args)

        assert atr["grant_type"] == "client_credentials"
        assert atr["state"] == "stat"

    def test_construct_access_token_req_extension_grant(self):
        request_args = {
            "grant_type": "urn:ietf:params:oauth:grant-type:saml2-bearer",
            "assertion": "saml assertion",
        }
        atr = self.client.construct_AccessTokenRequest(
            request=ExtensionTokenRequest, request_args=request_args)
        assert atr[
            "grant_type"] == "urn:ietf:params:oauth:grant-type:saml2-bearer"
        assert atr["assertion"] == "saml assertion"

    def test_construct_access_token_request_fail(self):
        with pytest.raises(GrantError):
            self.client.construct_AccessTokenRequest(state="unknown")

    def test_construct_access_token_req_override(self):
        grant = Grant()
        grant.code = "AbCdEf"
        grant.grant_expiration_time = time_util.utc_time_sans_frac() + 30
        self.client.grant = {"xyz": grant}

        atr = self.client.construct_AccessTokenRequest(state="xyz")

        assert atr["grant_type"] == "authorization_code"
        assert atr["code"] == "AbCdEf"
        assert atr["redirect_uri"] == self.redirect_uri

    def test_parse_access_token_resp(self):
        atr = AccessTokenResponse(
            access_token="2YotnFZFEjr1zCsicMWpAA",
            token_type="example",
            expires_in=3600,
            refresh_token="tGzv3JOkF0XG5Qx2TlKWIA",
            example_parameter="example_value",
        )

        self.client.parse_response(AccessTokenResponse,
                                   info=json.dumps(atr.to_dict()))

        _grant = self.client.grant[""]
        assert len(_grant.tokens) == 1
        token = _grant.tokens[0]
        assert token.access_token == "2YotnFZFEjr1zCsicMWpAA"
        assert token.token_type == "example"
        assert token.token_expiration_time > time_util.time_sans_frac()
        assert token.refresh_token == "tGzv3JOkF0XG5Qx2TlKWIA"

    def test_get_access_token_refresh_with_refresh_token(self):
        self.client.grant["foo"] = Grant()
        _get = time_util.utc_time_sans_frac() + 60
        self.client.grant["foo"].grant_expiration_time = _get
        self.client.grant["foo"].code = "access_code"
        resp = AccessTokenResponse(refresh_token="refresh_with_me",
                                   access_token="access")
        token = Token(resp)
        self.client.grant["foo"].tokens.append(token)

        # Uses refresh_token from previous response
        atr = self.client.construct_RefreshAccessTokenRequest(token=token)

        assert atr["grant_type"] == "refresh_token"
        assert atr["refresh_token"] == "refresh_with_me"

    def test_get_access_token_refresh_from_state(self):
        self.client.grant["foo"] = Grant()
        _get = time_util.utc_time_sans_frac() + 60
        self.client.grant["foo"].grant_expiration_time = _get
        self.client.grant["foo"].code = "access_code"

        resp = AccessTokenResponse(refresh_token="refresh_with_me",
                                   access_token="access")

        self.client.grant["foo"].tokens.append(Token(resp))
        # Uses refresh_token from previous response
        atr = self.client.construct_RefreshAccessTokenRequest(state="foo")

        assert isinstance(atr, RefreshAccessTokenRequest)
        assert atr["grant_type"] == "refresh_token"
        assert atr["refresh_token"] == "refresh_with_me"

    def test_parse_authz_err_resp(self):
        error = "access_denied"
        state = "xyz"
        ruri = "{}?error={}&state={}".format(self.redirect_uri, error, state)

        resp = self.client.parse_response(AuthorizationResponse,
                                          info=ruri,
                                          sformat="urlencoded")

        assert isinstance(resp, AuthorizationErrorResponse)
        assert resp["error"] == error
        assert resp["state"] == state

    def test_return_non_existant_grant(self):
        assert self.client.grant_from_state("123456abcdef") is None

    def test_get_grant(self):
        resp = AuthorizationResponse(code="code", state="state")
        grant = Grant()
        grant.add_code(resp)

        self.client.grant["state"] = grant
        new_grant = self.client.grant_from_state("state")
        assert new_grant is not None
        assert new_grant.code == "code"

    def test_construct_access_token_req_with_extra_args(self):
        query = "code=SplxlOBeZQQYbYS6WxSbIA&state=abc"
        self.client.parse_response(AuthorizationResponse,
                                   info=query,
                                   sformat="urlencoded")

        req = self.client.construct_AccessTokenRequest(
            state="abc", extra_args={"foo": "bar"})

        assert _eq(
            req.keys(),
            [
                "code", "grant_type", "client_id", "redirect_uri", "foo",
                "state"
            ],
        )
        assert req["foo"] == "bar"

    def test_request_info_simple(self):
        req_args = {"state": "hmm", "response_type": "code"}
        uri, body, h_args, cis = self.client.request_info(
            AuthorizationRequest, request_args=req_args)

        assert uri == self.authorization_endpoint
        body_elts = body.split("&")
        expected_body = (
            "state=hmm&redirect_uri={}&response_type=code&client_id=1".format(
                quote(self.redirect_uri, safe="")))
        expected_body_elts = expected_body.split("&")
        assert set(body_elts) == set(expected_body_elts)
        assert h_args == {
            "headers": {
                "Content-Type": "application/x-www-form-urlencoded"
            }
        }
        assert isinstance(cis, AuthorizationRequest)

    def test_request_info_simple_get(self):
        uri, body, h_args, cis = self.client.request_info(AuthorizationRequest,
                                                          method="GET")
        assert url_compare(
            uri,
            "{}?redirect_uri={}&response_type=code&client_id=1".format(
                self.authorization_endpoint, quote(self.redirect_uri,
                                                   safe="")),
        )
        assert body is None
        assert h_args == {}

    def test_request_info_simple_get_with_req_args(self):
        uri, body, h_args, cis = self.client.request_info(
            AuthorizationRequest, method="GET", request_args={"state": "init"})

        assert url_compare(
            uri,
            "{}?state=init&redirect_uri={}&response_type=code&client_id=1".
            format(self.authorization_endpoint,
                   quote(self.redirect_uri, safe="")),
        )
        assert body is None
        assert h_args == {}
        assert isinstance(cis, AuthorizationRequest)

    def test_request_info_simple_get_with_extra_args(self):
        uri, body, h_args, cis = self.client.request_info(
            AuthorizationRequest, method="GET", extra_args={"rock": "little"})

        assert url_compare(
            uri,
            "{}?redirect_uri={}&response_type=code&client_id=1&rock=little".
            format(self.authorization_endpoint,
                   quote(self.redirect_uri, safe="")),
        )
        assert body is None
        assert h_args == {}
        assert isinstance(cis, AuthorizationRequest)

    def test_request_info_with_req_and_extra_args(self):
        uri, body, h_args, cis = self.client.request_info(
            AuthorizationRequest,
            method="GET",
            request_args={"state": "init"},
            extra_args={"rock": "little"},
        )

        expected = (
            "{}?state=init&redirect_uri={}&response_type=code&client_id=1&rock=little"
        )
        assert url_compare(
            uri,
            expected.format(self.authorization_endpoint,
                            quote(self.redirect_uri, safe="")),
        )
        assert body is None
        assert h_args == {}
        assert isinstance(cis, AuthorizationRequest)

    def test_construct_access_token_req_expired_grant(self):
        resp = AuthorizationResponse(code="code", state="state")
        grant = Grant(-10)  # expired grant
        grant.add_code(resp)

        client = Client()
        client.grant["openid"] = grant
        with pytest.raises(GrantExpired):
            client.construct_AccessTokenRequest(state="openid")

    def test_parse_access_token_resp_json(self):
        atr = self.client.parse_response(AccessTokenResponse,
                                         info=ACC_TOK_RESP.to_json())
        assert _eq(atr.keys(),
                   ["token_type", "scope", "access_token", "refresh_token"])

    def test_parse_access_token_resp_urlencoded(self):
        uatr = self.client.parse_response(AccessTokenResponse,
                                          info=ACC_TOK_RESP.to_urlencoded(),
                                          sformat="urlencoded")
        assert _eq(uatr.keys(),
                   ["token_type", "scope", "access_token", "refresh_token"])

    def test_parse_access_token_resp_url(self):
        url = "{}?{}".format("https://example.com/token",
                             ACC_TOK_RESP.to_urlencoded())
        uatr = self.client.parse_response(AccessTokenResponse,
                                          info=url,
                                          sformat="urlencoded")
        assert _eq(uatr.keys(),
                   ["token_type", "scope", "access_token", "refresh_token"])

    def test_parse_error_resp(self):
        err = ErrorResponse(
            error="invalid_request",
            error_description="Something was missing",
            error_uri="http://example.com/error_message.html",
        )
        jerr = err.to_json()
        uerr = err.to_urlencoded()

        self.client.parse_response(AccessTokenResponse, info=jerr)
        self.client.parse_response(AccessTokenResponse,
                                   info=uerr,
                                   sformat="urlencoded")

        with pytest.raises(ResponseError):
            self.client.parse_response(AccessTokenResponse,
                                       info=jerr,
                                       sformat="urlencoded")

        with pytest.raises(DecodeError):
            self.client.parse_response(AccessTokenResponse, info=uerr)

        with pytest.raises(FormatError):
            self.client.parse_response(
                AccessTokenResponse,
                info=jerr,
                sformat="focus"  # type: ignore
            )

    def test_parse_access_token_resp_missing_attribute(self):
        atresp = AccessTokenResponse(
            access_token="SlAV32hkKG",
            token_type="Bearer",
            refresh_token="8xLOxBtZp8",
            expire_in=3600,
        )
        atdict = atresp.to_dict()
        del atdict["access_token"]  # remove required access_token
        atj = json.dumps(atdict)

        with pytest.raises(MissingRequiredAttribute):
            self.client.parse_response(AccessTokenResponse, info=atj)

        with pytest.raises(MissingRequiredAttribute):
            self.client.parse_response(AccessTokenResponse,
                                       info=urlencode(atdict),
                                       sformat="urlencoded")

    def test_client_parse_args(self):
        args = {
            "response_type": "",
            "client_id": "client_id",
            "redirect_uri": "http://example.com/authz",
            "scope": "scope",
            "state": "state",
        }

        ar_args = self.client._parse_args(AuthorizationRequest, **args)

        assert _eq(
            ar_args.keys(),
            ["scope", "state", "redirect_uri", "response_type", "client_id"],
        )

    def test_client_parse_extra_args(self):
        args = {
            "response_type": "",
            "client_id": "client_id",
            "redirect_uri": "http://example.com/authz",
            "scope": "scope",
            "state": "state",
            "extra_session": "home",
        }
        ar_args = self.client._parse_args(AuthorizationRequest, **args)

        assert _eq(
            ar_args.keys(),
            [
                "state",
                "redirect_uri",
                "response_type",
                "client_id",
                "scope",
                "extra_session",
            ],
        )

    def test_client_endpoint(self):
        self.client.authorization_endpoint = "https://example.org/oauth2/as"
        self.client.token_endpoint = "https://example.org/oauth2/token"
        self.client.token_revocation_endpoint = "https://example.org/oauth2/token_rev"

        assert (self.client._endpoint("authorization_endpoint") ==
                "https://example.org/oauth2/as")
        assert (self.client._endpoint("token_endpoint") ==
                "https://example.org/oauth2/token")
        assert (self.client._endpoint("token_revocation_endpoint") ==
                "https://example.org/oauth2/token_rev")

        auth_endpoint = self.client._endpoint(
            "authorization_endpoint",
            **{"authorization_endpoint": "https://example.com/as"})
        assert auth_endpoint == "https://example.com/as"

        self.client.token_endpoint = ""
        with pytest.raises(MissingEndpoint):
            self.client._endpoint("token_endpoint")
            self.client._endpoint("foo_endpoint")

    def test_do_access_token_request_client_credentials(self):
        class CCMessageFactory(OauthMessageFactory):
            """We are doing client credentials."""

            token_endpoint = MessageTuple(CCAccessTokenRequest,
                                          AccessTokenResponse)

        self.client.message_factory = CCMessageFactory
        with responses.RequestsMock() as rsps:
            rsps.add(
                rsps.POST,
                self.token_endpoint,
                json={
                    "access_token": "Token",
                    "token_type": "bearer"
                },
            )

            resp = self.client.do_access_token_request()
            assert rsps.calls[
                0].request.body == "grant_type=client_credentials"

        assert isinstance(resp, AccessTokenResponse)
        assert resp["access_token"] == "Token"

    def test_do_access_token_request_extension_grant(self):
        class ExtensionMessageFactory(OauthMessageFactory):
            """We are doing Extension grant."""

            token_endpoint = MessageTuple(ExtensionTokenRequest,
                                          AccessTokenResponse)

        self.client.message_factory = ExtensionMessageFactory
        request_args = {
            "assertion": "saml assertion",
            "grant_type": "urn:ietf:params:oauth:grant-type:saml2-bearer",
        }
        with responses.RequestsMock() as rsps:
            rsps.add(
                rsps.POST,
                self.token_endpoint,
                json={
                    "access_token": "Token",
                    "token_type": "bearer"
                },
            )

            resp = self.client.do_access_token_request(
                request_args=request_args)
            request = parse_qs(rsps.calls[0].request.body)
            assert request["assertion"][0] == "saml assertion"
            assert (request["grant_type"][0] ==
                    "urn:ietf:params:oauth:grant-type:saml2-bearer")

        assert isinstance(resp, AccessTokenResponse)
        assert resp["access_token"] == "Token"