def pat(username: str = None, password: str = None) -> Dict: """ retrieve protection api token (PAT), see `docs <https://www.keycloak.org/docs/latest/authorization_services/#_service_protection_whatis_obtain_pat>`__ for more details >>> >>> from keycloak import Client >>> kc = Client() >>> kc.pat() {'access_token': 'eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJmMTNTUndXVGxRQnFmNmNoamM4SHRtY09sN3NpaTNpaGVXaFNLX0hla280In0.eyJqdGkiOiIzNDliZmQ1ZC1jZDZjLTRjZDAtOTM3Mi1lNzE2N2Y5NGEyMDkiLCJleHAiOjE1ODQxODU0MDcsIm5iZiI6MCwiaWF0IjoxNTg0MTg1MzQ3LCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgwODAvYXV0aC9yZWFsbXMvbWFzdGVyIiwiYXVkIjpbImtleWNsb2FrLWNsaWVudCIsImFjY291bnQiXSwic3ViIjoiNGM5YzI0MzAtYjJlNy00ZjBiLTkzMjUtYWE4MWRmZmUwNDYzIiwidHlwIjoiQmVhcmVyIiwiYXpwIjoia2V5Y2xvYWstY2xpZW50IiwiYXV0aF90aW1lIjowLCJzZXNzaW9uX3N0YXRlIjoiYWY3N2JmOTEtNTQ2ZC00M2E1LTgwZmYtYzQ0MDg2MDVhNTlmIiwiYWNyIjoiMSIsInJlYWxtX2FjY2VzcyI6eyJyb2xlcyI6WyJvZmZsaW5lX2FjY2VzcyIsInVtYV9hdXRob3JpemF0aW9uIl19LCJyZXNvdXJjZV9hY2Nlc3MiOnsia2V5Y2xvYWstY2xpZW50Ijp7InJvbGVzIjpbInVtYV9wcm90ZWN0aW9uIl19LCJhY2NvdW50Ijp7InJvbGVzIjpbIm1hbmFnZS1hY2NvdW50IiwibWFuYWdlLWFjY291bnQtbGlua3MiLCJ2aWV3LXByb2ZpbGUiXX19LCJzY29wZSI6ImVtYWlsIHByb2ZpbGUiLCJjbGllbnRJZCI6ImtleWNsb2FrLWNsaWVudCIsImVtYWlsX3ZlcmlmaWVkIjpmYWxzZSwiY2xpZW50SG9zdCI6IjE3Mi4xNy4wLjEiLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJzZXJ2aWNlLWFjY291bnQta2V5Y2xvYWstY2xpZW50IiwiY2xpZW50QWRkcmVzcyI6IjE3Mi4xNy4wLjEifQ.PUq6-N-9Hn57kSrK0-6reC8AYT08EV4DZsBqxQ7D0cyp4hHTSP5ax9zQwn0Q05bCZ3c_L_prwMa8VOEFF5Nv-ch2otVg7lIqTc4xeLORSRmIxhjFSxLbiXwBhl4mmfOOHwSL0yBRVHhPzdRkHyVmLlq1WrPfiNe6NRuhDiQIIaFTA0-jSfyqtXNcYjcidsTwjL0q9_Cxt0BrsjTQZLO2b9NKnh5rKbBewvwwIWvZqY5j8QiT3LL652RAED_q7RbG-jFqtLleEklKTtS3bFlJIMCzvdOmfTxZT-FY2zbx_0NJil8bQTJorwveF6Vjb11vAuTI9ccjaOg54SFQT3tSGQ', 'expires_in': 60, 'refresh_expires_in': 1800, 'refresh_token': 'eyJhbGciOiJIUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICI5MmE5NTI2NC0wNTAyLTQzN2ItYWE3ZS01ZGIwNjFlYzMwOWYifQ.eyJqdGkiOiJhYjU2NTg1OS1hODJkLTQzMzYtOTFmNS1kNTU0OWU2ZTU0YTkiLCJleHAiOjE1ODQxODcxNDcsIm5iZiI6MCwiaWF0IjoxNTg0MTg1MzQ3LCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgwODAvYXV0aC9yZWFsbXMvbWFzdGVyIiwiYXVkIjoiaHR0cDovL2xvY2FsaG9zdDo4MDgwL2F1dGgvcmVhbG1zL21hc3RlciIsInN1YiI6IjRjOWMyNDMwLWIyZTctNGYwYi05MzI1LWFhODFkZmZlMDQ2MyIsInR5cCI6IlJlZnJlc2giLCJhenAiOiJrZXljbG9hay1jbGllbnQiLCJhdXRoX3RpbWUiOjAsInNlc3Npb25fc3RhdGUiOiJhZjc3YmY5MS01NDZkLTQzYTUtODBmZi1jNDQwODYwNWE1OWYiLCJyZWFsbV9hY2Nlc3MiOnsicm9sZXMiOlsib2ZmbGluZV9hY2Nlc3MiLCJ1bWFfYXV0aG9yaXphdGlvbiJdfSwicmVzb3VyY2VfYWNjZXNzIjp7ImtleWNsb2FrLWNsaWVudCI6eyJyb2xlcyI6WyJ1bWFfcHJvdGVjdGlvbiJdfSwiYWNjb3VudCI6eyJyb2xlcyI6WyJtYW5hZ2UtYWNjb3VudCIsIm1hbmFnZS1hY2NvdW50LWxpbmtzIiwidmlldy1wcm9maWxlIl19fSwic2NvcGUiOiJlbWFpbCBwcm9maWxlIn0.vdL4dCB8GLa-045EO3_UNUfDWMTOvoDnFs9giRjrvQM', 'token_type': 'bearer', 'not-before-policy': 0, 'session_state': 'af77bf91-546d-43a5-80ff-c4408605a59f', 'scope': 'email profile'} >>> :param username: username to be used :param password: password to be used :returns: dictionary """ headers = basic_auth(config.client.client_id, config.client.client_secret) payload = (AuthorizationMixin.payload_for_user(username, password) or AuthorizationMixin.payload_for_client()) log.debug("Retrieving PAT from server") response = httpx.post(config.uma2.token_endpoint, data=payload, headers=headers) response.raise_for_status() return response.json()
def introspect(rpt: str) -> Dict: """ introspect the request party token (RPT) see `docs <https://www.keycloak.org/docs/latest/authorization_services/#_service_protection_token_introspection>`__ for more details >>> >>> form keycloak import Client >>> kc = Client(username='******', password='******') >>> rpt = kc.rpt(kc.access_token) >>> kc.introspect(rpt['access_token']) 2020-08-03 11:47:54,628 [DEBUG] Introspecting RPT token 2020-08-03 11:47:54,635 [DEBUG] RPT introspected successfully {'exp': 1596435534, 'nbf': 0, 'iat': 1596435474, 'jti': '822c7f6f-cd0a-4b9d-b55c-72803755ca7c', 'aud': ['kc', 'account'], 'typ': 'Bearer', 'acr': '1', 'permissions': [{'rsid': '992dfa45-6098-45ac-b62e-da4d2787377f', 'rsname': 'Default Resource', 'resource_id': '992dfa45-6098-45ac-b62e-da4d2787377f', 'resource_scopes': []}], 'active': True} >>> :param rpt: rpt token :returns: dictionary """ payload = {"token_type_hint": TokenTypeHints.rpt, "token": rpt} headers = basic_auth(config.client.client_id, config.client.client_secret) log.debug("Introspecting RPT token") response = httpx.post(config.uma2.introspection_endpoint, data=payload, headers=headers) response.raise_for_status() log.debug("RPT introspected successfully") return response.json()
def test_renew_success(mock_auth, mock_post, mock_info, kc_client, kc_config): headers = basic_auth(kc_config.client.client_id, kc_config.client.client_secret) mock_auth.return_value = headers kc_client.tokens = {"refresh_token": "token0123456789"} kc_client._renew() payload = { "client_id": kc_config.client.client_id, "grant_type": "refresh_token", "refresh_token": "token0123456789", } mock_auth.assert_called_once_with(kc_config.client.client_id, kc_config.client.client_secret) mock_post.assert_called_once_with(kc_config.uma2.token_endpoint, data=payload, headers=headers) mock_info.assert_called_once_with("Renewing tokens")
def test_refresh_tokens_failure(mock_auth, mock_post, mock_exception, kc_client, kc_config): headers = basic_auth(kc_config.client.client_id, kc_config.client.client_secret) mock_auth.return_value = headers mock_post.return_value.content = "server error" mock_post.return_value.raise_for_status = MagicMock(side_effect=HTTPError) kc_client.tokens = {"refresh_token": "token0123456789"} with pytest.raises(HTTPError) as ex: kc_client.refresh_tokens() payload = { "client_id": kc_config.client.client_id, "grant_type": "refresh_token", "refresh_token": "token0123456789", } mock_auth.assert_called_once_with(kc_config.client.client_id, kc_config.client.client_secret) mock_post.assert_called_once_with(kc_config.uma2.token_endpoint, data=payload, headers=headers)
def refresh_tokens(self) -> None: """ method to refresh expired access token using refresh token >>> from keycloak import Client >>> kc = Client() >>> kc.refresh_tokens() """ headers = basic_auth(config.client.client_id, config.client.client_secret) payload = { "client_id": config.client.client_id, "grant_type": "refresh_token", "refresh_token": self._tokens["refresh_token"], } log.debug("Refreshing tokens") response = httpx.post(config.uma2.token_endpoint, data=payload, headers=headers) response.raise_for_status() log.debug("Tokens refreshed successfully") self._tokens = response.json()
async def refresh_tokens(self) -> None: """ method to refresh expired access token using refresh token >>> import asyncio >>> from keycloak import AsyncClient >>> kc= AsyncClient() >>> asyncio.run(await kc.refresh_tokens()) """ headers = basic_auth(config.client.client_id, config.client.client_secret) payload = { "client_id": config.client.client_id, "grant_type": "refresh_token", "refresh_token": self._tokens["refresh_token"], } log.debug("Refreshing tokens") async with httpx.AsyncClient() as client: response = await client.post(config.uma2.token_endpoint, data=payload, headers=headers) log.debug("Tokens refreshed successfully") self._tokens = response.json()
def test_basic_auth(): """ Test case for basic_auth """ actual_result = basic_auth("username", "password") assert actual_result == {"Authorization": "Basic dXNlcm5hbWU6cGFzc3dvcmQ="}