You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1201 lines
45 KiB

  1. import pytest
  2. import keycloak
  3. from keycloak import KeycloakAdmin
  4. from keycloak.connection import ConnectionManager
  5. from keycloak.exceptions import (
  6. KeycloakDeleteError,
  7. KeycloakGetError,
  8. KeycloakPostError,
  9. KeycloakPutError,
  10. )
  11. def test_keycloak_version():
  12. assert keycloak.__version__, keycloak.__version__
  13. def test_keycloak_admin_bad_init(env):
  14. with pytest.raises(TypeError) as err:
  15. KeycloakAdmin(
  16. server_url=f"http://{env.KEYCLOAK_HOST}:{env.KEYCLOAK_PORT}",
  17. username=env.KEYCLOAK_ADMIN,
  18. password=env.KEYCLOAK_ADMIN_PASSWORD,
  19. auto_refresh_token=1,
  20. )
  21. assert err.match("Expected a list of strings")
  22. with pytest.raises(TypeError) as err:
  23. KeycloakAdmin(
  24. server_url=f"http://{env.KEYCLOAK_HOST}:{env.KEYCLOAK_PORT}",
  25. username=env.KEYCLOAK_ADMIN,
  26. password=env.KEYCLOAK_ADMIN_PASSWORD,
  27. auto_refresh_token=["patch"],
  28. )
  29. assert err.match("Unexpected method in auto_refresh_token")
  30. def test_keycloak_admin_init(env):
  31. admin = KeycloakAdmin(
  32. server_url=f"http://{env.KEYCLOAK_HOST}:{env.KEYCLOAK_PORT}",
  33. username=env.KEYCLOAK_ADMIN,
  34. password=env.KEYCLOAK_ADMIN_PASSWORD,
  35. )
  36. assert admin.server_url == f"http://{env.KEYCLOAK_HOST}:{env.KEYCLOAK_PORT}", admin.server_url
  37. assert admin.realm_name == "master", admin.realm_name
  38. assert isinstance(admin.connection, ConnectionManager), type(admin.connection)
  39. assert admin.client_id == "admin-cli", admin.client_id
  40. assert admin.client_secret_key is None, admin.client_secret_key
  41. assert admin.verify, admin.verify
  42. assert admin.username == env.KEYCLOAK_ADMIN, admin.username
  43. assert admin.password == env.KEYCLOAK_ADMIN_PASSWORD, admin.password
  44. assert admin.totp is None, admin.totp
  45. assert admin.token is not None, admin.token
  46. assert admin.auto_refresh_token == list(), admin.auto_refresh_token
  47. assert admin.user_realm_name is None, admin.user_realm_name
  48. assert admin.custom_headers is None, admin.custom_headers
  49. def test_realms(admin: KeycloakAdmin):
  50. # Get realms
  51. realms = admin.get_realms()
  52. assert len(realms) == 1, realms
  53. assert "master" == realms[0]["realm"]
  54. # Create a test realm
  55. res = admin.create_realm(payload={"realm": "test"})
  56. assert res == b"", res
  57. # Create the same realm, should fail
  58. with pytest.raises(KeycloakPostError) as err:
  59. res = admin.create_realm(payload={"realm": "test"})
  60. assert err.match('409: b\'{"errorMessage":"Conflict detected. See logs for details"}\'')
  61. # Create the same realm, skip_exists true
  62. res = admin.create_realm(payload={"realm": "test"}, skip_exists=True)
  63. assert res == {"msg": "Already exists"}, res
  64. # Get a single realm
  65. res = admin.get_realm(realm_name="test")
  66. assert res["realm"] == "test"
  67. # Get non-existing realm
  68. with pytest.raises(KeycloakGetError) as err:
  69. admin.get_realm(realm_name="non-existent")
  70. assert err.match('404: b\'{"error":"Realm not found."}\'')
  71. # Update realm
  72. res = admin.update_realm(realm_name="test", payload={"accountTheme": "test"})
  73. assert res == dict(), res
  74. # Check that the update worked
  75. res = admin.get_realm(realm_name="test")
  76. assert res["realm"] == "test"
  77. assert res["accountTheme"] == "test"
  78. # Update wrong payload
  79. with pytest.raises(KeycloakPutError) as err:
  80. admin.update_realm(realm_name="test", payload={"wrong": "payload"})
  81. assert err.match('400: b\'{"error":"Unrecognized field')
  82. # Check that get realms returns both realms
  83. realms = admin.get_realms()
  84. realm_names = [x["realm"] for x in realms]
  85. assert len(realms) == 2, realms
  86. assert "master" in realm_names, realm_names
  87. assert "test" in realm_names, realm_names
  88. # Delete the realm
  89. res = admin.delete_realm(realm_name="test")
  90. assert res == dict(), res
  91. # Check that the realm does not exist anymore
  92. with pytest.raises(KeycloakGetError) as err:
  93. admin.get_realm(realm_name="test")
  94. assert err.match('404: b\'{"error":"Realm not found."}\'')
  95. # Delete non-existing realm
  96. with pytest.raises(KeycloakDeleteError) as err:
  97. admin.delete_realm(realm_name="non-existent")
  98. assert err.match('404: b\'{"error":"Realm not found."}\'')
  99. def test_import_export_realms(admin: KeycloakAdmin, realm: str):
  100. admin.realm_name = realm
  101. realm_export = admin.export_realm(export_clients=True, export_groups_and_role=True)
  102. assert realm_export != dict(), realm_export
  103. admin.delete_realm(realm_name=realm)
  104. admin.realm_name = "master"
  105. res = admin.import_realm(payload=realm_export)
  106. assert res == b"", res
  107. # Test bad import
  108. with pytest.raises(KeycloakPostError) as err:
  109. admin.import_realm(payload=dict())
  110. assert err.match('500: b\'{"error":"unknown_error"}\'')
  111. def test_users(admin: KeycloakAdmin, realm: str):
  112. admin.realm_name = realm
  113. # Check no users present
  114. users = admin.get_users()
  115. assert users == list(), users
  116. # Test create user
  117. user_id = admin.create_user(payload={"username": "test", "email": "test@test.test"})
  118. assert user_id is not None, user_id
  119. # Test create the same user
  120. with pytest.raises(KeycloakPostError) as err:
  121. admin.create_user(payload={"username": "test", "email": "test@test.test"})
  122. assert err.match('409: b\'{"errorMessage":"User exists with same username"}\'')
  123. # Test create the same user, exists_ok true
  124. user_id_2 = admin.create_user(
  125. payload={"username": "test", "email": "test@test.test"}, exist_ok=True
  126. )
  127. assert user_id == user_id_2
  128. # Test get user
  129. user = admin.get_user(user_id=user_id)
  130. assert user["username"] == "test", user["username"]
  131. assert user["email"] == "test@test.test", user["email"]
  132. # Test update user
  133. res = admin.update_user(user_id=user_id, payload={"firstName": "Test"})
  134. assert res == dict(), res
  135. user = admin.get_user(user_id=user_id)
  136. assert user["firstName"] == "Test"
  137. # Test update user fail
  138. with pytest.raises(KeycloakPutError) as err:
  139. admin.update_user(user_id=user_id, payload={"wrong": "payload"})
  140. assert err.match('400: b\'{"error":"Unrecognized field')
  141. # Test get users again
  142. users = admin.get_users()
  143. usernames = [x["username"] for x in users]
  144. assert "test" in usernames
  145. # Test users counts
  146. count = admin.users_count()
  147. assert count == 1, count
  148. # Test user groups
  149. groups = admin.get_user_groups(user_id=user["id"])
  150. assert len(groups) == 0
  151. # Test user groups bad id
  152. with pytest.raises(KeycloakGetError) as err:
  153. admin.get_user_groups(user_id="does-not-exist")
  154. assert err.match('404: b\'{"error":"User not found"}\'')
  155. # Test logout
  156. res = admin.user_logout(user_id=user["id"])
  157. assert res == dict(), res
  158. # Test logout fail
  159. with pytest.raises(KeycloakPostError) as err:
  160. admin.user_logout(user_id="non-existent-id")
  161. assert err.match('404: b\'{"error":"User not found"}\'')
  162. # Test consents
  163. res = admin.user_consents(user_id=user["id"])
  164. assert len(res) == 0, res
  165. # Test consents fail
  166. with pytest.raises(KeycloakGetError) as err:
  167. admin.user_consents(user_id="non-existent-id")
  168. assert err.match('404: b\'{"error":"User not found"}\'')
  169. # Test delete user
  170. res = admin.delete_user(user_id=user_id)
  171. assert res == dict(), res
  172. with pytest.raises(KeycloakGetError) as err:
  173. admin.get_user(user_id=user_id)
  174. err.match('404: b\'{"error":"User not found"}\'')
  175. # Test delete fail
  176. with pytest.raises(KeycloakDeleteError) as err:
  177. admin.delete_user(user_id="non-existent-id")
  178. assert err.match('404: b\'{"error":"User not found"}\'')
  179. def test_users_pagination(admin: KeycloakAdmin, realm: str):
  180. admin.realm_name = realm
  181. for ind in range(admin.PAGE_SIZE + 50):
  182. username = f"user_{ind}"
  183. admin.create_user(payload={"username": username, "email": f"{username}@test.test"})
  184. users = admin.get_users()
  185. assert len(users) == admin.PAGE_SIZE + 50, len(users)
  186. users = admin.get_users(query={"first": 100})
  187. assert len(users) == 50, len(users)
  188. users = admin.get_users(query={"max": 20})
  189. assert len(users) == 20, len(users)
  190. def test_idps(admin: KeycloakAdmin, realm: str):
  191. admin.realm_name = realm
  192. # Create IDP
  193. res = admin.create_idp(
  194. payload=dict(
  195. providerId="github", alias="github", config=dict(clientId="test", clientSecret="test")
  196. )
  197. )
  198. assert res == b"", res
  199. # Test create idp fail
  200. with pytest.raises(KeycloakPostError) as err:
  201. admin.create_idp(payload={"providerId": "does-not-exist", "alias": "something"})
  202. assert err.match("Invalid identity provider id"), err
  203. # Test listing
  204. idps = admin.get_idps()
  205. assert len(idps) == 1
  206. assert "github" == idps[0]["alias"]
  207. # Test adding a mapper
  208. res = admin.add_mapper_to_idp(
  209. idp_alias="github",
  210. payload={
  211. "identityProviderAlias": "github",
  212. "identityProviderMapper": "github-user-attribute-mapper",
  213. "name": "test",
  214. },
  215. )
  216. assert res == b"", res
  217. # Test mapper fail
  218. with pytest.raises(KeycloakPostError) as err:
  219. admin.add_mapper_to_idp(idp_alias="does-no-texist", payload=dict())
  220. assert err.match('404: b\'{"error":"HTTP 404 Not Found"}\'')
  221. # Test delete
  222. res = admin.delete_idp(idp_alias="github")
  223. assert res == dict(), res
  224. # Test delete fail
  225. with pytest.raises(KeycloakDeleteError) as err:
  226. admin.delete_idp(idp_alias="does-not-exist")
  227. assert err.match('404: b\'{"error":"HTTP 404 Not Found"}\'')
  228. def test_user_credentials(admin: KeycloakAdmin, user: str):
  229. res = admin.set_user_password(user_id=user, password="booya", temporary=True)
  230. assert res == dict(), res
  231. # Test user password set fail
  232. with pytest.raises(KeycloakPutError) as err:
  233. admin.set_user_password(user_id="does-not-exist", password="")
  234. assert err.match('404: b\'{"error":"User not found"}\'')
  235. credentials = admin.get_credentials(user_id=user)
  236. assert len(credentials) == 1
  237. assert credentials[0]["type"] == "password", credentials
  238. # Test get credentials fail
  239. with pytest.raises(KeycloakGetError) as err:
  240. admin.get_credentials(user_id="does-not-exist")
  241. assert err.match('404: b\'{"error":"User not found"}\'')
  242. res = admin.delete_credential(user_id=user, credential_id=credentials[0]["id"])
  243. assert res == dict(), res
  244. # Test delete fail
  245. with pytest.raises(KeycloakDeleteError) as err:
  246. admin.delete_credential(user_id=user, credential_id="does-not-exist")
  247. assert err.match('404: b\'{"error":"Credential not found"}\'')
  248. def test_social_logins(admin: KeycloakAdmin, user: str):
  249. res = admin.add_user_social_login(
  250. user_id=user, provider_id="gitlab", provider_userid="test", provider_username="test"
  251. )
  252. assert res == dict(), res
  253. admin.add_user_social_login(
  254. user_id=user, provider_id="github", provider_userid="test", provider_username="test"
  255. )
  256. assert res == dict(), res
  257. # Test add social login fail
  258. with pytest.raises(KeycloakPostError) as err:
  259. admin.add_user_social_login(
  260. user_id="does-not-exist",
  261. provider_id="does-not-exist",
  262. provider_userid="test",
  263. provider_username="test",
  264. )
  265. assert err.match('404: b\'{"error":"User not found"}\'')
  266. res = admin.get_user_social_logins(user_id=user)
  267. assert res == list(), res
  268. # Test get social logins fail
  269. with pytest.raises(KeycloakGetError) as err:
  270. admin.get_user_social_logins(user_id="does-not-exist")
  271. assert err.match('404: b\'{"error":"User not found"}\'')
  272. res = admin.delete_user_social_login(user_id=user, provider_id="gitlab")
  273. assert res == {}, res
  274. res = admin.delete_user_social_login(user_id=user, provider_id="github")
  275. assert res == {}, res
  276. with pytest.raises(KeycloakDeleteError) as err:
  277. admin.delete_user_social_login(user_id=user, provider_id="instagram")
  278. assert err.match('404: b\'{"error":"Link not found"}\''), err
  279. def test_server_info(admin: KeycloakAdmin):
  280. info = admin.get_server_info()
  281. assert set(info.keys()) == {
  282. "systemInfo",
  283. "memoryInfo",
  284. "profileInfo",
  285. "themes",
  286. "socialProviders",
  287. "identityProviders",
  288. "providers",
  289. "protocolMapperTypes",
  290. "builtinProtocolMappers",
  291. "clientInstallations",
  292. "componentTypes",
  293. "passwordPolicies",
  294. "enums",
  295. }, info.keys()
  296. def test_groups(admin: KeycloakAdmin, user: str):
  297. # Test get groups
  298. groups = admin.get_groups()
  299. assert len(groups) == 0
  300. # Test create group
  301. group_id = admin.create_group(payload={"name": "main-group"})
  302. assert group_id is not None, group_id
  303. # Test create subgroups
  304. subgroup_id_1 = admin.create_group(payload={"name": "subgroup-1"}, parent=group_id)
  305. subgroup_id_2 = admin.create_group(payload={"name": "subgroup-2"}, parent=group_id)
  306. # Test create group fail
  307. with pytest.raises(KeycloakPostError) as err:
  308. admin.create_group(payload={"name": "subgroup-1"}, parent=group_id)
  309. assert err.match('409: b\'{"error":"unknown_error"}\''), err
  310. # Test skip exists OK
  311. subgroup_id_1_eq = admin.create_group(
  312. payload={"name": "subgroup-1"}, parent=group_id, skip_exists=True
  313. )
  314. assert subgroup_id_1_eq is None
  315. # Test get groups again
  316. groups = admin.get_groups()
  317. assert len(groups) == 1, groups
  318. assert len(groups[0]["subGroups"]) == 2, groups["subGroups"]
  319. assert groups[0]["id"] == group_id
  320. assert {x["id"] for x in groups[0]["subGroups"]} == {subgroup_id_1, subgroup_id_2}
  321. # Test get groups query
  322. groups = admin.get_groups(query={"max": 10})
  323. assert len(groups) == 1, groups
  324. assert len(groups[0]["subGroups"]) == 2, groups["subGroups"]
  325. assert groups[0]["id"] == group_id
  326. assert {x["id"] for x in groups[0]["subGroups"]} == {subgroup_id_1, subgroup_id_2}
  327. # Test get group
  328. res = admin.get_group(group_id=subgroup_id_1)
  329. assert res["id"] == subgroup_id_1, res
  330. assert res["name"] == "subgroup-1"
  331. assert res["path"] == "/main-group/subgroup-1"
  332. # Test get group fail
  333. with pytest.raises(KeycloakGetError) as err:
  334. admin.get_group(group_id="does-not-exist")
  335. assert err.match('404: b\'{"error":"Could not find group by id"}\''), err
  336. # Create 1 more subgroup
  337. subsubgroup_id_1 = admin.create_group(payload={"name": "subsubgroup-1"}, parent=subgroup_id_2)
  338. main_group = admin.get_group(group_id=group_id)
  339. # Test nested searches
  340. res = admin.get_subgroups(group=main_group, path="/main-group/subgroup-2/subsubgroup-1")
  341. assert res is not None, res
  342. assert res["id"] == subsubgroup_id_1
  343. # Test empty search
  344. res = admin.get_subgroups(group=main_group, path="/none")
  345. assert res is None, res
  346. # Test get group by path
  347. res = admin.get_group_by_path(path="/main-group/subgroup-1")
  348. assert res is None, res
  349. res = admin.get_group_by_path(path="/main-group/subgroup-1", search_in_subgroups=True)
  350. assert res is not None, res
  351. assert res["id"] == subgroup_id_1, res
  352. res = admin.get_group_by_path(
  353. path="/main-group/subgroup-2/subsubgroup-1/test", search_in_subgroups=True
  354. )
  355. assert res is None, res
  356. res = admin.get_group_by_path(
  357. path="/main-group/subgroup-2/subsubgroup-1", search_in_subgroups=True
  358. )
  359. assert res is not None, res
  360. assert res["id"] == subsubgroup_id_1
  361. res = admin.get_group_by_path(path="/main-group")
  362. assert res is not None, res
  363. assert res["id"] == group_id, res
  364. # Test group members
  365. res = admin.get_group_members(group_id=subgroup_id_2)
  366. assert len(res) == 0, res
  367. # Test fail group members
  368. with pytest.raises(KeycloakGetError) as err:
  369. admin.get_group_members(group_id="does-not-exist")
  370. assert err.match('404: b\'{"error":"Could not find group by id"}\'')
  371. res = admin.group_user_add(user_id=user, group_id=subgroup_id_2)
  372. assert res == dict(), res
  373. res = admin.get_group_members(group_id=subgroup_id_2)
  374. assert len(res) == 1, res
  375. assert res[0]["id"] == user
  376. # Test get group members query
  377. res = admin.get_group_members(group_id=subgroup_id_2, query={"max": 10})
  378. assert len(res) == 1, res
  379. assert res[0]["id"] == user
  380. with pytest.raises(KeycloakDeleteError) as err:
  381. admin.group_user_remove(user_id="does-not-exist", group_id=subgroup_id_2)
  382. assert err.match('404: b\'{"error":"User not found"}\''), err
  383. res = admin.group_user_remove(user_id=user, group_id=subgroup_id_2)
  384. assert res == dict(), res
  385. # Test set permissions
  386. res = admin.group_set_permissions(group_id=subgroup_id_2, enabled=True)
  387. assert res["enabled"], res
  388. res = admin.group_set_permissions(group_id=subgroup_id_2, enabled=False)
  389. assert not res["enabled"], res
  390. with pytest.raises(KeycloakPutError) as err:
  391. admin.group_set_permissions(group_id=subgroup_id_2, enabled="blah")
  392. assert err.match('500: b\'{"error":"unknown_error"}\''), err
  393. # Test update group
  394. res = admin.update_group(group_id=subgroup_id_2, payload={"name": "new-subgroup-2"})
  395. assert res == dict(), res
  396. assert admin.get_group(group_id=subgroup_id_2)["name"] == "new-subgroup-2"
  397. # test update fail
  398. with pytest.raises(KeycloakPutError) as err:
  399. admin.update_group(group_id="does-not-exist", payload=dict())
  400. assert err.match('404: b\'{"error":"Could not find group by id"}\''), err
  401. # Test delete
  402. res = admin.delete_group(group_id=group_id)
  403. assert res == dict(), res
  404. assert len(admin.get_groups()) == 0
  405. # Test delete fail
  406. with pytest.raises(KeycloakDeleteError) as err:
  407. admin.delete_group(group_id="does-not-exist")
  408. assert err.match('404: b\'{"error":"Could not find group by id"}\''), err
  409. def test_clients(admin: KeycloakAdmin, realm: str):
  410. admin.realm_name = realm
  411. # Test get clients
  412. clients = admin.get_clients()
  413. assert len(clients) == 6, clients
  414. assert {x["name"] for x in clients} == set(
  415. [
  416. "${client_admin-cli}",
  417. "${client_security-admin-console}",
  418. "${client_account-console}",
  419. "${client_broker}",
  420. "${client_account}",
  421. "${client_realm-management}",
  422. ]
  423. ), clients
  424. # Test create client
  425. client_id = admin.create_client(payload={"name": "test-client", "clientId": "test-client"})
  426. assert client_id, client_id
  427. with pytest.raises(KeycloakPostError) as err:
  428. admin.create_client(payload={"name": "test-client", "clientId": "test-client"})
  429. assert err.match('409: b\'{"errorMessage":"Client test-client already exists"}\''), err
  430. client_id_2 = admin.create_client(
  431. payload={"name": "test-client", "clientId": "test-client"}, skip_exists=True
  432. )
  433. assert client_id == client_id_2, client_id_2
  434. # Test get client
  435. res = admin.get_client(client_id=client_id)
  436. assert res["clientId"] == "test-client", res
  437. assert res["name"] == "test-client", res
  438. assert res["id"] == client_id, res
  439. with pytest.raises(KeycloakGetError) as err:
  440. admin.get_client(client_id="does-not-exist")
  441. assert err.match('404: b\'{"error":"Could not find client"}\'')
  442. assert len(admin.get_clients()) == 7
  443. # Test get client id
  444. assert admin.get_client_id(client_name="test-client") == client_id
  445. assert admin.get_client_id(client_name="does-not-exist") is None
  446. # Test update client
  447. res = admin.update_client(client_id=client_id, payload={"name": "test-client-change"})
  448. assert res == dict(), res
  449. with pytest.raises(KeycloakPutError) as err:
  450. admin.update_client(client_id="does-not-exist", payload={"name": "test-client-change"})
  451. assert err.match('404: b\'{"error":"Could not find client"}\'')
  452. # Test authz
  453. auth_client_id = admin.create_client(
  454. payload={
  455. "name": "authz-client",
  456. "clientId": "authz-client",
  457. "authorizationServicesEnabled": True,
  458. "serviceAccountsEnabled": True,
  459. }
  460. )
  461. res = admin.get_client_authz_settings(client_id=auth_client_id)
  462. assert res["allowRemoteResourceManagement"]
  463. assert res["decisionStrategy"] == "UNANIMOUS"
  464. assert len(res["policies"]) >= 0
  465. with pytest.raises(KeycloakGetError) as err:
  466. admin.get_client_authz_settings(client_id=client_id)
  467. assert err.match('500: b\'{"error":"HTTP 500 Internal Server Error"}\'')
  468. # Authz resources
  469. res = admin.get_client_authz_resources(client_id=auth_client_id)
  470. assert len(res) == 1
  471. assert res[0]["name"] == "Default Resource"
  472. with pytest.raises(KeycloakGetError) as err:
  473. admin.get_client_authz_resources(client_id=client_id)
  474. assert err.match('500: b\'{"error":"unknown_error"}\'')
  475. res = admin.create_client_authz_resource(
  476. client_id=auth_client_id, payload={"name": "test-resource"}
  477. )
  478. assert res["name"] == "test-resource", res
  479. test_resource_id = res["_id"]
  480. with pytest.raises(KeycloakPostError) as err:
  481. admin.create_client_authz_resource(
  482. client_id=auth_client_id, payload={"name": "test-resource"}
  483. )
  484. assert err.match('409: b\'{"error":"invalid_request"')
  485. assert admin.create_client_authz_resource(
  486. client_id=auth_client_id, payload={"name": "test-resource"}, skip_exists=True
  487. ) == {"msg": "Already exists"}
  488. res = admin.get_client_authz_resources(client_id=auth_client_id)
  489. assert len(res) == 2
  490. assert {x["name"] for x in res} == {"Default Resource", "test-resource"}
  491. # Authz policies
  492. res = admin.get_client_authz_policies(client_id=auth_client_id)
  493. assert len(res) == 1, res
  494. assert res[0]["name"] == "Default Policy"
  495. assert len(admin.get_client_authz_policies(client_id=client_id)) == 1
  496. with pytest.raises(KeycloakGetError) as err:
  497. admin.get_client_authz_policies(client_id="does-not-exist")
  498. assert err.match('404: b\'{"error":"Could not find client"}\'')
  499. role_id = admin.get_realm_role(role_name="offline_access")["id"]
  500. res = admin.create_client_authz_role_based_policy(
  501. client_id=auth_client_id,
  502. payload={"name": "test-authz-rb-policy", "roles": [{"id": role_id}]},
  503. )
  504. assert res["name"] == "test-authz-rb-policy", res
  505. with pytest.raises(KeycloakPostError) as err:
  506. admin.create_client_authz_role_based_policy(
  507. client_id=auth_client_id,
  508. payload={"name": "test-authz-rb-policy", "roles": [{"id": role_id}]},
  509. )
  510. assert err.match('409: b\'{"error":"Policy with name')
  511. assert admin.create_client_authz_role_based_policy(
  512. client_id=auth_client_id,
  513. payload={"name": "test-authz-rb-policy", "roles": [{"id": role_id}]},
  514. skip_exists=True,
  515. ) == {"msg": "Already exists"}
  516. assert len(admin.get_client_authz_policies(client_id=auth_client_id)) == 2
  517. # Test authz permissions
  518. res = admin.get_client_authz_permissions(client_id=auth_client_id)
  519. assert len(res) == 1, res
  520. assert res[0]["name"] == "Default Permission"
  521. assert len(admin.get_client_authz_permissions(client_id=client_id)) == 1
  522. with pytest.raises(KeycloakGetError) as err:
  523. admin.get_client_authz_permissions(client_id="does-not-exist")
  524. assert err.match('404: b\'{"error":"Could not find client"}\'')
  525. res = admin.create_client_authz_resource_based_permission(
  526. client_id=auth_client_id,
  527. payload={"name": "test-permission-rb", "resources": [test_resource_id]},
  528. )
  529. assert res, res
  530. assert res["name"] == "test-permission-rb"
  531. assert res["resources"] == [test_resource_id]
  532. with pytest.raises(KeycloakPostError) as err:
  533. admin.create_client_authz_resource_based_permission(
  534. client_id=auth_client_id,
  535. payload={"name": "test-permission-rb", "resources": [test_resource_id]},
  536. )
  537. assert err.match('409: b\'{"error":"Policy with name')
  538. assert admin.create_client_authz_resource_based_permission(
  539. client_id=auth_client_id,
  540. payload={"name": "test-permission-rb", "resources": [test_resource_id]},
  541. skip_exists=True,
  542. ) == {"msg": "Already exists"}
  543. assert len(admin.get_client_authz_permissions(client_id=auth_client_id)) == 2
  544. # Test authz scopes
  545. res = admin.get_client_authz_scopes(client_id=auth_client_id)
  546. assert len(res) == 0, res
  547. with pytest.raises(KeycloakGetError) as err:
  548. admin.get_client_authz_scopes(client_id=client_id)
  549. assert err.match('500: b\'{"error":"unknown_error"}\'')
  550. # Test service account user
  551. res = admin.get_client_service_account_user(client_id=auth_client_id)
  552. assert res["username"] == "service-account-authz-client", res
  553. with pytest.raises(KeycloakGetError) as err:
  554. admin.get_client_service_account_user(client_id=client_id)
  555. assert err.match('400: b\'{"error":"unknown_error"}\'')
  556. # Test delete client
  557. res = admin.delete_client(client_id=auth_client_id)
  558. assert res == dict(), res
  559. with pytest.raises(KeycloakDeleteError) as err:
  560. admin.delete_client(client_id=auth_client_id)
  561. assert err.match('404: b\'{"error":"Could not find client"}\'')
  562. def test_realm_roles(admin: KeycloakAdmin, realm: str):
  563. admin.realm_name = realm
  564. # Test get realm roles
  565. roles = admin.get_realm_roles()
  566. assert len(roles) == 3, roles
  567. role_names = [x["name"] for x in roles]
  568. assert "uma_authorization" in role_names, role_names
  569. assert "offline_access" in role_names, role_names
  570. # Test empty members
  571. with pytest.raises(KeycloakGetError) as err:
  572. admin.get_realm_role_members(role_name="does-not-exist")
  573. assert err.match('404: b\'{"error":"Could not find role"}\'')
  574. members = admin.get_realm_role_members(role_name="offline_access")
  575. assert members == list(), members
  576. # Test create realm role
  577. role_id = admin.create_realm_role(payload={"name": "test-realm-role"})
  578. assert role_id, role_id
  579. with pytest.raises(KeycloakPostError) as err:
  580. admin.create_realm_role(payload={"name": "test-realm-role"})
  581. assert err.match('409: b\'{"errorMessage":"Role with name test-realm-role already exists"}\'')
  582. role_id_2 = admin.create_realm_role(payload={"name": "test-realm-role"}, skip_exists=True)
  583. assert role_id == role_id_2
  584. # Test update realm role
  585. res = admin.update_realm_role(
  586. role_name="test-realm-role", payload={"name": "test-realm-role-update"}
  587. )
  588. assert res == dict(), res
  589. with pytest.raises(KeycloakPutError) as err:
  590. admin.update_realm_role(
  591. role_name="test-realm-role", payload={"name": "test-realm-role-update"}
  592. )
  593. assert err.match('404: b\'{"error":"Could not find role"}\''), err
  594. # Test realm role user assignment
  595. user_id = admin.create_user(payload={"username": "role-testing", "email": "test@test.test"})
  596. with pytest.raises(KeycloakPostError) as err:
  597. admin.assign_realm_roles(user_id=user_id, roles=["bad"])
  598. assert err.match('500: b\'{"error":"unknown_error"}\'')
  599. res = admin.assign_realm_roles(
  600. user_id=user_id,
  601. roles=[
  602. admin.get_realm_role(role_name="offline_access"),
  603. admin.get_realm_role(role_name="test-realm-role-update"),
  604. ],
  605. )
  606. assert res == dict(), res
  607. assert admin.get_user(user_id=user_id)["username"] in [
  608. x["username"] for x in admin.get_realm_role_members(role_name="offline_access")
  609. ]
  610. assert admin.get_user(user_id=user_id)["username"] in [
  611. x["username"] for x in admin.get_realm_role_members(role_name="test-realm-role-update")
  612. ]
  613. roles = admin.get_realm_roles_of_user(user_id=user_id)
  614. assert len(roles) == 3
  615. assert "offline_access" in [x["name"] for x in roles]
  616. assert "test-realm-role-update" in [x["name"] for x in roles]
  617. with pytest.raises(KeycloakDeleteError) as err:
  618. admin.delete_realm_roles_of_user(user_id=user_id, roles=["bad"])
  619. assert err.match('500: b\'{"error":"unknown_error"}\'')
  620. res = admin.delete_realm_roles_of_user(
  621. user_id=user_id, roles=[admin.get_realm_role(role_name="offline_access")]
  622. )
  623. assert res == dict(), res
  624. assert admin.get_realm_role_members(role_name="offline_access") == list()
  625. roles = admin.get_realm_roles_of_user(user_id=user_id)
  626. assert len(roles) == 2
  627. assert "offline_access" not in [x["name"] for x in roles]
  628. assert "test-realm-role-update" in [x["name"] for x in roles]
  629. roles = admin.get_available_realm_roles_of_user(user_id=user_id)
  630. assert len(roles) == 2
  631. assert "offline_access" in [x["name"] for x in roles]
  632. assert "uma_authorization" in [x["name"] for x in roles]
  633. # Test realm role group assignment
  634. group_id = admin.create_group(payload={"name": "test-group"})
  635. with pytest.raises(KeycloakPostError) as err:
  636. admin.assign_group_realm_roles(group_id=group_id, roles=["bad"])
  637. assert err.match('500: b\'{"error":"unknown_error"}\'')
  638. res = admin.assign_group_realm_roles(
  639. group_id=group_id,
  640. roles=[
  641. admin.get_realm_role(role_name="offline_access"),
  642. admin.get_realm_role(role_name="test-realm-role-update"),
  643. ],
  644. )
  645. assert res == dict(), res
  646. roles = admin.get_group_realm_roles(group_id=group_id)
  647. assert len(roles) == 2
  648. assert "offline_access" in [x["name"] for x in roles]
  649. assert "test-realm-role-update" in [x["name"] for x in roles]
  650. with pytest.raises(KeycloakDeleteError) as err:
  651. admin.delete_group_realm_roles(group_id=group_id, roles=["bad"])
  652. assert err.match('500: b\'{"error":"unknown_error"}\'')
  653. res = admin.delete_group_realm_roles(
  654. group_id=group_id, roles=[admin.get_realm_role(role_name="offline_access")]
  655. )
  656. assert res == dict(), res
  657. roles = admin.get_group_realm_roles(group_id=group_id)
  658. assert len(roles) == 1
  659. assert "test-realm-role-update" in [x["name"] for x in roles]
  660. # Test composite realm roles
  661. composite_role = admin.create_realm_role(payload={"name": "test-composite-role"})
  662. with pytest.raises(KeycloakPostError) as err:
  663. admin.add_composite_realm_roles_to_role(role_name=composite_role, roles=["bad"])
  664. assert err.match('500: b\'{"error":"unknown_error"}\'')
  665. res = admin.add_composite_realm_roles_to_role(
  666. role_name=composite_role, roles=[admin.get_realm_role(role_name="test-realm-role-update")]
  667. )
  668. assert res == dict(), res
  669. res = admin.get_composite_realm_roles_of_role(role_name=composite_role)
  670. assert len(res) == 1
  671. assert "test-realm-role-update" in res[0]["name"]
  672. with pytest.raises(KeycloakGetError) as err:
  673. admin.get_composite_realm_roles_of_role(role_name="bad")
  674. assert err.match('404: b\'{"error":"Could not find role"}\'')
  675. res = admin.get_composite_realm_roles_of_user(user_id=user_id)
  676. assert len(res) == 4
  677. assert "offline_access" in {x["name"] for x in res}
  678. assert "test-realm-role-update" in {x["name"] for x in res}
  679. assert "uma_authorization" in {x["name"] for x in res}
  680. with pytest.raises(KeycloakGetError) as err:
  681. admin.get_composite_realm_roles_of_user(user_id="bad")
  682. assert err.match('404: b\'{"error":"User not found"}\'')
  683. with pytest.raises(KeycloakDeleteError) as err:
  684. admin.remove_composite_realm_roles_to_role(role_name=composite_role, roles=["bad"])
  685. assert err.match('500: b\'{"error":"unknown_error"}\'')
  686. res = admin.remove_composite_realm_roles_to_role(
  687. role_name=composite_role, roles=[admin.get_realm_role(role_name="test-realm-role-update")]
  688. )
  689. assert res == dict(), res
  690. res = admin.get_composite_realm_roles_of_role(role_name=composite_role)
  691. assert len(res) == 0
  692. # Test delete realm role
  693. res = admin.delete_realm_role(role_name=composite_role)
  694. assert res == dict(), res
  695. with pytest.raises(KeycloakDeleteError) as err:
  696. admin.delete_realm_role(role_name=composite_role)
  697. assert err.match('404: b\'{"error":"Could not find role"}\'')
  698. def test_client_roles(admin: KeycloakAdmin, client: str):
  699. # Test get client roles
  700. res = admin.get_client_roles(client_id=client)
  701. assert len(res) == 0
  702. with pytest.raises(KeycloakGetError) as err:
  703. admin.get_client_roles(client_id="bad")
  704. assert err.match('404: b\'{"error":"Could not find client"}\'')
  705. # Test create client role
  706. client_role_id = admin.create_client_role(
  707. client_role_id=client, payload={"name": "client-role-test"}
  708. )
  709. with pytest.raises(KeycloakPostError) as err:
  710. admin.create_client_role(client_role_id=client, payload={"name": "client-role-test"})
  711. assert err.match('409: b\'{"errorMessage":"Role with name client-role-test already exists"}\'')
  712. client_role_id_2 = admin.create_client_role(
  713. client_role_id=client, payload={"name": "client-role-test"}, skip_exists=True
  714. )
  715. assert client_role_id == client_role_id_2
  716. # Test get client role
  717. res = admin.get_client_role(client_id=client, role_name="client-role-test")
  718. assert res["name"] == client_role_id
  719. with pytest.raises(KeycloakGetError) as err:
  720. admin.get_client_role(client_id=client, role_name="bad")
  721. assert err.match('404: b\'{"error":"Could not find role"}\'')
  722. res_ = admin.get_client_role_id(client_id=client, role_name="client-role-test")
  723. assert res_ == res["id"]
  724. with pytest.raises(KeycloakGetError) as err:
  725. admin.get_client_role_id(client_id=client, role_name="bad")
  726. assert err.match('404: b\'{"error":"Could not find role"}\'')
  727. assert len(admin.get_client_roles(client_id=client)) == 1
  728. # Test update client role
  729. res = admin.update_client_role(
  730. client_role_id=client,
  731. role_name="client-role-test",
  732. payload={"name": "client-role-test-update"},
  733. )
  734. assert res == dict()
  735. with pytest.raises(KeycloakPutError) as err:
  736. res = admin.update_client_role(
  737. client_role_id=client,
  738. role_name="client-role-test",
  739. payload={"name": "client-role-test-update"},
  740. )
  741. assert err.match('404: b\'{"error":"Could not find role"}\'')
  742. # Test user with client role
  743. res = admin.get_client_role_members(client_id=client, role_name="client-role-test-update")
  744. assert len(res) == 0
  745. with pytest.raises(KeycloakGetError) as err:
  746. admin.get_client_role_members(client_id=client, role_name="bad")
  747. assert err.match('404: b\'{"error":"Could not find role"}\'')
  748. user_id = admin.create_user(payload={"username": "test", "email": "test@test.test"})
  749. with pytest.raises(KeycloakPostError) as err:
  750. admin.assign_client_role(user_id=user_id, client_id=client, roles=["bad"])
  751. assert err.match('500: b\'{"error":"unknown_error"}\'')
  752. res = admin.assign_client_role(
  753. user_id=user_id,
  754. client_id=client,
  755. roles=[admin.get_client_role(client_id=client, role_name="client-role-test-update")],
  756. )
  757. assert res == dict()
  758. assert (
  759. len(admin.get_client_role_members(client_id=client, role_name="client-role-test-update"))
  760. == 1
  761. )
  762. roles = admin.get_client_roles_of_user(user_id=user_id, client_id=client)
  763. assert len(roles) == 1, roles
  764. with pytest.raises(KeycloakGetError) as err:
  765. admin.get_client_roles_of_user(user_id=user_id, client_id="bad")
  766. assert err.match('404: b\'{"error":"Client not found"}\'')
  767. roles = admin.get_composite_client_roles_of_user(user_id=user_id, client_id=client)
  768. assert len(roles) == 1, roles
  769. with pytest.raises(KeycloakGetError) as err:
  770. admin.get_composite_client_roles_of_user(user_id=user_id, client_id="bad")
  771. assert err.match('404: b\'{"error":"Client not found"}\'')
  772. roles = admin.get_available_client_roles_of_user(user_id=user_id, client_id=client)
  773. assert len(roles) == 0, roles
  774. with pytest.raises(KeycloakGetError) as err:
  775. admin.get_composite_client_roles_of_user(user_id=user_id, client_id="bad")
  776. assert err.match('404: b\'{"error":"Client not found"}\'')
  777. with pytest.raises(KeycloakDeleteError) as err:
  778. admin.delete_client_roles_of_user(user_id=user_id, client_id=client, roles=["bad"])
  779. assert err.match('500: b\'{"error":"unknown_error"}\'')
  780. admin.delete_client_roles_of_user(
  781. user_id=user_id,
  782. client_id=client,
  783. roles=[admin.get_client_role(client_id=client, role_name="client-role-test-update")],
  784. )
  785. assert len(admin.get_client_roles_of_user(user_id=user_id, client_id=client)) == 0
  786. # Test groups and client roles
  787. res = admin.get_client_role_groups(client_id=client, role_name="client-role-test-update")
  788. assert len(res) == 0
  789. with pytest.raises(KeycloakGetError) as err:
  790. admin.get_client_role_groups(client_id=client, role_name="bad")
  791. assert err.match('404: b\'{"error":"Could not find role"}\'')
  792. group_id = admin.create_group(payload={"name": "test-group"})
  793. res = admin.get_group_client_roles(group_id=group_id, client_id=client)
  794. assert len(res) == 0
  795. with pytest.raises(KeycloakGetError) as err:
  796. admin.get_group_client_roles(group_id=group_id, client_id="bad")
  797. assert err.match('404: b\'{"error":"Client not found"}\'')
  798. with pytest.raises(KeycloakPostError) as err:
  799. admin.assign_group_client_roles(group_id=group_id, client_id=client, roles=["bad"])
  800. assert err.match('500: b\'{"error":"unknown_error"}\'')
  801. res = admin.assign_group_client_roles(
  802. group_id=group_id,
  803. client_id=client,
  804. roles=[admin.get_client_role(client_id=client, role_name="client-role-test-update")],
  805. )
  806. assert res == dict()
  807. assert (
  808. len(admin.get_client_role_groups(client_id=client, role_name="client-role-test-update"))
  809. == 1
  810. )
  811. assert len(admin.get_group_client_roles(group_id=group_id, client_id=client)) == 1
  812. with pytest.raises(KeycloakDeleteError) as err:
  813. admin.delete_group_client_roles(group_id=group_id, client_id=client, roles=["bad"])
  814. assert err.match('500: b\'{"error":"unknown_error"}\'')
  815. res = admin.delete_group_client_roles(
  816. group_id=group_id,
  817. client_id=client,
  818. roles=[admin.get_client_role(client_id=client, role_name="client-role-test-update")],
  819. )
  820. assert res == dict()
  821. # Test composite client roles
  822. with pytest.raises(KeycloakPostError) as err:
  823. admin.add_composite_client_roles_to_role(
  824. client_role_id=client, role_name="client-role-test-update", roles=["bad"]
  825. )
  826. assert err.match('500: b\'{"error":"unknown_error"}\'')
  827. res = admin.add_composite_client_roles_to_role(
  828. client_role_id=client,
  829. role_name="client-role-test-update",
  830. roles=[admin.get_realm_role(role_name="offline_access")],
  831. )
  832. assert res == dict()
  833. assert admin.get_client_role(client_id=client, role_name="client-role-test-update")[
  834. "composite"
  835. ]
  836. # Test delete of client role
  837. res = admin.delete_client_role(client_role_id=client, role_name="client-role-test-update")
  838. assert res == dict()
  839. with pytest.raises(KeycloakDeleteError) as err:
  840. admin.delete_client_role(client_role_id=client, role_name="client-role-test-update")
  841. assert err.match('404: b\'{"error":"Could not find role"}\'')
  842. def test_email(admin: KeycloakAdmin, user: str):
  843. # Emails will fail as we don't have SMTP test setup
  844. with pytest.raises(KeycloakPutError) as err:
  845. admin.send_update_account(user_id=user, payload=dict())
  846. assert err.match('500: b\'{"error":"unknown_error"}\'')
  847. admin.update_user(user_id=user, payload={"enabled": True})
  848. with pytest.raises(KeycloakPutError) as err:
  849. admin.send_verify_email(user_id=user)
  850. assert err.match('500: b\'{"errorMessage":"Failed to send execute actions email"}\'')
  851. def test_get_sessions(admin: KeycloakAdmin):
  852. sessions = admin.get_sessions(user_id=admin.get_user_id(username=admin.username))
  853. assert len(sessions) >= 1
  854. with pytest.raises(KeycloakGetError) as err:
  855. admin.get_sessions(user_id="bad")
  856. assert err.match('404: b\'{"error":"User not found"}\'')
  857. def test_get_client_installation_provider(admin: KeycloakAdmin, client: str):
  858. with pytest.raises(KeycloakGetError) as err:
  859. admin.get_client_installation_provider(client_id=client, provider_id="bad")
  860. assert err.match('404: b\'{"error":"Unknown Provider"}\'')
  861. installation = admin.get_client_installation_provider(
  862. client_id=client, provider_id="keycloak-oidc-keycloak-json"
  863. )
  864. assert set(installation.keys()) == {
  865. "auth-server-url",
  866. "confidential-port",
  867. "credentials",
  868. "realm",
  869. "resource",
  870. "ssl-required",
  871. }
  872. def test_auth_flows(admin: KeycloakAdmin, realm: str):
  873. admin.realm_name = realm
  874. res = admin.get_authentication_flows()
  875. assert len(res) == 8, res
  876. assert set(res[0].keys()) == {
  877. "alias",
  878. "authenticationExecutions",
  879. "builtIn",
  880. "description",
  881. "id",
  882. "providerId",
  883. "topLevel",
  884. }
  885. assert {x["alias"] for x in res} == {
  886. "reset credentials",
  887. "browser",
  888. "http challenge",
  889. "registration",
  890. "docker auth",
  891. "direct grant",
  892. "first broker login",
  893. "clients",
  894. }
  895. with pytest.raises(KeycloakGetError) as err:
  896. admin.get_authentication_flow_for_id(flow_id="bad")
  897. assert err.match('404: b\'{"error":"Could not find flow with id"}\'')
  898. browser_flow_id = [x for x in res if x["alias"] == "browser"][0]["id"]
  899. res = admin.get_authentication_flow_for_id(flow_id=browser_flow_id)
  900. assert res["alias"] == "browser"
  901. # Test copying
  902. with pytest.raises(KeycloakPostError) as err:
  903. admin.copy_authentication_flow(payload=dict(), flow_alias="bad")
  904. assert err.match("404: b''")
  905. res = admin.copy_authentication_flow(payload={"newName": "test-browser"}, flow_alias="browser")
  906. assert res == b"", res
  907. assert len(admin.get_authentication_flows()) == 9
  908. # Test create
  909. res = admin.create_authentication_flow(
  910. payload={"alias": "test-create", "providerId": "basic-flow"}
  911. )
  912. assert res == b""
  913. with pytest.raises(KeycloakPostError) as err:
  914. admin.create_authentication_flow(payload={"alias": "test-create", "builtIn": False})
  915. assert err.match('409: b\'{"errorMessage":"Flow test-create already exists"}\'')
  916. assert admin.create_authentication_flow(
  917. payload={"alias": "test-create"}, skip_exists=True
  918. ) == {"msg": "Already exists"}
  919. # Test flow executions
  920. res = admin.get_authentication_flow_executions(flow_alias="browser")
  921. assert len(res) == 8, res
  922. with pytest.raises(KeycloakGetError) as err:
  923. admin.get_authentication_flow_executions(flow_alias="bad")
  924. assert err.match("404: b''")
  925. exec_id = res[0]["id"]
  926. res = admin.get_authentication_flow_execution(execution_id=exec_id)
  927. assert set(res.keys()) == {
  928. "alternative",
  929. "authenticator",
  930. "authenticatorFlow",
  931. "conditional",
  932. "disabled",
  933. "enabled",
  934. "id",
  935. "parentFlow",
  936. "priority",
  937. "required",
  938. "requirement",
  939. }, res
  940. with pytest.raises(KeycloakGetError) as err:
  941. admin.get_authentication_flow_execution(execution_id="bad")
  942. assert err.match('404: b\'{"error":"Illegal execution"}\'')
  943. with pytest.raises(KeycloakPostError) as err:
  944. admin.create_authentication_flow_execution(payload=dict(), flow_alias="browser")
  945. assert err.match('400: b\'{"error":"It is illegal to add execution to a built in flow"}\'')
  946. res = admin.create_authentication_flow_execution(
  947. payload={"provider": "auth-cookie"}, flow_alias="test-create"
  948. )
  949. assert res == b""
  950. assert len(admin.get_authentication_flow_executions(flow_alias="test-create")) == 1
  951. with pytest.raises(KeycloakPutError) as err:
  952. admin.update_authentication_flow_executions(
  953. payload={"required": "yes"}, flow_alias="test-create"
  954. )
  955. assert err.match('400: b\'{"error":"Unrecognized field')
  956. payload = admin.get_authentication_flow_executions(flow_alias="test-create")[0]
  957. payload["displayName"] = "test"
  958. res = admin.update_authentication_flow_executions(payload=payload, flow_alias="test-create")
  959. assert res
  960. exec_id = admin.get_authentication_flow_executions(flow_alias="test-create")[0]["id"]
  961. res = admin.delete_authentication_flow_execution(execution_id=exec_id)
  962. assert res == dict()
  963. with pytest.raises(KeycloakDeleteError) as err:
  964. admin.delete_authentication_flow_execution(execution_id=exec_id)
  965. assert err.match('404: b\'{"error":"Illegal execution"}\'')
  966. # Test subflows
  967. res = admin.create_authentication_flow_subflow(
  968. payload={
  969. "alias": "test-subflow",
  970. "provider": "basic-flow",
  971. "type": "something",
  972. "description": "something",
  973. },
  974. flow_alias="test-browser",
  975. )
  976. assert res == b""
  977. with pytest.raises(KeycloakPostError) as err:
  978. admin.create_authentication_flow_subflow(
  979. payload={"alias": "test-subflow", "providerId": "basic-flow"},
  980. flow_alias="test-browser",
  981. )
  982. assert err.match('409: b\'{"errorMessage":"New flow alias name already exists"}\'')
  983. res = admin.create_authentication_flow_subflow(
  984. payload={
  985. "alias": "test-subflow",
  986. "provider": "basic-flow",
  987. "type": "something",
  988. "description": "something",
  989. },
  990. flow_alias="test-create",
  991. skip_exists=True,
  992. )
  993. assert res == {"msg": "Already exists"}
  994. # Test delete auth flow
  995. flow_id = [x for x in admin.get_authentication_flows() if x["alias"] == "test-browser"][0][
  996. "id"
  997. ]
  998. res = admin.delete_authentication_flow(flow_id=flow_id)
  999. assert res == dict()
  1000. with pytest.raises(KeycloakDeleteError) as err:
  1001. admin.delete_authentication_flow(flow_id=flow_id)
  1002. assert err.match('404: b\'{"error":"Could not find flow with id"}\'')