From f14f4805d61cd987e9f63a2d11a35b9d4d76ce37 Mon Sep 17 00:00:00 2001 From: Stan Silvert Date: Tue, 14 May 2024 08:49:47 -0400 Subject: [PATCH] Fix access for IDP links tab. (#29428) * Fix access for IDP links tab. Signed-off-by: Stan Silvert * Fix tests. Signed-off-by: Stan Silvert --------- Signed-off-by: Stan Silvert --- .../tabs/IdentityProviderLinksTab.ts | 2 +- .../admin/messages/messages_en.properties | 4 +- js/apps/admin-ui/src/user/EditUser.tsx | 20 +- .../src/user/UserIdentityProviderLinks.tsx | 183 ++++++++++-------- 4 files changed, 116 insertions(+), 93 deletions(-) diff --git a/js/apps/admin-ui/cypress/support/pages/admin-ui/manage/users/user_details/tabs/IdentityProviderLinksTab.ts b/js/apps/admin-ui/cypress/support/pages/admin-ui/manage/users/user_details/tabs/IdentityProviderLinksTab.ts index 78981895a5..570abb14e7 100644 --- a/js/apps/admin-ui/cypress/support/pages/admin-ui/manage/users/user_details/tabs/IdentityProviderLinksTab.ts +++ b/js/apps/admin-ui/cypress/support/pages/admin-ui/manage/users/user_details/tabs/IdentityProviderLinksTab.ts @@ -60,7 +60,7 @@ export default class IdentityProviderLinksTab { public assertNoIdentityProvidersLinkedMessageExist(exist: boolean) { cy.get(this.#linkedProvidersSection).should( (exist ? "" : "not.") + "contain.text", - "No identity providers linked. Choose one from the list below.", + "No identity providers linked.", ); return this; diff --git a/js/apps/admin-ui/maven-resources/theme/keycloak.v2/admin/messages/messages_en.properties b/js/apps/admin-ui/maven-resources/theme/keycloak.v2/admin/messages/messages_en.properties index ef6729447f..036b73fe45 100644 --- a/js/apps/admin-ui/maven-resources/theme/keycloak.v2/admin/messages/messages_en.properties +++ b/js/apps/admin-ui/maven-resources/theme/keycloak.v2/admin/messages/messages_en.properties @@ -2105,7 +2105,7 @@ duplicateEmailsHelpText=Allow multiple users to have the same email address. Cha importOverwritten_zero=No records overwritten. usermodel.realmRoleMapping.rolePrefix.label=Realm Role prefix eventTypes.GRANT_CONSENT.name=Grant consent -noProvidersLinked=No identity providers linked. Choose one from the list below. +noProvidersLinked=No identity providers linked. testConnectionSuccess=Success\! SMTP connection successful. E-mail was sent\! samlSettings=SAML settings userFedDisableConfirm=If you disable this user federation provider, it will not be considered for queries and imported users will be disabled and read-only until the provider is enabled again. @@ -2852,7 +2852,7 @@ syncModeOverrideHelp=Overrides the default sync mode of the IDP for this mapper. eventTypes.TOKEN_EXCHANGE_ERROR.description=Token exchange error strictTransportSecurityHelp=The Strict-Transport-Security HTTP header tells browsers to always use HTTPS. Once a browser sees this header, it will only visit the site over HTTPS for the time specified (1 year) at max-age, including the subdomains. <1>Learn more authenticationExplain=Authentication is the area where you can configure and manage different credential types. -passwordPoliciesHelp.hashIterations=The number of times a password is hashed before storage or verification. Default\: -1 in case argon2 is used as the hashing algorithm; 210,000 in case pbkdf2-sha512 is used as the hashing algorithm; 600,000 if the pbkdf2-sha256 algorithm is used as the hashing algorithm; 1,300,000 if the pbkdf2 algorithm is used as the hashing algorithm. +passwordPoliciesHelp.hashIterations=The number of times a password is hashed before storage or verification. Default\: -1 in case argon2 is used as the hashing algorithm; 210,000 in case pbkdf2-sha512 is used as the hashing algorithm; 600,000 if the pbkdf2-sha256 algorithm is used as the hashing algorithm; 1,300,000 if the pbkdf2 algorithm is used as the hashing algorithm. dropNonexistingGroupsDuringSync=Drop non-existing groups during sync clientAssertionSigningAlgHelp=Signature algorithm to create JWT assertion as client authentication. In the case of JWT signed with private key or JWT signed with client secret, it is required. If no algorithm is specified, the following algorithm is adapted. RS256 is adapted in the case of JWT signed with private key. HS256 is adapted in the case of JWT signed with client secret. jwtX509HeadersEnabledHelp=If enabled, the x5t (X.509 Certificate SHA-1 Thumbprint) header will be added to the JWT to reference the certificate used to sign it. Otherwise, the kid (Key ID) header will be used instead. diff --git a/js/apps/admin-ui/src/user/EditUser.tsx b/js/apps/admin-ui/src/user/EditUser.tsx index 87dddee3a5..4963436a14 100644 --- a/js/apps/admin-ui/src/user/EditUser.tsx +++ b/js/apps/admin-ui/src/user/EditUser.tsx @@ -368,17 +368,15 @@ export default function EditUser() { > - {hasAccess("view-identity-providers") && ( - {t("identityProviderLinks")} - } - {...identityProviderLinksTab} - > - - - )} + {t("identityProviderLinks")} + } + {...identityProviderLinksTab} + > + + {t("sessions")}} diff --git a/js/apps/admin-ui/src/user/UserIdentityProviderLinks.tsx b/js/apps/admin-ui/src/user/UserIdentityProviderLinks.tsx index 2c599d8061..772fd186ae 100644 --- a/js/apps/admin-ui/src/user/UserIdentityProviderLinks.tsx +++ b/js/apps/admin-ui/src/user/UserIdentityProviderLinks.tsx @@ -24,6 +24,7 @@ import { useServerInfo } from "../context/server-info/ServerInfoProvider"; import { toIdentityProvider } from "../identity-providers/routes/IdentityProvider"; import { emptyFormatter, upperCaseFormatter } from "../util"; import { UserIdpModal } from "./UserIdPModal"; +import { useAccess } from "../context/access/Access"; type UserIdentityProviderLinksProps = { userId: string; @@ -41,6 +42,12 @@ export const UserIdentityProviderLinks = ({ const { realm } = useRealm(); const { addAlert, addError } = useAlerts(); const { t } = useTranslation(); + const { hasAccess, hasSomeAccess } = useAccess(); + + const canQueryIDPDetails = hasSomeAccess( + "manage-identity-providers", + "view-identity-providers", + ); const refresh = () => setKey(new Date().getTime()); @@ -51,15 +58,17 @@ export const UserIdentityProviderLinks = ({ const identityProviders = useServerInfo().identityProviders; const getFederatedIdentities = async () => { - const allProviders = await adminClient.identityProviders.find(); - const allFedIds = (await adminClient.users.listFederatedIdentities({ id: userId, })) as WithProviderId[]; - for (const element of allFedIds) { - element.providerId = allProviders.find( - (item) => item.alias === element.identityProvider, - )?.providerId!; + + if (canQueryIDPDetails) { + const allProviders = await adminClient.identityProviders.find(); + for (const element of allFedIds) { + element.providerId = allProviders.find( + (item) => item.alias === element.identityProvider, + )?.providerId!; + } } return allFedIds; @@ -107,6 +116,9 @@ export const UserIdentityProviderLinks = ({ }); const idpLinkRenderer = (idp: WithProviderId) => { + if (!canQueryIDPDetails) + return {capitalize(idp.identityProvider)}; + return ( { + if (!hasAccess("manage-users")) return ; + return (