Browse Source

Merged in develop (pull request #5)

Develop

Approved-by: Marcos Pereira <marcospereira.mpj@gmail.com>
hotfix/merge
Marcos Pereira 6 years ago
parent
commit
99896f47b6
  1. 42
      CHANGELOG.md
  2. 59
      README.md
  3. 4
      docs/source/conf.py
  4. 60
      docs/source/index.rst
  5. 377
      keycloak/keycloak_admin.py
  6. 30
      keycloak/keycloak_openid.py
  7. 7
      keycloak/urls_patterns.py

42
CHANGELOG.md

@ -0,0 +1,42 @@
Changelog
============
All notable changes to this project will be documented in this file.
## [0.5.0] - 2017-08-21
* Basic functions for Keycloak API (well_know, token, userinfo, logout, certs,
entitlement, instropect)
## [0.6.0] - 2017-08-23
* Added load authorization settings
## [0.7.0] - 2017-08-23
* Added polices
## [0.8.0] - 2017-08-23
* Added permissions
## [0.9.0] - 2017-09-05
* Added functions for Admin Keycloak API
## [0.10.0] - 2017-10-23
* Updated libraries versions
* Updated Docs
## [0.11.0] - 2017-12-12
* Changed Instropect RPT
## [0.12.0] - 2018-01-25
* Add groups functions
* Add Admin Tasks for user and client role management
* Function to trigger user sync from provider
* Optional parameter: verify

59
README.md

@ -3,6 +3,8 @@
Python Keycloak
====================
For review- see https://bitbucket.org/agriness/python-keycloak
**python-keycloak** is a Python package providing access to the Keycloak API.
## Installation
@ -53,8 +55,7 @@ from keycloak import KeycloakOpenID
keycloak_openid = KeycloakOpenID(server_url="http://localhost:8080/auth/",
client_id="example_client",
realm_name="example_realm",
client_secret_key="secret",
verify=True)
client_secret_key="secret")
# Get WellKnow
config_well_know = keycloak_openid.well_know()
@ -65,6 +66,9 @@ token = keycloak_openid.token("user", "password")
# Get Userinfo
userinfo = keycloak_openid.userinfo(token['access_token'])
# Refresh token
token = keycloak_openid.refresh_token(token['refresh_token'])
# Logout
keycloak_openid.logout(token['refresh_token'])
@ -110,7 +114,18 @@ new_user = keycloak_admin.create_user({"email": "example@example.com",
"firstName": "Example",
"lastName": "Example",
"realmRoles": ["user_default", ],
"attributes": {"example": "1,2,3,3,"}})
"attributes": {"example": "1,2,3,3,"}})
# Add user and set password
new_user = keycloak_admin.create_user({"email": "example@example.com",
"username": "example@example.com",
"enabled": True,
"firstName": "Example",
"lastName": "Example",
"credentials": [{"value": "secret","type": "password",}],
"realmRoles": ["user_default", ],
"attributes": {"example": "1,2,3,3,"}})
# User counter
count_users = keycloak_admin.users_count()
@ -127,6 +142,9 @@ user = keycloak_admin.get_user("user-id-keycloak")
# Update User
response = keycloak_admin.update_user(user_id="user-id-keycloak",
payload={'firstName': 'Example Update'})
# Update User Password
response = set_user_password(user_id="user-id-keycloak", password="secret", temporary=True)
# Delete User
response = keycloak_admin.delete_user(user_id="user-id-keycloak")
@ -154,20 +172,39 @@ clients = keycloak_admin.get_clients()
client_id=keycloak_admin.get_client_id("my-client")
# Get representation of the client - id of client (not client-id)
client = keycloak_admin.get_client(client_id=client_id)
client = keycloak_admin.get_client(client_id="client_id")
# Get all roles for the realm or client
realm_roles = keycloak_admin.get_realm_roles()
# Get all roles for the client
client_roles = keycloak_admin.get_client_role(client_id=client_id)
client_roles = keycloak_admin.get_client_roles(client_id="client_id")
# Create client role
keycloak_admin.create_client_role(client_id, "test")
# Get client role
role = keycloak_admin.get_client_role(client_id="client_id", role_name="role_name")
# Warning: Deprecated
# Get client role id from name
role_id = keycloak_admin.get_client_role_id(client_id=client_id, role_name="test")
role_id = keycloak_admin.get_client_role_id(client_id="client_id", role_name="test")
# Get all roles for the realm or client
realm_roles = keycloak_admin.get_roles()
# Create client role
keycloak_admin.create_client_role(client_id, "test")
# Assign client role to user. Note that BOTH role_name and role_id appear to be required.
keycloak_admin.assign_client_role(client_id=client_id, user_id=user_id, role_id=role_id, role_name="test")
keycloak_admin.assign_client_role(client_id="client_id", user_id="user_id", role_id="role_id", role_name="test")
# Create new group
group = keycloak_admin.create_group(name="Example Group")
# Get all groups
groups = keycloak_admin.get_groups()
# Get group
group = keycloak_admin.get_group(group_id='group_id')
# Get group by name
group = keycloak_admin.get_group_by_name(name_or_path='group_id', search_in_subgroups=True)
# Function to trigger user sync from provider
sync_users(storage_id="storage_di", action="action")
```

4
docs/source/conf.py

@ -60,9 +60,9 @@ author = 'Marcos Pereira'
# built documents.
#
# The short X.Y version.
version = '0.11.1'
version = '0.12.0'
# The full version, including alpha/beta/rc tags.
release = '0.11.1'
release = '0.12.0'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.

60
docs/source/index.rst

@ -73,14 +73,15 @@ Usage
Main methods::
# KEYCLOAK OPENID
from keycloak import KeycloakOpenID
# Configure client
keycloak_openid = KeycloakOpenID(server_url="http://localhost:8080/auth/",
client_id="example_client",
realm_name="example_realm",
client_secret_key="secret",
verify=True)
client_secret_key="secret")
# Get WellKnow
config_well_know = keycloak_openid.well_know()
@ -91,6 +92,9 @@ Main methods::
# Get Userinfo
userinfo = keycloak_openid.userinfo(token['access_token'])
# Refresh token
token = keycloak_openid.refresh_token(token['refresh_token'])
# Logout
keycloak_openid.logout(token['refresh_token'])
@ -138,12 +142,26 @@ Main methods::
"realmRoles": ["user_default", ],
"attributes": {"example": "1,2,3,3,"}})
# Add user and set password
new_user = keycloak_admin.create_user({"email": "example@example.com",
"username": "example@example.com",
"enabled": True,
"firstName": "Example",
"lastName": "Example",
"credentials": [{"value": "secret","type": "password",}],
"realmRoles": ["user_default", ],
"attributes": {"example": "1,2,3,3,"}})
# User counter
count_users = keycloak_admin.users_count()
# Get users Returns a list of users, filtered according to query parameters
users = keycloak_admin.get_users({})
# Get user ID from name
user-id-keycloak = keycloak_admin.get_user_id("example@example.com")
# Get User
user = keycloak_admin.get_user("user-id-keycloak")
@ -151,6 +169,9 @@ Main methods::
response = keycloak_admin.update_user(user_id="user-id-keycloak",
payload={'firstName': 'Example Update'})
# Update User Password
response = set_user_password(user_id="user-id-keycloak", password="secret", temporary=True)
# Delete User
response = keycloak_admin.delete_user(user_id="user-id-keycloak")
@ -177,19 +198,38 @@ Main methods::
client_id=keycloak_admin.get_client_id("my-client")
# Get representation of the client - id of client (not client-id)
client_roles = keycloak_admin.get_client_role(client_id=client_id)
client = keycloak_admin.get_client(client_id="client_id")
# Get all roles for the realm or client
realm_roles = keycloak_admin.get_realm_roles()
# Get all roles for the client
client_roles = keycloak_admin.get_client_role(client_id=client_id)
client_roles = keycloak_admin.get_client_roles(client_id="client_id")
# Create client role
keycloak_admin.create_client_role(client_id, "test")
# Get client role
role = keycloak_admin.get_client_role(client_id="client_id", role_name="role_name")
# Warning: Deprecated
# Get client role id from name
role_id = keycloak_admin.get_client_role_id(client_id=client_id, role_name="test")
role_id = keycloak_admin.get_client_role_id(client_id="client_id", role_name="test")
# Get all roles for the realm or client
realm_roles = keycloak_admin.get_roles()
# Create client role
keycloak_admin.create_client_role(client_id, "test")
# Assign client role to user. Note that BOTH role_name and role_id appear to be required.
keycloak_admin.assign_client_role(client_id=client_id, user_id=user_id, role_id=role_id, role_name="test")
keycloak_admin.assign_client_role(client_id="client_id", user_id="user_id", role_id="role_id", role_name="test")
# Create new group
group = keycloak_admin.create_group(name="Example Group")
# Get all groups
groups = keycloak_admin.get_groups()
# Get group
group = keycloak_admin.get_group(group_id='group_id')
# Get group by name
group = keycloak_admin.get_group_by_name(name_or_path='group_id', search_in_subgroups=True)
# Function to trigger user sync from provider
sync_users(storage_id="storage_di", action="action")

377
keycloak/keycloak_admin.py

@ -15,10 +15,16 @@
# You should have received a copy of the GNU Lesser General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from .urls_patterns import URL_ADMIN_USERS_COUNT, URL_ADMIN_USER, URL_ADMIN_USER_CONSENTS, \
# Unless otherwise stated in the comments, "id", in e.g. user_id, refers to the
# internal Keycloak server ID, usually a uuid string
from keycloak.urls_patterns import URL_ADMIN_CLIENT_ROLE
from .urls_patterns import \
URL_ADMIN_USERS_COUNT, URL_ADMIN_USER, URL_ADMIN_USER_CONSENTS, \
URL_ADMIN_SEND_UPDATE_ACCOUNT, URL_ADMIN_RESET_PASSWORD, URL_ADMIN_SEND_VERIFY_EMAIL, URL_ADMIN_GET_SESSIONS, \
URL_ADMIN_SERVER_INFO, URL_ADMIN_CLIENTS, URL_ADMIN_CLIENT, URL_ADMIN_CLIENT_ROLES, URL_ADMIN_REALM_ROLES, \
URL_ADMIN_USER_CLIENT_ROLES, URL_ADMIN_USER_STORAGE
URL_ADMIN_GROUP, URL_ADMIN_GROUPS, URL_ADMIN_GROUP_CHILD, URL_ADMIN_USER_GROUP,\
URL_ADMIN_GROUP_PERMISSIONS, URL_ADMIN_USER_CLIENT_ROLES, URL_ADMIN_USER_STORAGE
from .keycloak_openid import KeycloakOpenID
from .exceptions import raise_error_from_response, KeycloakGetError
@ -33,14 +39,24 @@ import json
class KeycloakAdmin:
def __init__(self, server_url, verify, username, password, realm_name='master', client_id='admin-cli'):
def __init__(self, server_url, username, password, realm_name='master', client_id='admin-cli', verify=True):
"""
:param server_url: Keycloak server url
:param username: admin username
:param password: admin password
:param realm_name: realm name
:param client_id: client id
:param verify: True if want check connection SSL
"""
self._username = username
self._password = password
self._client_id = client_id
self._realm_name = realm_name
# Get token Admin
keycloak_openid = KeycloakOpenID(server_url=server_url, client_id=client_id, realm_name=realm_name, verify=verify)
keycloak_openid = KeycloakOpenID(server_url=server_url, client_id=client_id, realm_name=realm_name,
verify=verify)
self._token = keycloak_openid.token(username, password)
self._connection = ConnectionManager(base_url=server_url,
@ -138,20 +154,21 @@ class KeycloakAdmin:
Get internal keycloak user id from username
This is required for further actions against this user.
:param username:
clientId in UserRepresentation
UserRepresentation
http://www.keycloak.org/docs-api/3.3/rest-api/index.html#_userrepresentation
:return: user_id (uuid as string)
:param username: id in UserRepresentation
:return: user_id
"""
params_path = {"realm-name": self.realm_name, "username": username}
data_raw = self.connection.raw_get(URL_ADMIN_USERS.format(**params_path))
data_content = raise_error_from_response(data_raw, KeycloakGetError)
for user in data_content:
thisusername = json.dumps(user["username"]).strip('"')
if thisusername == username:
return json.dumps(user["id"]).strip('"')
this_use_rname = json.dumps(user["username"]).strip('"')
if this_use_rname == username:
return json.dumps(user["id"]).strip('"')
return None
@ -195,6 +212,26 @@ class KeycloakAdmin:
data_raw = self.connection.raw_delete(URL_ADMIN_USER.format(**params_path))
return raise_error_from_response(data_raw, KeycloakGetError, expected_code=204)
def set_user_password(self, user_id, password, temporary=True):
"""
Set up a password for the user. If temporary is True, the user will have to reset
the temporary password next time they log in.
http://www.keycloak.org/docs-api/3.2/rest-api/#_users_resource
http://www.keycloak.org/docs-api/3.2/rest-api/#_credentialrepresentation
:param user_id: User id
:param password: New password
:param temporary: True if password is temporary
:return:
"""
payload = {"type": "password", "temporary": temporary, "value": password}
params_path = {"realm-name": self.realm_name, "id": user_id}
data_raw = self.connection.raw_put(URL_ADMIN_RESET_PASSWORD.format(**params_path),
data=json.dumps(payload))
return raise_error_from_response(data_raw, KeycloakGetError, expected_code=204)
def consents_user(self, user_id):
"""
Get consents granted by the user
@ -247,7 +284,7 @@ class KeycloakAdmin:
"""
Get sessions associated with the user
:param user_id: User id
:param user_id: id of user
UserSessionRepresentation
http://www.keycloak.org/docs-api/3.3/rest-api/index.html#_usersessionrepresentation
@ -270,41 +307,162 @@ class KeycloakAdmin:
data_raw = self.connection.raw_get(URL_ADMIN_SERVER_INFO)
return raise_error_from_response(data_raw, KeycloakGetError)
def get_clients(self):
def get_groups(self):
"""
Get clients belonging to the realm Returns a list of clients belonging to the realm
Get groups belonging to the realm. Returns a list of groups belonging to the realm
ClientRepresentation
http://www.keycloak.org/docs-api/3.3/rest-api/index.html#_clientrepresentation
GroupRepresentation
http://www.keycloak.org/docs-api/3.2/rest-api/#_grouprepresentation
:return: ClientRepresentation
:return: array GroupRepresentation
"""
params_path = {"realm-name": self.realm_name}
data_raw = self.connection.raw_get(URL_ADMIN_CLIENTS.format(**params_path))
data_raw = self.connection.raw_get(URL_ADMIN_GROUPS.format(**params_path))
return raise_error_from_response(data_raw, KeycloakGetError)
def get_client_id(self, client_id_name):
def get_group(self, group_id):
"""
Get internal keycloak client id from client-id.
This is required for further actions against this client.
Get group by id. Returns full group details
:param client_id_name:
clientId in ClientRepresentation
http://www.keycloak.org/docs-api/3.3/rest-api/index.html#_clientrepresentation
GroupRepresentation
http://www.keycloak.org/docs-api/3.2/rest-api/#_grouprepresentation
:return: client_id (uuid as string)
:return: Keycloak server response (GroupRepresentation)
"""
params_path = {"realm-name": self.realm_name, "clientId": client_id_name}
data_raw = self.connection.raw_get(URL_ADMIN_CLIENTS.format(**params_path))
data_content = raise_error_from_response(data_raw, KeycloakGetError)
params_path = {"realm-name": self.realm_name, "id": group_id}
data_raw = self.connection.raw_get(URL_ADMIN_GROUP.format(**params_path))
return raise_error_from_response(data_raw, KeycloakGetError)
for client in data_content:
client_id = json.dumps(client["clientId"]).strip('"')
if client_id == client_id_name:
return json.dumps(client["id"]).strip('"')
def get_group_by_name(self, name_or_path, search_in_subgroups=False):
"""
Get group id based on name or path.
A straight name or path match with a top-level group will return first.
Subgroups are traversed, the first to match path (or name with path) is returned.
GroupRepresentation
http://www.keycloak.org/docs-api/3.2/rest-api/#_grouprepresentation
:param name: group name
:param path: group path
:param search_in_subgroups: True if want search in the subgroups
:return: Keycloak server response (GroupRepresentation)
"""
groups = self.get_groups()
# TODO: Review this code is necessary
for group in groups:
if group['name'] == name_or_path or group['path'] == name_or_path:
return group
elif search_in_subgroups and group["subGroups"]:
for subgroup in group["subGroups"]:
if subgroup['name'] == name_or_path or subgroup['path'] == name_or_path:
return subgroup
return None
def create_group(self, name=None, client_roles={}, realm_roles=[], sub_groups=[], path=None, parent=None):
"""
Create a group in the Realm
GroupRepresentation
http://www.keycloak.org/docs-api/3.2/rest-api/#_grouprepresentation
:param name: group name
:param client_roles: (Dict) Client roles to include in groupp # Not demonstrated to work
:param realm_roles: (List) Realm roles to include in group # Not demonstrated to work
:param sub_groups: (List) Subgroups to include in groupp # Not demonstrated to work
:param path: group path
:param parent: parent group's id. Required to create a sub-group.
:return: Keycloak server response (GroupRepresentation)
"""
data = {"name": name or path,
"path": path,
"clientRoles": client_roles,
"realmRoles": realm_roles,
"subGroups": sub_groups}
if parent is None:
params_path = {"realm-name": self.realm_name}
data_raw = self.connection.raw_post(URL_ADMIN_GROUPS.format(**params_path),
data=json.dumps(data))
else:
params_path = {"realm-name": self.realm_name, "id": parent}
data_raw = self.connection.raw_post(URL_ADMIN_GROUP_CHILD.format(**params_path),
data=json.dumps(data))
return raise_error_from_response(data_raw, KeycloakGetError, expected_code=201)
def group_set_permissions(self, group_id, enabled=True):
"""
Enable/Disable permissions for a group. Cannot delete group if disabled
:param group_id: id of group
:param enabled: boolean
:return: Keycloak server response
"""
params_path = {"realm-name": self.realm_name, "id": group_id}
data_raw = self.connection.raw_put(URL_ADMIN_GROUP_PERMISSIONS.format(**params_path),
data=json.dumps({"enabled": enabled}))
return raise_error_from_response(data_raw, KeycloakGetError)
def group_user_add(self, user_id, group_id):
"""
Add user to group (user_id and group_id)
:param group_id: id of group
:param user_id: id of user
:param group_id: id of group to add to
:return: Keycloak server response
"""
params_path = {"realm-name": self.realm_name, "id": user_id, "group-id": group_id}
data_raw = self.connection.raw_put(URL_ADMIN_USER_GROUP.format(**params_path), data=None)
return raise_error_from_response(data_raw, KeycloakGetError, expected_code=204)
def group_user_remove(self, user_id, group_id):
"""
Remove user from group (user_id and group_id)
:param group_id: id of group
:param user_id: id of user
:param group_id: id of group to add to
:return: Keycloak server response
"""
params_path = {"realm-name": self.realm_name, "id": user_id, "group-id": group_id}
data_raw = self.connection.raw_delete(URL_ADMIN_USER_GROUP.format(**params_path))
return raise_error_from_response(data_raw, KeycloakGetError, expected_code=204)
def delete_group(self, group_id):
"""
Deletes a group in the Realm
:param group_id: id of group to delete
:return: Keycloak server response
"""
params_path = {"realm-name": self.realm_name, "id": group_id}
data_raw = self.connection.raw_delete(URL_ADMIN_GROUP.format(**params_path))
return raise_error_from_response(data_raw, KeycloakGetError, expected_code=204)
def get_clients(self):
"""
Get clients belonging to the realm Returns a list of clients belonging to the realm
ClientRepresentation
http://www.keycloak.org/docs-api/3.3/rest-api/index.html#_clientrepresentation
:return: Keycloak server response (ClientRepresentation)
"""
params_path = {"realm-name": self.realm_name}
data_raw = self.connection.raw_get(URL_ADMIN_CLIENTS.format(**params_path))
return raise_error_from_response(data_raw, KeycloakGetError)
def get_client(self, client_id):
"""
Get representation of the client
@ -312,34 +470,45 @@ class KeycloakAdmin:
ClientRepresentation
http://www.keycloak.org/docs-api/3.3/rest-api/index.html#_clientrepresentation
:param client_id: id of client (not client-id)
:return: ClientRepresentation
:param client_id: id of client (not client-id)
:return: Keycloak server response (ClientRepresentation)
"""
params_path = {"realm-name": self.realm_name, "id": client_id}
data_raw = self.connection.raw_get(URL_ADMIN_CLIENT.format(**params_path))
return raise_error_from_response(data_raw, KeycloakGetError)
def create_client(self, name, client_id, redirect_urls, protocol="openid-connect", public_client=True, direct_access_grants=True):
def get_client_id(self, client_name):
"""
Create a client
:param name: name of client, payload (ClientRepresentation)
Get internal keycloak client id from client-id.
This is required for further actions against this client.
ClientRepresentation
:param client_name: name in ClientRepresentation
http://www.keycloak.org/docs-api/3.3/rest-api/index.html#_clientrepresentation
:return: client_id (uuid as string)
"""
clients = self.get_clients()
for client in clients:
if client_name == client['name']:
return client["id"]
return None
def create_client(self, payload):
"""
data={}
data["name"]=name
data["clientId"]=client_id
data["redirectUris"]=redirect_urls
data["protocol"]=protocol
data["publicClient"]=public_client
data["directAccessGrantsEnabled"]=direct_access_grants
Create a client
ClientRepresentation: http://www.keycloak.org/docs-api/3.3/rest-api/index.html#_clientrepresentation
:param payload: ClientRepresentation
:return: Keycloak server response (UserRepresentation)
"""
params_path = {"realm-name": self.realm_name}
data_raw = self.connection.raw_post(URL_ADMIN_CLIENTS.format(**params_path),
data=json.dumps(data))
data=json.dumps(payload))
return raise_error_from_response(data_raw, KeycloakGetError, expected_code=201)
def delete_client(self, client_id):
@ -349,121 +518,137 @@ class KeycloakAdmin:
ClientRepresentation
http://www.keycloak.org/docs-api/3.3/rest-api/index.html#_clientrepresentation
:param client_id: id of client (not client-id)
:return: ClientRepresentation
:param client_id: keycloak client id (not oauth client-id)
:return: Keycloak server response (ClientRepresentation)
"""
params_path = {"realm-name": self.realm_name, "id": client_id}
data_raw = self.connection.raw_delete(URL_ADMIN_CLIENT.format(**params_path))
return raise_error_from_response(data_raw, KeycloakGetError, expected_code=204)
def get_client_roles(self, client_id):
def get_realm_roles(self):
"""
Get all roles for the client
Get all roles for the realm or client
RoleRepresentation
http://www.keycloak.org/docs-api/3.3/rest-api/index.html#_rolerepresentation
:return: Keycloak server response (RoleRepresentation)
"""
params_path = {"realm-name": self.realm_name}
data_raw = self.connection.raw_get(URL_ADMIN_REALM_ROLES.format(**params_path))
return raise_error_from_response(data_raw, KeycloakGetError)
def get_client_roles(self, client_id):
"""
Get all roles for the client
:param client_id: id of client (not client-id)
:return: RoleRepresentation
RoleRepresentation
http://www.keycloak.org/docs-api/3.3/rest-api/index.html#_rolerepresentation
:return: Keycloak server response (RoleRepresentation)
"""
params_path = {"realm-name": self.realm_name, "id": client_id}
data_raw = self.connection.raw_get(URL_ADMIN_CLIENT_ROLES.format(**params_path))
return raise_error_from_response(data_raw, KeycloakGetError)
def get_client_role_id(self, client_id, role_name):
def get_client_role(self, client_id, role_name):
"""
Get client role id
Get client role id by name
This is required for further actions with this role.
:param client_id: id of client (not client-id)
:param role_name: roles name (not id!)
RoleRepresentation
http://www.keycloak.org/docs-api/3.3/rest-api/index.html#_rolerepresentation
:param client_id: id of client (not client-id), role_name: name of role
:return: role_id
"""
params_path = {"realm-name": self.realm_name, "id": client_id}
data_raw = self.connection.raw_get(URL_ADMIN_CLIENT_ROLES.format(**params_path))
data_content = raise_error_from_response(data_raw, KeycloakGetError)
params_path = {"realm-name": self.realm_name, "id": client_id, "role-name": role_name}
data_raw = self.connection.raw_get(URL_ADMIN_CLIENT_ROLE.format(**params_path))
return raise_error_from_response(data_raw, KeycloakGetError)
for role in data_content:
this_role_name = json.dumps(role["name"]).strip('"')
if this_role_name == role_name:
return json.dumps(role["id"]).strip('"')
def get_client_role_id(self, client_id, role_name):
"""
Warning: Deprecated
return None
Get client role id by name
This is required for further actions with this role.
def get_roles(self):
"""
Get all roles for the realm or client
:param client_id: id of client (not client-id)
:param role_name: roles name (not id!)
RoleRepresentation
http://www.keycloak.org/docs-api/3.3/rest-api/index.html#_rolerepresentation
:return: RoleRepresentation
:return: role_id
"""
params_path = {"realm-name": self.realm_name}
data_raw = self.connection.raw_get(URL_ADMIN_REALM_ROLES.format(**params_path))
return raise_error_from_response(data_raw, KeycloakGetError)
role = self.get_client_role(client_id, role_name)
return role.get("id")
def create_client_role(self, client_id, role_name):
def create_client_role(self, payload):
"""
Create a client role
:param client_id: id of client (not client-id), payload (RoleRepresentation)
RoleRepresentation
http://www.keycloak.org/docs-api/3.3/rest-api/index.html#_rolerepresentation
:param payload: id of client (not client-id), role_name: name of role
:return: Keycloak server response (RoleRepresentation)
"""
data={}
data["name"]=role_name
data["clientRole"]=True
params_path = {"realm-name": self.realm_name, "id": client_id}
params_path = {"realm-name": self.realm_name, "id": self.client_id}
data_raw = self.connection.raw_post(URL_ADMIN_CLIENT_ROLES.format(**params_path),
data=json.dumps(data))
data=json.dumps(payload))
return raise_error_from_response(data_raw, KeycloakGetError, expected_code=201)
def delete_client_role(self, client_id, role_name):
def delete_client_role(self, role_name):
"""
Create a client role
:param client_id: id of client (not client-id), payload (RoleRepresentation)
RoleRepresentation
http://www.keycloak.org/docs-api/3.3/rest-api/index.html#_rolerepresentation
:param role_name: roles name (not id!)
"""
data={}
data["name"]=role_name
data["clientRole"]=True
params_path = {"realm-name": self.realm_name, "id": client_id}
data_raw = self.connection.raw_delete(URL_ADMIN_CLIENT_ROLES.format(**params_path) + "/" + role_name,
data=json.dumps(data))
params_path = {"realm-name": self.realm_name, "id": self.client_id, "role-name": role_name}
data_raw = self.connection.raw_delete(URL_ADMIN_CLIENT_ROLE.format(**params_path))
return raise_error_from_response(data_raw, KeycloakGetError, expected_code=204)
def assign_client_role(self, user_id, client_id, role_id, role_name):
def assign_client_role(self, user_id, client_id, roles):
"""
Assign a client role to a user
:param client_id: id of client (not client-id), user_id: id of user, client_id: id of client containing role, role_id: client role id, role_name: client role name)
:param client_id: id of client (not client-id)
:param user_id: id of user
:param client_id: id of client containing role,
:param roles: roles list or role (use RoleRepresentation)
:return Keycloak server response
"""
payload=[{}]
payload[0]["id"]=role_id
payload[0]["name"]=role_name
payload = roles if isinstance(roles, list) else [roles]
params_path = {"realm-name": self.realm_name, "id": user_id, "client-id": client_id}
data_raw = self.connection.raw_post(URL_ADMIN_USER_CLIENT_ROLES.format(**params_path),
data=json.dumps(payload))
return raise_error_from_response(data_raw, KeycloakGetError, expected_code=204)
def sync_users(self, storage_id, action):
"""
Function to trigger user sync from provider
:param storage_id:
:param action:
:return:
"""
data = {'action': action}
params_path = {"realm-name": self.realm_name, "id": storage_id}
params_query = {"action": action}
params_path = {"realm-name": self.realm_name, "id": storage_id}
data_raw = self.connection.raw_post(URL_ADMIN_USER_STORAGE.format(**params_path),
data=json.dumps(data), **params_query)
return raise_error_from_response(data_raw, KeycloakGetError)

30
keycloak/keycloak_openid.py

@ -34,7 +34,15 @@ import json
class KeycloakOpenID:
def __init__(self, server_url, verify, client_id, realm_name, client_secret_key=None):
def __init__(self, server_url, realm_name, client_id, client_secret_key=None, verify=True):
"""
:param server_url: Keycloak server url
:param client_id: client id
:param realm_name: realm name
:param client_secret_key: client secret key
:param verify: True if want check connection SSL
"""
self._client_id = client_id
self._client_secret_key = client_secret_key
self._realm_name = realm_name
@ -165,6 +173,26 @@ class KeycloakOpenID:
data=payload)
return raise_error_from_response(data_raw, KeycloakGetError)
def refresh_token(self, refresh_token, grant_type=["refresh_token"]):
"""
The token endpoint is used to obtain tokens. Tokens can either be obtained by
exchanging an authorization code or by supplying credentials directly depending on
what flow is used. The token endpoint is also used to obtain new access tokens
when they expire.
http://openid.net/specs/openid-connect-core-1_0.html#TokenEndpoint
:param refresh_token:
:param grant_type:
:return:
"""
params_path = {"realm-name": self.realm_name}
payload = {"client_id": self.client_id, "grant_type": grant_type, "refresh_token": refresh_token}
payload = self._add_secret_key(payload)
data_raw = self.connection.raw_post(URL_TOKEN.format(**params_path),
data=payload)
return raise_error_from_response(data_raw, KeycloakGetError)
def userinfo(self, token):
"""
The userinfo endpoint returns standard claims about the authenticated user,

7
keycloak/urls_patterns.py

@ -34,12 +34,19 @@ URL_ADMIN_SEND_VERIFY_EMAIL = "admin/realms/{realm-name}/users/{id}/send-verify-
URL_ADMIN_RESET_PASSWORD = "admin/realms/{realm-name}/users/{id}/reset-password"
URL_ADMIN_GET_SESSIONS = "admin/realms/{realm-name}/users/{id}/sessions"
URL_ADMIN_USER_CLIENT_ROLES = "admin/realms/{realm-name}/users/{id}/role-mappings/clients/{client-id}"
URL_ADMIN_USER_GROUP = "admin/realms/{realm-name}/users/{id}/groups/{group-id}"
URL_ADMIN_SERVER_INFO = "admin/serverinfo"
URL_ADMIN_GROUPS = "admin/realms/{realm-name}/groups"
URL_ADMIN_GROUP = "admin/realms/{realm-name}/groups/{id}"
URL_ADMIN_GROUP_CHILD = "admin/realms/{realm-name}/groups/{id}/children"
URL_ADMIN_GROUP_PERMISSIONS = "admin/realms/{realm-name}/groups/{id}/management/permissions"
URL_ADMIN_CLIENTS = "admin/realms/{realm-name}/clients"
URL_ADMIN_CLIENT = "admin/realms/{realm-name}/clients/{id}"
URL_ADMIN_CLIENT_ROLES = "admin/realms/{realm-name}/clients/{id}/roles"
URL_ADMIN_CLIENT_ROLE = "admin/realms/{realm-name}/clients/{id}/roles/{role-name}"
URL_ADMIN_REALM_ROLES = "admin/realms/{realm-name}/roles"

Loading…
Cancel
Save