Keycloak¶
-
class
keycloak.
Client
(callback_uri: str = 'http://localhost/kc/callback', username: str = None, password: str = None)¶ An interface to interact with the rest APIs of keycloak server from python
-
property
access_token
¶ access token associated with the client/user
>>> from keycloak import Client >>> kc = Client() >>> kc.access_token 'eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJLRG9qblhUaF90Z0dzeWtDM1g4VjJfaEY3TU0zZlZpa1B6T2VDX2RiLWx3In0.eyJqdGkiOiIzOWJkMDQ0ZS04OGQ3LTQ3MGQtOGE4Ni1hMWMxMWI2ZmI2MzIiLCJleHAiOjE1ODQyNTcwMjgsIm5iZiI6MCwiaWF0IjoxNTg0MjU2OTY4LCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgwODAvYXV0aC9yZWFsbXMvbWFzdGVyIiwiYXVkIjpbImtleWNsb2FrLWNsaWVudCIsImFjY291bnQiXSwic3ViIjoiNmJhMDg0NDMtMzg4MS00MGU3LWFmNDMtMTBiNzE5NmIwMmZkIiwidHlwIjoiQmVhcmVyIiwiYXpwIjoia2V5Y2xvYWstY2xpZW50IiwiYXV0aF90aW1lIjowLCJzZXNzaW9uX3N0YXRlIjoiNWU3ZDcyMjUtMGVjNi00NTgxLWE3OWEtMDkyMWI2ZjYzMDFhIiwiYWNyIjoiMSIsInJlYWxtX2FjY2VzcyI6eyJyb2xlcyI6WyJvZmZsaW5lX2FjY2VzcyIsInVtYV9hdXRob3JpemF0aW9uIl19LCJyZXNvdXJjZV9hY2Nlc3MiOnsia2V5Y2xvYWstY2xpZW50Ijp7InJvbGVzIjpbInVtYV9wcm90ZWN0aW9uIl19LCJhY2NvdW50Ijp7InJvbGVzIjpbIm1hbmFnZS1hY2NvdW50IiwibWFuYWdlLWFjY291bnQtbGlua3MiLCJ2aWV3LXByb2ZpbGUiXX19LCJzY29wZSI6ImVtYWlsIHByb2ZpbGUiLCJlbWFpbF92ZXJpZmllZCI6ZmFsc2UsImNsaWVudElkIjoia2V5Y2xvYWstY2xpZW50IiwiY2xpZW50SG9zdCI6IjE3Mi4xNy4wLjEiLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJzZXJ2aWNlLWFjY291bnQta2V5Y2xvYWstY2xpZW50IiwiY2xpZW50QWRkcmVzcyI6IjE3Mi4xNy4wLjEifQ.Yx_GlS3VUl9SfqH185A1G-ZKnTLdPVkRaLoNlXZYG-yA3g85293T4cRayqWDy-aSs0QrhcFht4E-x0PfXZXkS-F_mdByJXzkojCtS3zwztCvUt1667RTc-tRqxqiU3jzdrQw8pQSPKJBBwwrVOthoowc17uSCr7QmvNf2VUA6411ySyzrqr2Hm5Y8oUpcY-eAeN3ivxuIHfCIyv2QRj4MchthY8mZkZGltJygZIN3fHSqiNmgv29NGQDZQ7JMDRg1dKDqFVEmmhObtmjiYu1jpxX3Z3rLGw3AfpdzkfLlC7Bd0qNjLIYQDfmniX1-LK9eEzvUGSD3Mf0bHvfgw5qlg' >>>
- Returns
string
-
callback
(code: str) → Dict¶ openid login callback handler
>>> from keycloak import Client >>> from flask import Flask, request, session, redirect, Response >>> >>> kc = Client() >>> >>> app = Flask(__name__) >>> >>> @app.route("/howdy) >>> def howdy(): >>> return "Howdy!" >>> >>> @app.route("/login) >>> def login(): >>> url, state = kc.login() >>> session["state"] = state >>> return redirect(url) >>> >>> @app.route("/callback) >>> def callback(): >>> state = request.params["state"] >>> if session["state"] != state: >>> return Response("Invalid state", status=400) >>> >>> code = request.params["code"] >>> session["tokens"] = kc.callback(code) >>> return redirect("/howdy") >>> >>> if __name__ == "__main__": >>> app.run()
- Parameters
code – code send by the keycloak server
- Returns
dictionary
-
callback_uri
= 'http://localhost/kc/callback'¶
-
static
construct_key
(alg: str, jwk: str) → bytes¶ construct jwt algorithm instance from jwk
- Parameters
alg – algorithm to be used
jwk – signing key aka jwk
- Returns
key
-
decode
(token: str) → Dict¶ decode given json web token (jwt)
>>> from keycloak import Client >>> kc = Client() >>> kc.decode(kc.access_token) {'jti': '39bd044e-88d7-470d-8a86-a1c11b6fb632', 'exp': 1584257028, 'nbf': 0, 'iat': 1584256968, 'iss': 'http://localhost:8080/auth/realms/master', 'aud': ['keycloak-client', 'account'], 'sub': '6ba08443-3881-40e7-af43-10b7196b02fd', 'typ': 'Bearer', 'azp': 'keycloak-client', 'auth_time': 0, 'session_state': '5e7d7225-0ec6-4581-a79a-0921b6f6301a', 'acr': '1', 'realm_access': {'roles': ['offline_access', 'uma_authorization']}, 'resource_access': {'keycloak-client': {'roles': ['uma_protection']}, 'account': {'roles': ['manage-account', 'manage-account-links', 'view-profile']}}, 'scope': 'email profile', 'email_verified': False, 'clientId': 'keycloak-client', 'clientHost': '172.17.0.1', 'preferred_username': 'service-account-keycloak-client', 'clientAddress': '172.17.0.1'} >>>
- Parameters
token – jwt to be decoded eg:access_token or refresh_token
- Returns
dictionary
-
fetch_jwk
(kid: str) → str¶ find jwk with given id from self.jwks
>>> from keycloak import Client >>> kc = Client() >>> kc.fetch_jwk('KDojnXTh_tgGsykC3X8V2_hF7MM3fVikPzOeC_db-lw') '{"kid": "KDojnXTh_tgGsykC3X8V2_hF7MM3fVikPzOeC_db-lw", "kty": "RSA", "alg": "RS256", "use": "sig", "n": "q8JxMYdetQKGZHhH6ZzQvnc0S6qfBlUchwuNITAD2_nBlta970_2zE840bxbwQSiZVfMh1fdnQ4xZiIc5qTjeLIn2n6LBs78uzTdAP4PG1tyV2jJviBnJY6FNEHwWKJ-bPLMp_WRze5uSnzwW9sq2e9XhhQY1os9m6tou01GIo93KUnYY94Xvl1MMNjxFAX7RA5MYi-qPw6BNi-b_5WB1LD3A2e-aJUnh40NMwJAPC286Is8KvJIgeg3CMIKPfvVcwzMDUvrLZHRHhvypjvW5ws7OgnNkngCdnz8hyMe4qGNkKl8rbWiu5UOI6qlG3ub4r_CTv6nvqIOdlyO_y97wQ", "e": "AQAB", "x5c": ["MIICmzCCAYMCBgFw3RFEWTANBgkqhkiG9w0BAQsFADARMQ8wDQYDVQQDDAZtYXN0ZXIwHhcNMjAwMzE1MDcxOTIxWhcNMzAwMzE1MDcyMTAxWjARMQ8wDQYDVQQDDAZtYXN0ZXIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCrwnExh161AoZkeEfpnNC+dzRLqp8GVRyHC40hMAPb+cGW1r3vT/bMTzjRvFvBBKJlV8yHV92dDjFmIhzmpON4sifafosGzvy7NN0A/g8bW3JXaMm+IGcljoU0QfBYon5s8syn9ZHN7m5KfPBb2yrZ71eGFBjWiz2bq2i7TUYij3cpSdhj3he+XUww2PEUBftEDkxiL6o/DoE2L5v/lYHUsPcDZ75olSeHjQ0zAkA8Lbzoizwq8kiB6DcIwgo9+9VzDMwNS+stkdEeG/KmO9bnCzs6Cc2SeAJ2fPyHIx7ioY2QqXyttaK7lQ4jqqUbe5viv8JO/qe+og52XI7/L3vBAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAEIkR4iXNmFWJTyP5j682i7MWeHnMCTMQTQZtOfqbVAJLKMRxm9X8ND/PwbucoLFsmx9UnyCe9erIJ/EGRimTNGij311kRWVtDCw6FtObMaxNvgOLwiuN989N7bA2B6QqsBqYvlYnEHy5rPLJWRojUPQ942mildqRiFI5JfGHjY88gwju/q/DhhAPu7wFORYDYxo0Fxv4/aV/VJzg03gav0/vZWebqEa/aRFSpScZgYxc4KloNMkYZYHYo/OtAX01WUBO5cilbennNnUDeryy3FBc9p1/rv1a1BL9rY5wW2Kt4jYyp82lk+gZqtfHJDHHk44QLW7xq37AYd8JdQMjss="], "x5t": "eDziHrpDesOJXALdEuBF2tY4vWc", "x5t#S256": "__cmdM6AqteNxXRMH4daJGEsG15jZCsSxKTCwYk-PX4"}' >>>
- Returns
string
-
fetch_rpt
(ticket: str = None, access_token: str = None) → Dict¶ retrieve request party token (RPT) see docs for more details
>>> >>> form keycloak import Client, Resource >>> kc = Client() >>> ticket = kc.find_ticket(kc.resources) >>> kc.rpt(ticket["ticket"]) {'upgraded': False, 'access_token': 'eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJHYkdydV9sa05wN29hdjg1MUx4LXRQT1c3LWdCeWRKRWZIYmUxRHp1Zm1NIn0.eyJqdGkiOiIzZTg3OGNkNy1iNjZkLTQyOGItYjQ0ZS05YTRkNjE4NzA2NTAiLCJleHAiOjE1NzIyNDY1NTcsIm5iZiI6MCwiaWF0IjoxNTcyMjQ2NDk3LCJpc3MiOiJodHRwczovL2tleWNsb2FrLmFraGlscHV0aGlyeS5kZXYvYXV0aC9yZWFsbXMvbWFzdGVyIiwiYXVkIjpbInB5dGhvbi1jbGllbnQiLCJhY2NvdW50Il0sInN1YiI6ImUxZmJkN2Q2LWFkMmItNDA3Zi04OWNmLTZjMmIwMDRkNzhiYiIsInR5cCI6IkJlYXJlciIsImF6cCI6InB5dGhvbi1jbGllbnQiLCJhdXRoX3RpbWUiOjAsInNlc3Npb25fc3RhdGUiOiJiZWM3NGI4MC02MDJlLTQzZTktYjBlMS1jYTQ5YzA1YWI0OGUiLCJhY3IiOiIxIiwicmVhbG1fYWNjZXNzIjp7InJvbGVzIjpbIm9mZmxpbmVfYWNjZXNzIiwidW1hX2F1dGhvcml6YXRpb24iXX0sInJlc291cmNlX2FjY2VzcyI6eyJweXRob24tY2xpZW50Ijp7InJvbGVzIjpbInVtYV9wcm90ZWN0aW9uIl19LCJhY2NvdW50Ijp7InJvbGVzIjpbIm1hbmFnZS1hY2NvdW50IiwibWFuYWdlLWFjY291bnQtbGlua3MiLCJ2aWV3LXByb2ZpbGUiXX19LCJhdXRob3JpemF0aW9uIjp7InBlcm1pc3Npb25zIjpbeyJyc2lkIjoiYmI2YTc3N2YtYTE3Yi00NTU1LWIwMzUtYTZjZTEyYTFmZDIxIiwicnNuYW1lIjoiRGVmYXVsdCBSZXNvdXJjZSJ9XX0sInNjb3BlIjoiZW1haWwgcHJvZmlsZSIsImNsaWVudEhvc3QiOiIxODAuMTUxLjEzNy4xNDAiLCJjbGllbnRJZCI6InB5dGhvbi1jbGllbnQiLCJlbWFpbF92ZXJpZmllZCI6ZmFsc2UsInByZWZlcnJlZF91c2VybmFtZSI6InNlcnZpY2UtYWNjb3VudC1weXRob24tY2xpZW50IiwiY2xpZW50QWRkcmVzcyI6IjE4MC4xNTEuMTM3LjE0MCIsImVtYWlsIjoic2VydmljZS1hY2NvdW50LXB5dGhvbi1jbGllbnRAcGxhY2Vob2xkZXIub3JnIn0.UmMaTi-x-tX71iWovQ8gupFdzpJ7YLOSQsAPPLlhaKLbHFDci0w1C99IXAcVkDyKzTgGfs-2SQzPsS5hYQzy_hZP5d-jqWxOvq_iBx5Nem1ccKrfUmkpHDsNDB7BV-me6g8jp0uPOMq4pPTR5elJ8YEho_TS_QKqsD-N3yNLhQgxVtELWGovgjmnbuLmglKoNLktBYoJTukoWkwpNCXFuJSbbujUrHcsQ1bb14LXZrDJ15_EreO3JpWMtt-lR9H-6MH56StKQ7OKhp3CK7zIOreNW8kZfGCoqGzWMotDGQXDYZsL4DjtIzuSgkeI63culrN70ZIA0M89klrqX9ZpFw', 'expires_in': 60, 'refresh_expires_in': 1800, 'refresh_token': 'eyJhbGciOiJIUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICIxOGQ1NzdiYy03MmY2LTRiMTUtYjc2Mi1hOGIzOWRjNzE2MjkifQ.eyJqdGkiOiI3YWFkOTZjNy1jYmI0LTQyNzUtODkyMi01MjNhN2M1MDBlYzQiLCJleHAiOjE1NzIyNDgyOTcsIm5iZiI6MCwiaWF0IjoxNTcyMjQ2NDk3LCJpc3MiOiJodHRwczovL2tleWNsb2FrLmFraGlscHV0aGlyeS5kZXYvYXV0aC9yZWFsbXMvbWFzdGVyIiwiYXVkIjoiaHR0cHM6Ly9rZXljbG9hay5ha2hpbHB1dGhpcnkuZGV2L2F1dGgvcmVhbG1zL21hc3RlciIsInN1YiI6ImUxZmJkN2Q2LWFkMmItNDA3Zi04OWNmLTZjMmIwMDRkNzhiYiIsInR5cCI6IlJlZnJlc2giLCJhenAiOiJweXRob24tY2xpZW50IiwiYXV0aF90aW1lIjowLCJzZXNzaW9uX3N0YXRlIjoiYmVjNzRiODAtNjAyZS00M2U5LWIwZTEtY2E0OWMwNWFiNDhlIiwicmVhbG1fYWNjZXNzIjp7InJvbGVzIjpbIm9mZmxpbmVfYWNjZXNzIiwidW1hX2F1dGhvcml6YXRpb24iXX0sInJlc291cmNlX2FjY2VzcyI6eyJweXRob24tY2xpZW50Ijp7InJvbGVzIjpbInVtYV9wcm90ZWN0aW9uIl19LCJhY2NvdW50Ijp7InJvbGVzIjpbIm1hbmFnZS1hY2NvdW50IiwibWFuYWdlLWFjY291bnQtbGlua3MiLCJ2aWV3LXByb2ZpbGUiXX19LCJhdXRob3JpemF0aW9uIjp7InBlcm1pc3Npb25zIjpbeyJyc2lkIjoiYmI2YTc3N2YtYTE3Yi00NTU1LWIwMzUtYTZjZTEyYTFmZDIxIiwicnNuYW1lIjoiRGVmYXVsdCBSZXNvdXJjZSJ9XX0sInNjb3BlIjoiZW1haWwgcHJvZmlsZSJ9.woXfkz49D13Fzxqaii9Gh3dr2ZiGHNA2grq2z9nYNqc', 'token_type': 'Bearer', 'not-before-policy': 0} >>>
- Parameters
ticket – permission ticket
access_token – access token to be used
- Returns
dictionary
-
fetch_ticket
(resources: List = [], access_token: str = None) → Dict¶ retrieve permission ticket from keycloak server see docs for more details
>>> >>> from keycloak import Client >>> kc = Client() >>> kc.fetch_ticket(kc.resources) {'ticket': 'eyJhbGciOiJIUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICI5MmE5NTI2NC0wNTAyLTQzN2ItYWE3ZS01ZGIwNjFlYzMwOWYifQ.eyJwZXJtaXNzaW9ucyI6W3sicnNpZCI6IjQ4MTUyMTI2LWFhOTEtNGE0Zi04ZWU4LTczOTI4ZjViNmMwMCJ9XSwianRpIjoiNDhlZmVmZDQtMDg5NC00NjA2LTk0YjUtMDhlNjZiNTE4YWM2LTE1ODQxODUyOTUyMzkiLCJleHAiOjE1ODQxODUzNTUsIm5iZiI6MCwiaWF0IjoxNTg0MTg1Mjk1LCJhdWQiOiJodHRwOi8vbG9jYWxob3N0OjgwODAvYXV0aC9yZWFsbXMvbWFzdGVyIiwic3ViIjoiNGM5YzI0MzAtYjJlNy00ZjBiLTkzMjUtYWE4MWRmZmUwNDYzIiwiYXpwIjoia2V5Y2xvYWstY2xpZW50In0.Or_6wzK9wlQMBPpi8bWIioWCeO6QuolKjr4mKC4YWpA'} >>>
- Parameters
resources – list of resources
access_token – access token to be used
- Returns
dictionary
-
fetch_userinfo
(access_token: str = None) → Dict¶ method to retrieve userinfo from the keycloak server
>>> >>> from keycloak import Client >>> kc = Client() >>> kc.fetch_userinfo() {'sub': '4c9c2430-b2e7-4f0b-9325-aa81dffe0463', 'email_verified': False, 'preferred_username': 'service-account-keycloak-client'} >>>
- Parameters
access_token – access token of the client or user
- Returns
dicttionary
-
find_resource
(resource_id: str, access_token: str = None) → Dict¶ Method to fetch the details of a resource
>>> from keycloak import Client >>> kc = Client() >>> kc.find_resource('bb6a777f-a17b-4555-b035-a6ce12a1fd21') {'name': 'Default Resource', 'type': 'urn:python-client:resources:default', 'owner': {'id': 'd74cc555-d46c-4ef8-8a30-ceb2b91d8823'}, 'ownerManagedAccess': False, 'attributes': {}, '_id': 'bb6a777f-a17b-4555-b035-a6ce12a1fd21', 'uris': ['/*'], 'resource_scopes': []} >>>
- Parameters
access_token – access token to be used
- Returns
list
-
find_resources
(access_token: str = None) → Dict¶ fetch resources from keycloak server
>>> from keycloak import Client >>> kc = Client() >>> kc.find_resources() [{'name': 'Default Resource', 'type': 'urn:python-client:resources:default', 'owner': {'id': 'd74cc555-d46c-4ef8-8a30-ceb2b91d8823'}, 'ownerManagedAccess': False, 'attributes': {}, '_id': 'bb6a777f-a17b-4555-b035-a6ce12a1fd21', 'uris': ['/*'], 'resource_scopes': []}] >>>
- Parameters
access_token – access token to be used
- Returns
list
-
static
introspect
(rpt: str) → Dict¶ introspect the request party token (RPT) see docs for more details
>>> >>> form keycloak import Client, Resource >>> kc = Client() >>> ticket = kc.find_ticket(resources) >>> rpt = kc.rpt(ticket["ticket"]) >>> kc.introspect(rpt["access_token"]) {'jti': '5a948d88-d8ef-4730-ad4f-a7f82604c196', 'exp': 1572246750, 'nbf': 0, 'iat': 1572246690, 'aud': ['python-client', 'account'], 'typ': 'Bearer', 'auth_time': 0, 'acr': '1', 'permissions': [{'rsid': 'bb6a777f-a17b-4555-b035-a6ce12a1fd21', 'rsname': 'Default Resource', 'resource_id': 'bb6a777f-a17b-4555-b035-a6ce12a1fd21', 'resource_scopes': []}], 'active': True} >>>
- Parameters
rpt – rpt token
- Returns
dictionary
-
property
jwks
¶ list of signing keys/JWKs used by the keycloak server
>>> from keycloak import Client >>> kc = Client() >>> kc.jwks [{'kid': 'KDojnXTh_tgGsykC3X8V2_hF7MM3fVikPzOeC_db-lw', 'kty': 'RSA', 'alg': 'RS256', 'use': 'sig', 'n': 'q8JxMYdetQKGZHhH6ZzQvnc0S6qfBlUchwuNITAD2_nBlta970_2zE840bxbwQSiZVfMh1fdnQ4xZiIc5qTjeLIn2n6LBs78uzTdAP4PG1tyV2jJviBnJY6FNEHwWKJ-bPLMp_WRze5uSnzwW9sq2e9XhhQY1os9m6tou01GIo93KUnYY94Xvl1MMNjxFAX7RA5MYi-qPw6BNi-b_5WB1LD3A2e-aJUnh40NMwJAPC286Is8KvJIgeg3CMIKPfvVcwzMDUvrLZHRHhvypjvW5ws7OgnNkngCdnz8hyMe4qGNkKl8rbWiu5UOI6qlG3ub4r_CTv6nvqIOdlyO_y97wQ', 'e': 'AQAB', 'x5c': ['MIICmzCCAYMCBgFw3RFEWTANBgkqhkiG9w0BAQsFADARMQ8wDQYDVQQDDAZtYXN0ZXIwHhcNMjAwMzE1MDcxOTIxWhcNMzAwMzE1MDcyMTAxWjARMQ8wDQYDVQQDDAZtYXN0ZXIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCrwnExh161AoZkeEfpnNC+dzRLqp8GVRyHC40hMAPb+cGW1r3vT/bMTzjRvFvBBKJlV8yHV92dDjFmIhzmpON4sifafosGzvy7NN0A/g8bW3JXaMm+IGcljoU0QfBYon5s8syn9ZHN7m5KfPBb2yrZ71eGFBjWiz2bq2i7TUYij3cpSdhj3he+XUww2PEUBftEDkxiL6o/DoE2L5v/lYHUsPcDZ75olSeHjQ0zAkA8Lbzoizwq8kiB6DcIwgo9+9VzDMwNS+stkdEeG/KmO9bnCzs6Cc2SeAJ2fPyHIx7ioY2QqXyttaK7lQ4jqqUbe5viv8JO/qe+og52XI7/L3vBAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAEIkR4iXNmFWJTyP5j682i7MWeHnMCTMQTQZtOfqbVAJLKMRxm9X8ND/PwbucoLFsmx9UnyCe9erIJ/EGRimTNGij311kRWVtDCw6FtObMaxNvgOLwiuN989N7bA2B6QqsBqYvlYnEHy5rPLJWRojUPQ942mildqRiFI5JfGHjY88gwju/q/DhhAPu7wFORYDYxo0Fxv4/aV/VJzg03gav0/vZWebqEa/aRFSpScZgYxc4KloNMkYZYHYo/OtAX01WUBO5cilbennNnUDeryy3FBc9p1/rv1a1BL9rY5wW2Kt4jYyp82lk+gZqtfHJDHHk44QLW7xq37AYd8JdQMjss='], 'x5t': 'eDziHrpDesOJXALdEuBF2tY4vWc', 'x5t#S256': '__cmdM6AqteNxXRMH4daJGEsG15jZCsSxKTCwYk-PX4'}] >>>
- Returns
list
-
load_jwks
() → List¶ retrieve signing keys/JWK from the keycloak server
>>> from keycloak import Client >>> kc = Client() >>> kc.load_jwks() [{'kid': 'KDojnXTh_tgGsykC3X8V2_hF7MM3fVikPzOeC_db-lw', 'kty': 'RSA', 'alg': 'RS256', 'use': 'sig', 'n': 'q8JxMYdetQKGZHhH6ZzQvnc0S6qfBlUchwuNITAD2_nBlta970_2zE840bxbwQSiZVfMh1fdnQ4xZiIc5qTjeLIn2n6LBs78uzTdAP4PG1tyV2jJviBnJY6FNEHwWKJ-bPLMp_WRze5uSnzwW9sq2e9XhhQY1os9m6tou01GIo93KUnYY94Xvl1MMNjxFAX7RA5MYi-qPw6BNi-b_5WB1LD3A2e-aJUnh40NMwJAPC286Is8KvJIgeg3CMIKPfvVcwzMDUvrLZHRHhvypjvW5ws7OgnNkngCdnz8hyMe4qGNkKl8rbWiu5UOI6qlG3ub4r_CTv6nvqIOdlyO_y97wQ', 'e': 'AQAB', 'x5c': ['MIICmzCCAYMCBgFw3RFEWTANBgkqhkiG9w0BAQsFADARMQ8wDQYDVQQDDAZtYXN0ZXIwHhcNMjAwMzE1MDcxOTIxWhcNMzAwMzE1MDcyMTAxWjARMQ8wDQYDVQQDDAZtYXN0ZXIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCrwnExh161AoZkeEfpnNC+dzRLqp8GVRyHC40hMAPb+cGW1r3vT/bMTzjRvFvBBKJlV8yHV92dDjFmIhzmpON4sifafosGzvy7NN0A/g8bW3JXaMm+IGcljoU0QfBYon5s8syn9ZHN7m5KfPBb2yrZ71eGFBjWiz2bq2i7TUYij3cpSdhj3he+XUww2PEUBftEDkxiL6o/DoE2L5v/lYHUsPcDZ75olSeHjQ0zAkA8Lbzoizwq8kiB6DcIwgo9+9VzDMwNS+stkdEeG/KmO9bnCzs6Cc2SeAJ2fPyHIx7ioY2QqXyttaK7lQ4jqqUbe5viv8JO/qe+og52XI7/L3vBAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAEIkR4iXNmFWJTyP5j682i7MWeHnMCTMQTQZtOfqbVAJLKMRxm9X8ND/PwbucoLFsmx9UnyCe9erIJ/EGRimTNGij311kRWVtDCw6FtObMaxNvgOLwiuN989N7bA2B6QqsBqYvlYnEHy5rPLJWRojUPQ942mildqRiFI5JfGHjY88gwju/q/DhhAPu7wFORYDYxo0Fxv4/aV/VJzg03gav0/vZWebqEa/aRFSpScZgYxc4KloNMkYZYHYo/OtAX01WUBO5cilbennNnUDeryy3FBc9p1/rv1a1BL9rY5wW2Kt4jYyp82lk+gZqtfHJDHHk44QLW7xq37AYd8JdQMjss='], 'x5t': 'eDziHrpDesOJXALdEuBF2tY4vWc', 'x5t#S256': '__cmdM6AqteNxXRMH4daJGEsG15jZCsSxKTCwYk-PX4'}] >>>
- Returns
list
-
login
(scopes: Tuple = ('openid', )) → Tuple¶ method to generate openid login url and state
>>> from keycloak import Client >>> from flask import Flask, request, session, redirect >>> >>> kc = Client() >>> >>> app = Flask(__name__) >>> >>> @app.route("/howdy) >>> def howdy(): >>> return "Howdy!" >>> >>> @app.route("/login) >>> def login(): >>> url, state = kc.login() >>> session["state"] = state >>> return redirect(url) >>> >>> if __name__ == "__main__": >>> app.run()
- Parameters
scopes – scopes to be requested eg: openid, email, profile etc
- Returns
endpoint url and state
-
parse_key_and_alg
(header: str) → Tuple[bytes, str]¶ retrieve signing key and algorithm from given jwt header
>>> from keycloak import Client >>> kc = Client() >>> kc.parse_key_and_alg('eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJLRG9qblhUaF90Z0dzeWtDM1g4VjJfaEY3TU0zZlZpa1B6T2VDX2RiLWx3In0') (<cryptography.hazmat.backends.openssl.rsa._RSAPublicKey object at 0x101da7d90>, 'RS256') >>>
- Parameters
header – jwt header
- Returns
key and algorithm
-
static
pat
(username: str = None, password: str = None) → Dict¶ retrieve protection api token (PAT), see docs 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'} >>>
- Parameters
username – username to be used
password – password to be used
- Returns
dictionary
-
static
payload_for_client
() → Dict¶ generate payload for keycloak client
- Returns
dictionary
-
static
payload_for_user
(username: str = None, password: str = None) → Dict¶ generate payload for keycloak user
- Parameters
username – username to be used
password – password to be used
- Returns
dictionary
-
property
refresh_token
¶ refresh token associated with the client/user
>>> from keycloak import Client >>> kc = Client() >>> kc.refresh_token 'eyJhbGciOiJIUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJjYmFkZWRhYS04NDA5LTQ3MDYtODcwMy02NjViM2Q2MzYwMDAifQ.eyJqdGkiOiJkODVhOWJlYi03NzE1LTQ4ZTAtOTA3My00ZDEyMmQ4MDM1NzAiLCJleHAiOjE1ODQyNTg3NjgsIm5iZiI6MCwiaWF0IjoxNTg0MjU2OTY4LCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgwODAvYXV0aC9yZWFsbXMvbWFzdGVyIiwiYXVkIjoiaHR0cDovL2xvY2FsaG9zdDo4MDgwL2F1dGgvcmVhbG1zL21hc3RlciIsInN1YiI6IjZiYTA4NDQzLTM4ODEtNDBlNy1hZjQzLTEwYjcxOTZiMDJmZCIsInR5cCI6IlJlZnJlc2giLCJhenAiOiJrZXljbG9hay1jbGllbnQiLCJhdXRoX3RpbWUiOjAsInNlc3Npb25fc3RhdGUiOiI1ZTdkNzIyNS0wZWM2LTQ1ODEtYTc5YS0wOTIxYjZmNjMwMWEiLCJyZWFsbV9hY2Nlc3MiOnsicm9sZXMiOlsib2ZmbGluZV9hY2Nlc3MiLCJ1bWFfYXV0aG9yaXphdGlvbiJdfSwicmVzb3VyY2VfYWNjZXNzIjp7ImtleWNsb2FrLWNsaWVudCI6eyJyb2xlcyI6WyJ1bWFfcHJvdGVjdGlvbiJdfSwiYWNjb3VudCI6eyJyb2xlcyI6WyJtYW5hZ2UtYWNjb3VudCIsIm1hbmFnZS1hY2NvdW50LWxpbmtzIiwidmlldy1wcm9maWxlIl19fSwic2NvcGUiOiJlbWFpbCBwcm9maWxlIn0.K22gl2ICSmVh6omZMk7z4DB_Io4tDiWp__Gxxx_W4Nk' >>>
- Returns
string
-
refresh_tokens
() → None¶ method to refresh expired access token using refresh token
>>> from keycloak import Client >>> kc = Client() >>> kc.refresh_tokens()
-
property
resources
¶ list of resources available in keycloak server
>>> from keycloak import Client >>> kc = Client() >>> kc.resources [{'name': 'Default Resource', 'type': 'urn:python-client:resources:default', 'owner': {'id': 'd74cc555-d46c-4ef8-8a30-ceb2b91d8823'}, 'ownerManagedAccess': False, 'attributes': {}, '_id': 'bb6a777f-a17b-4555-b035-a6ce12a1fd21', 'uris': ['/*'], 'resource_scopes': []}] >>>
- Returns
list
-
property
rpt
¶ request party token retrieved from server
- Returns
dictionary
-
property
scope
¶ scopes available
>>> from keycloak import Client >>> kc = Client() >>> kc.scope ['email', 'profile'] >>>
- Returns
list
-
property
ticket
¶ permission ticket retrieved from server
- Returns
dictionary
-
property
token_type
¶ type of token
>>> from keycloak import Client >>> kc = Client() >>> kc.token_type 'bearer' >>>
- Returns
string
-
property
tokens
¶ access and refresh tokens associated with the client/user
>>> from keycloak import Client >>> kc = Client() >>> kc.tokens {'access_token': 'eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJLRG9qblhUaF90Z0dzeWtDM1g4VjJfaEY3TU0zZlZpa1B6T2VDX2RiLWx3In0.eyJqdGkiOiIzOWJkMDQ0ZS04OGQ3LTQ3MGQtOGE4Ni1hMWMxMWI2ZmI2MzIiLCJleHAiOjE1ODQyNTcwMjgsIm5iZiI6MCwiaWF0IjoxNTg0MjU2OTY4LCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgwODAvYXV0aC9yZWFsbXMvbWFzdGVyIiwiYXVkIjpbImtleWNsb2FrLWNsaWVudCIsImFjY291bnQiXSwic3ViIjoiNmJhMDg0NDMtMzg4MS00MGU3LWFmNDMtMTBiNzE5NmIwMmZkIiwidHlwIjoiQmVhcmVyIiwiYXpwIjoia2V5Y2xvYWstY2xpZW50IiwiYXV0aF90aW1lIjowLCJzZXNzaW9uX3N0YXRlIjoiNWU3ZDcyMjUtMGVjNi00NTgxLWE3OWEtMDkyMWI2ZjYzMDFhIiwiYWNyIjoiMSIsInJlYWxtX2FjY2VzcyI6eyJyb2xlcyI6WyJvZmZsaW5lX2FjY2VzcyIsInVtYV9hdXRob3JpemF0aW9uIl19LCJyZXNvdXJjZV9hY2Nlc3MiOnsia2V5Y2xvYWstY2xpZW50Ijp7InJvbGVzIjpbInVtYV9wcm90ZWN0aW9uIl19LCJhY2NvdW50Ijp7InJvbGVzIjpbIm1hbmFnZS1hY2NvdW50IiwibWFuYWdlLWFjY291bnQtbGlua3MiLCJ2aWV3LXByb2ZpbGUiXX19LCJzY29wZSI6ImVtYWlsIHByb2ZpbGUiLCJlbWFpbF92ZXJpZmllZCI6ZmFsc2UsImNsaWVudElkIjoia2V5Y2xvYWstY2xpZW50IiwiY2xpZW50SG9zdCI6IjE3Mi4xNy4wLjEiLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJzZXJ2aWNlLWFjY291bnQta2V5Y2xvYWstY2xpZW50IiwiY2xpZW50QWRkcmVzcyI6IjE3Mi4xNy4wLjEifQ.Yx_GlS3VUl9SfqH185A1G-ZKnTLdPVkRaLoNlXZYG-yA3g85293T4cRayqWDy-aSs0QrhcFht4E-x0PfXZXkS-F_mdByJXzkojCtS3zwztCvUt1667RTc-tRqxqiU3jzdrQw8pQSPKJBBwwrVOthoowc17uSCr7QmvNf2VUA6411ySyzrqr2Hm5Y8oUpcY-eAeN3ivxuIHfCIyv2QRj4MchthY8mZkZGltJygZIN3fHSqiNmgv29NGQDZQ7JMDRg1dKDqFVEmmhObtmjiYu1jpxX3Z3rLGw3AfpdzkfLlC7Bd0qNjLIYQDfmniX1-LK9eEzvUGSD3Mf0bHvfgw5qlg', 'expires_in': 60, 'refresh_expires_in': 1800, 'refresh_token': 'eyJhbGciOiJIUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJjYmFkZWRhYS04NDA5LTQ3MDYtODcwMy02NjViM2Q2MzYwMDAifQ.eyJqdGkiOiJkODVhOWJlYi03NzE1LTQ4ZTAtOTA3My00ZDEyMmQ4MDM1NzAiLCJleHAiOjE1ODQyNTg3NjgsIm5iZiI6MCwiaWF0IjoxNTg0MjU2OTY4LCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgwODAvYXV0aC9yZWFsbXMvbWFzdGVyIiwiYXVkIjoiaHR0cDovL2xvY2FsaG9zdDo4MDgwL2F1dGgvcmVhbG1zL21hc3RlciIsInN1YiI6IjZiYTA4NDQzLTM4ODEtNDBlNy1hZjQzLTEwYjcxOTZiMDJmZCIsInR5cCI6IlJlZnJlc2giLCJhenAiOiJrZXljbG9hay1jbGllbnQiLCJhdXRoX3RpbWUiOjAsInNlc3Npb25fc3RhdGUiOiI1ZTdkNzIyNS0wZWM2LTQ1ODEtYTc5YS0wOTIxYjZmNjMwMWEiLCJyZWFsbV9hY2Nlc3MiOnsicm9sZXMiOlsib2ZmbGluZV9hY2Nlc3MiLCJ1bWFfYXV0aG9yaXphdGlvbiJdfSwicmVzb3VyY2VfYWNjZXNzIjp7ImtleWNsb2FrLWNsaWVudCI6eyJyb2xlcyI6WyJ1bWFfcHJvdGVjdGlvbiJdfSwiYWNjb3VudCI6eyJyb2xlcyI6WyJtYW5hZ2UtYWNjb3VudCIsIm1hbmFnZS1hY2NvdW50LWxpbmtzIiwidmlldy1wcm9maWxlIl19fSwic2NvcGUiOiJlbWFpbCBwcm9maWxlIn0.K22gl2ICSmVh6omZMk7z4DB_Io4tDiWp__Gxxx_W4Nk', 'token_type': 'bearer', 'not-before-policy': 0, 'session_state': '5e7d7225-0ec6-4581-a79a-0921b6f6301a', 'scope': 'email profile'} >>>
- Returns
dictionary
-
property
userinfo
¶ user information available within the server
>>> >>> from keycloak import Client >>> kc = Client() >>> kc.userinfo {'sub': '4c9c2430-b2e7-4f0b-9325-aa81dffe0463', 'email_verified': False, 'preferred_username': 'service-account-keycloak-client'} >>>
- Returns
dictionary
-
property