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"
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.client = Client("1") # pylint: disable=attribute-defined-outside-init self.client.redirect_uris = [self.redirect_uri] self.client.response_type = "code" self.client.authorization_endpoint = self.authorization_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): self.client.response_type = ["code"] 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_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.expires_in == 3600 assert token.refresh_token == "tGzv3JOkF0XG5Qx2TlKWIA" # I'm dropping parameters I don't recognize # with pytest.raises(AttributeError): # TODO not satisfied # nothing = token.example_parameter 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 assert self.client.grant_from_state("state").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"]) assert req["foo"] == "bar" def test_construct_TokenRevocationRequest(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) state = "foo" query = "code=SplxlOBeZQQYbYS6WxSbIA&state={}".format(state) self.client.parse_response(AuthorizationResponse, info=query, sformat="urlencoded") req = self.client.construct_TokenRevocationRequest(state=state) assert _eq(req.keys(), ["token"]) assert req["token"] == "access" 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) # default == "POST" 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(ValueError): self.client.parse_response(AccessTokenResponse, info=uerr) with pytest.raises(FormatError): self.client.parse_response(AccessTokenResponse, info=jerr, sformat="focus") 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")
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.client = Client("1", config={'issuer': 'https://example.com/as'}) self.client.redirect_uris = [self.redirect_uri] self.client.response_type = "code" self.client.authorization_endpoint = self.authorization_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): self.client.response_type = ["code"] 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_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.expires_in == 3600 assert token.refresh_token == "tGzv3JOkF0XG5Qx2TlKWIA" # I'm dropping parameters I don't recognize # with pytest.raises(AttributeError): # TODO not satisfied # nothing = token.example_parameter 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 assert self.client.grant_from_state("state").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_construct_TokenRevocationRequest(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) # # state = "foo" # query = "code=SplxlOBeZQQYbYS6WxSbIA&state={}".format(state) # self.client.parse_response(AuthorizationResponse, # info=query, sformat="urlencoded") # # req = self.client.construct_TokenRevocationRequest(state=state) # assert _eq(req.keys(), ['token']) # assert req["token"] == "access" 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) # default == "POST" 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(ValueError): self.client.parse_response(AccessTokenResponse, info=uerr) with pytest.raises(FormatError): self.client.parse_response(AccessTokenResponse, info=jerr, sformat="focus") 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")
class TestOAuthClient(): def setup_class(self): self.client = Client("1") self.client.redirect_uris = ["http://example.com/redirect"] def test_areq_1(self): ar = self.client.construct_AuthorizationRequest( request_args={"response_type": ["code"]}) assert ar["redirect_uri"] == "http://example.com/redirect" assert ar["response_type"] == ["code"] assert ar["client_id"] == "1" assert "state" not in ar assert "scope" not in ar def test_areq_2(self): self.client.state = "abc" req_args = {"response_type": ["code"], "scope": ["foo", "bar"]} ar = self.client.construct_AuthorizationRequest(request_args=req_args) assert ar["redirect_uri"] == "http://example.com/redirect" assert ar["response_type"] == ["code"] assert ar["client_id"] == "1" assert ar["state"] == "abc" assert ar["scope"] == ["foo", "bar"] def test_areq_replace_default_state(self): self.client.state = "efg" req_args = {"response_type": ["code"], "scope": ["foo", "bar"]} ar = self.client.construct_AuthorizationRequest(request_args=req_args) assert ar["redirect_uri"] == "http://example.com/redirect" assert ar["response_type"] == ["code"] assert ar["client_id"] == "1" assert ar["state"] == "efg" assert ar["scope"] == ["foo", "bar"] def test_parse_authz_resp_url(self): url = "https://client.example.com/cb?code=SplxlOBeZQQYbYS6WxSbIA&state=ghi" aresp = self.client.parse_response(AuthorizationResponse, info=url, sformat="urlencoded") assert aresp["code"] == "SplxlOBeZQQYbYS6WxSbIA" assert aresp["state"] == "ghi" assert self.client.grant["ghi"] assert self.client.grant["ghi"].code == aresp["code"] assert self.client.grant["ghi"].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" print self.client.grant.keys() 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): query = "code=SplxlOBeZQQYbYS6WxAAAA&state=klm" aresp = self.client.parse_response(AuthorizationResponse, info=query, sformat="urlencoded") assert aresp["code"] == "SplxlOBeZQQYbYS6WxAAAA" assert aresp["state"] == "klm" assert self.client.grant["klm"] assert self.client.grant["klm"].code == aresp["code"] assert self.client.grant["klm"].grant_expiration_time assert _eq(self.client.grant.keys(), ['ghi', 'hij', 'klm']) 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" print aresp.__dict__.keys() assert "foo" not in aresp.__dict__ assert self.client.grant["xyz"] assert self.client.grant["xyz"].code == aresp["code"] assert self.client.grant["xyz"].grant_expiration_time def test_get_access_token_request_1(self): self.client.reset() self.client.redirect_uris = ["http://client.example.com/authz"] 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"] == "http://client.example.com/authz" def test_construct_access_token_request_fail(self): raises(Exception, 'self.client.construct_AccessTokenRequest(state="unknown")') def test_get_access_token_request_override(self): self.client.reset() self.client.redirect_uris = ["http://client.example.com/authz"] 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"] == "http://client.example.com/authz" def test_construct_request_no_input(self): self.client.response_type = ["code"] atr = self.client.construct_AuthorizationRequest() print atr assert atr["redirect_uri"] == "http://client.example.com/authz" assert atr["response_type"] == ["code"] assert atr["client_id"] == "1" def test_parse_access_token_response(self): jso = """{ "access_token":"2YotnFZFEjr1zCsicMWpAA", "token_type":"example", "expires_in":3600, "refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA", "example_parameter":"example_value" }""" self.client.parse_response(AccessTokenResponse, info="".join([ x.strip() for x in jso.split("\n")])) assert self.client.grant _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.expires_in == 3600 assert token.refresh_token == "tGzv3JOkF0XG5Qx2TlKWIA" # I'm dropping parameters I don't recognize assert "example_parameter" not in self.client.__dict__ #assert self.client.access_token_is_valid() def test_get_access_token_refresh_1(self): print self.client.grant self.client.grant[""].grant_expiration_time = time.time() + 60 self.client.grant[""].code = "access_code" token = self.client.grant[""].tokens[0] print token # Uses refresh_token from previous response atr = self.client.construct_RefreshAccessTokenRequest(token=token) print atr.to_dict() assert atr.type() == "RefreshAccessTokenRequest" assert atr["grant_type"] == "refresh_token" assert atr["refresh_token"] == "tGzv3JOkF0XG5Qx2TlKWIA" def test_get_access_token_refresh_2(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" print self.client.grant["foo"] 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 atr.type() == "RefreshAccessTokenRequest" assert atr["grant_type"] == "refresh_token" assert atr["refresh_token"] == "refresh_with_me" def test_parse_authz_err_response(self): ruri = "https://client.example.com/cb?error=access_denied&state=xyz" resp = self.client.parse_response(AuthorizationResponse, info=ruri, sformat="urlencoded") print type(resp), resp assert resp.type() == "AuthorizationErrorResponse" assert resp["error"] == "access_denied" assert resp["state"] == "xyz" def test_return_non_existant_grant(self): assert self.client.grant_from_state("123456abcdef") is None def test_construct_request_with_extra_args(self): print self.client.__dict__.items() req = self.client.construct_AccessTokenRequest( state="foo", extra_args={"foo": "bar"}) assert req print req.keys() assert _eq(req.keys(), ['code', 'grant_type', 'client_id', 'redirect_uri', 'foo']) assert req["foo"] == "bar" def test_construct_TokenRevocationRequest(self): req = self.client.construct_TokenRevocationRequest(state="foo") assert req print req.keys() assert _eq(req.keys(), ['token']) assert req["token"] == "access" def test_request_info_simple(self): self.client.authorization_endpoint = "https://example.com/authz" uri, body, h_args, cis = self.client.request_info(AuthorizationRequest) # default == "POST" assert uri == 'https://example.com/authz' assert body == "redirect_uri=http%3A%2F%2Fclient.example.com%2Fauthz&response_type=code&client_id=1" assert h_args == {'headers': {'content-type': 'application/x-www-form-urlencoded'}} assert cis.type() == "AuthorizationRequest" def test_request_info_simple_get(self): #self.client.authorization_endpoint = "https://example.com/authz" uri, body, h_args, cis = self.client.request_info(AuthorizationRequest, method="GET") assert uri == 'https://example.com/authz?redirect_uri=http%3A%2F%2Fclient.example.com%2Fauthz&response_type=code&client_id=1' assert body is None assert h_args == {} assert cis.type() == "AuthorizationRequest" def test_request_info_simple_get_with_req_args(self): #self.client.authorization_endpoint = "https://example.com/authz" uri, body, h_args, cis = self.client.request_info( AuthorizationRequest, method="GET", request_args={"state": "init"}) print uri assert uri == 'https://example.com/authz?state=init&redirect_uri=http%3A%2F%2Fclient.example.com%2Fauthz&response_type=code&client_id=1' assert body is None assert h_args == {} assert cis.type() == "AuthorizationRequest" def test_request_info_simple_get_with_extra_args(self): #self.client.authorization_endpoint = "https://example.com/authz" uri, body, h_args, cis = self.client.request_info( AuthorizationRequest, method="GET", extra_args={"rock": "little"}) print uri assert uri == 'https://example.com/authz?redirect_uri=http%3A%2F%2Fclient.example.com%2Fauthz&response_type=code&client_id=1&rock=little' assert body is None assert h_args == {} assert cis.type() == "AuthorizationRequest" def test_request_info_with_req_and_extra_args(self): #self.client.authorization_endpoint = "https://example.com/authz" uri, body, h_args, cis = self.client.request_info( AuthorizationRequest, method="GET", request_args={"state": "init"}, extra_args={"rock": "little"}) print uri assert uri == 'https://example.com/authz?state=init&redirect_uri=http%3A%2F%2Fclient.example.com%2Fauthz&response_type=code&client_id=1&rock=little' assert body is None assert h_args == {} assert cis.type() == "AuthorizationRequest"
class TestOAuthClient(): def setup_class(self): self.client = Client("1") self.client.redirect_uris = ["http://example.com/redirect"] def test_areq_1(self): ar = self.client.construct_AuthorizationRequest( request_args={"response_type": ["code"]}) assert ar["redirect_uri"] == "http://example.com/redirect" assert ar["response_type"] == ["code"] assert ar["client_id"] == "1" assert "state" not in ar assert "scope" not in ar def test_areq_2(self): self.client.state = "abc" req_args = {"response_type": ["code"], "scope": ["foo", "bar"]} ar = self.client.construct_AuthorizationRequest(request_args=req_args) assert ar["redirect_uri"] == "http://example.com/redirect" assert ar["response_type"] == ["code"] assert ar["client_id"] == "1" assert ar["state"] == "abc" assert ar["scope"] == ["foo", "bar"] def test_areq_replace_default_state(self): self.client.state = "efg" req_args = {"response_type": ["code"], "scope": ["foo", "bar"]} ar = self.client.construct_AuthorizationRequest(request_args=req_args) assert ar["redirect_uri"] == "http://example.com/redirect" assert ar["response_type"] == ["code"] assert ar["client_id"] == "1" assert ar["state"] == "efg" assert ar["scope"] == ["foo", "bar"] def test_parse_authz_resp_url(self): url = "https://client.example.com/cb?code=SplxlOBeZQQYbYS6WxSbIA&state=ghi" aresp = self.client.parse_response(AuthorizationResponse, info=url, sformat="urlencoded") assert aresp["code"] == "SplxlOBeZQQYbYS6WxSbIA" assert aresp["state"] == "ghi" assert self.client.grant["ghi"] assert self.client.grant["ghi"].code == aresp["code"] assert self.client.grant["ghi"].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" print self.client.grant.keys() 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): query = "code=SplxlOBeZQQYbYS6WxAAAA&state=klm" aresp = self.client.parse_response(AuthorizationResponse, info=query, sformat="urlencoded") assert aresp["code"] == "SplxlOBeZQQYbYS6WxAAAA" assert aresp["state"] == "klm" assert self.client.grant["klm"] assert self.client.grant["klm"].code == aresp["code"] assert self.client.grant["klm"].grant_expiration_time assert _eq(self.client.grant.keys(), ['ghi', 'hij', 'klm']) 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" print aresp.__dict__.keys() assert "foo" not in aresp.__dict__ assert self.client.grant["xyz"] assert self.client.grant["xyz"].code == aresp["code"] assert self.client.grant["xyz"].grant_expiration_time def test_get_access_token_request_1(self): self.client.reset() self.client.redirect_uris = ["http://client.example.com/authz"] 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"] == "http://client.example.com/authz" def test_construct_access_token_request_fail(self): raises(Exception, 'self.client.construct_AccessTokenRequest(state="unknown")') def test_get_access_token_request_override(self): self.client.reset() self.client.redirect_uris = ["http://client.example.com/authz"] 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"] == "http://client.example.com/authz" def test_construct_request_no_input(self): self.client.response_type = ["code"] atr = self.client.construct_AuthorizationRequest() print atr assert atr["redirect_uri"] == "http://client.example.com/authz" assert atr["response_type"] == ["code"] assert atr["client_id"] == "1" def test_parse_access_token_response(self): jso = """{ "access_token":"2YotnFZFEjr1zCsicMWpAA", "token_type":"example", "expires_in":3600, "refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA", "example_parameter":"example_value" }""" self.client.parse_response(AccessTokenResponse, info="".join( [x.strip() for x in jso.split("\n")])) assert self.client.grant _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.expires_in == 3600 assert token.refresh_token == "tGzv3JOkF0XG5Qx2TlKWIA" # I'm dropping parameters I don't recognize assert "example_parameter" not in self.client.__dict__ #assert self.client.access_token_is_valid() def test_get_access_token_refresh_1(self): print self.client.grant self.client.grant[""].grant_expiration_time = time.time() + 60 self.client.grant[""].code = "access_code" token = self.client.grant[""].tokens[0] print token # Uses refresh_token from previous response atr = self.client.construct_RefreshAccessTokenRequest(token=token) print atr.to_dict() assert atr.type() == "RefreshAccessTokenRequest" assert atr["grant_type"] == "refresh_token" assert atr["refresh_token"] == "tGzv3JOkF0XG5Qx2TlKWIA" def test_get_access_token_refresh_2(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" print self.client.grant["foo"] 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 atr.type() == "RefreshAccessTokenRequest" assert atr["grant_type"] == "refresh_token" assert atr["refresh_token"] == "refresh_with_me" def test_parse_authz_err_response(self): ruri = "https://client.example.com/cb?error=access_denied&state=xyz" resp = self.client.parse_response(AuthorizationResponse, info=ruri, sformat="urlencoded") print type(resp), resp assert resp.type() == "AuthorizationErrorResponse" assert resp["error"] == "access_denied" assert resp["state"] == "xyz" def test_return_non_existant_grant(self): assert self.client.grant_from_state("123456abcdef") is None def test_construct_request_with_extra_args(self): print self.client.__dict__.items() req = self.client.construct_AccessTokenRequest( state="foo", extra_args={"foo": "bar"}) assert req print req.keys() assert _eq(req.keys(), ['code', 'grant_type', 'client_id', 'redirect_uri', 'foo']) assert req["foo"] == "bar" def test_construct_TokenRevocationRequest(self): req = self.client.construct_TokenRevocationRequest(state="foo") assert req print req.keys() assert _eq(req.keys(), ['token']) assert req["token"] == "access" def test_request_info_simple(self): self.client.authorization_endpoint = "https://example.com/authz" uri, body, h_args, cis = self.client.request_info(AuthorizationRequest) # default == "POST" assert uri == 'https://example.com/authz' assert body == "redirect_uri=http%3A%2F%2Fclient.example.com%2Fauthz&response_type=code&client_id=1" assert h_args == { 'headers': { 'Content-type': 'application/x-www-form-urlencoded' } } assert cis.type() == "AuthorizationRequest" def test_request_info_simple_get(self): #self.client.authorization_endpoint = "https://example.com/authz" uri, body, h_args, cis = self.client.request_info(AuthorizationRequest, method="GET") assert uri == 'https://example.com/authz?redirect_uri=http%3A%2F%2Fclient.example.com%2Fauthz&response_type=code&client_id=1' assert body is None assert h_args == {} assert cis.type() == "AuthorizationRequest" def test_request_info_simple_get_with_req_args(self): #self.client.authorization_endpoint = "https://example.com/authz" uri, body, h_args, cis = self.client.request_info( AuthorizationRequest, method="GET", request_args={"state": "init"}) print uri assert uri == 'https://example.com/authz?state=init&redirect_uri=http%3A%2F%2Fclient.example.com%2Fauthz&response_type=code&client_id=1' assert body is None assert h_args == {} assert cis.type() == "AuthorizationRequest" def test_request_info_simple_get_with_extra_args(self): #self.client.authorization_endpoint = "https://example.com/authz" uri, body, h_args, cis = self.client.request_info( AuthorizationRequest, method="GET", extra_args={"rock": "little"}) print uri assert uri == 'https://example.com/authz?redirect_uri=http%3A%2F%2Fclient.example.com%2Fauthz&response_type=code&client_id=1&rock=little' assert body is None assert h_args == {} assert cis.type() == "AuthorizationRequest" def test_request_info_with_req_and_extra_args(self): #self.client.authorization_endpoint = "https://example.com/authz" uri, body, h_args, cis = self.client.request_info( AuthorizationRequest, method="GET", request_args={"state": "init"}, extra_args={"rock": "little"}) print uri assert uri == 'https://example.com/authz?state=init&redirect_uri=http%3A%2F%2Fclient.example.com%2Fauthz&response_type=code&client_id=1&rock=little' assert body is None assert h_args == {} assert cis.type() == "AuthorizationRequest"