Description
Before reporting an issue
- I have read and understood the above terms for submitting issues, and I understand that my issue may be closed without action if I do not follow them.
Area
core
Describe the bug
org/keycloak/representations/idm/RealmEventsConfigRepresentation.java
is missing a field for the expiration time for the admin events:
public class RealmEventsConfigRepresentation {
protected boolean eventsEnabled;
protected Long eventsExpiration;
protected List<String> eventsListeners;
protected List<String> enabledEventTypes;
protected Boolean adminEventsEnabled;
protected Boolean adminEventsDetailsEnabled;
// missing the expiration time of admin events here
// other methods
}
Effect:
That way it is not possible to update the expiration time of the admin events via the keycloak services method in org/keycloak/services/resources/admin/RealmAdminResource.java
:
@PUT
@Path("events/config")
@Consumes(MediaType.APPLICATION_JSON)
@Tag(name = KeycloakOpenAPI.Admin.Tags.REALMS_ADMIN)
@Operation( description = "Update the events provider Change the events provider and/or its configuration")
@APIResponses(value = {
@APIResponse(responseCode = "204", description = "No Content"),
@APIResponse(responseCode = "403", description = "Forbidden")
})
public void updateRealmEventsConfig(final RealmEventsConfigRepresentation rep) {
auth.realm().requireManageEvents();
logger.debugf("updating realm events config: %s", realm.getName());
new RealmManager(session).updateRealmEventsConfig(rep, realm);
adminEvent.operation(OperationType.UPDATE).resource(ResourceType.REALM)
.resourcePath(session.getContext().getUri()).representation(rep)
// refresh the builder to consider old and new config
.refreshRealmEventsConfig(session)
.success();
}
Now it seems to me that one of these calls should suffice for the purpose of persisting the new event settings. The two of them could lead to unwanted behaviour at this moment, depending on which call is executed first, as the second documented call updating the config directly via the serialised RealmEventsConfigRepresentation, misses the admin event expiration time.
Version
26.2.5
Regression
- The issue is a regression
Expected behavior
- The representation RealmEventsConfigRepresentation should include the setting for admin events expiration.
- Ideally, one call is fired to update the realm event settings and not two. seems the direct call to the config endpoint is more precise.
- The placement of the fields is currently quite inconsistent, as
eventsExpiration
is located in the root of the realm representation, whileadminEventsExpiration
is nested in theattributes
map of the realm representation. (Maybe this has a reason, which is not that apparent at first sight?)
Actual behavior
- Two consecutive PUT calls are being triggered, one to {HOST}/admin/realms/example and another to {HSOT}/admin/realms/example/events/config.
- the direct call on the realm includes a full realm representation including all event settings and the desired admin events expiration setting
- the second call updates the config settings a second time, bu directly putting updated RealmEventsConfigRepresentation to the server, unfortunately missing a field for the admin event expiration settings.
How to Reproduce?
More details:
When using the admin UI to configure the admin and user events at URL {HOST}/admin/master/console/#/example/realm-settings/events
an update to the settings of either user events or admin events and subsequently clicking save, will trigger two consecutive PUT calls, one to
Request URL {HOST}/admin/realms/example
Request Method PUT
Status Code 204 No Content
Payload:
{
"id": "example",
"realm": "example",
"displayName": "Example Product Realm",
"notBefore": 0,
"defaultSignatureAlgorithm": "RS256",
"revokeRefreshToken": false,
"refreshTokenMaxReuse": 0,
"accessTokenLifespan": 300,
"accessTokenLifespanForImplicitFlow": 900,
"ssoSessionIdleTimeout": 1800,
"ssoSessionMaxLifespan": 36000,
"ssoSessionIdleTimeoutRememberMe": 0,
"ssoSessionMaxLifespanRememberMe": 0,
"offlineSessionIdleTimeout": 2592000,
"offlineSessionMaxLifespanEnabled": false,
"offlineSessionMaxLifespan": 5184000,
"clientSessionIdleTimeout": 0,
"clientSessionMaxLifespan": 0,
"clientOfflineSessionIdleTimeout": 0,
"clientOfflineSessionMaxLifespan": 0,
"accessCodeLifespan": 60,
"accessCodeLifespanUserAction": 300,
"accessCodeLifespanLogin": 1800,
"actionTokenGeneratedByAdminLifespan": 43200,
"actionTokenGeneratedByUserLifespan": 300,
"oauth2DeviceCodeLifespan": 600,
"oauth2DevicePollingInterval": 5,
"enabled": true,
"sslRequired": "external",
"registrationAllowed": false,
"registrationEmailAsUsername": false,
"rememberMe": false,
"verifyEmail": false,
"loginWithEmailAllowed": true,
"duplicateEmailsAllowed": false,
"resetPasswordAllowed": false,
"editUsernameAllowed": false,
"bruteForceProtected": true,
"permanentLockout": false,
"maxTemporaryLockouts": 0,
"bruteForceStrategy": "MULTIPLE",
"maxFailureWaitSeconds": 900,
"minimumQuickLoginWaitSeconds": 60,
"waitIncrementSeconds": 60,
"quickLoginCheckMilliSeconds": 1000,
"maxDeltaTimeSeconds": 43200,
"failureFactor": 30,
"defaultRole": {
"id": "56119c93-934e-4ae3-b4bb-1f2b3551ae41",
"name": "default-roles-example",
"description": "${role_default-roles}",
"composite": true,
"clientRole": false,
"containerId": "example"
},
"requiredCredentials": [
"password"
],
"otpPolicyType": "totp",
"otpPolicyAlgorithm": "HmacSHA1",
"otpPolicyInitialCounter": 0,
"otpPolicyDigits": 6,
"otpPolicyLookAheadWindow": 1,
"otpPolicyPeriod": 30,
"otpPolicyCodeReusable": false,
"otpSupportedApplications": [
"totpAppFreeOTPName",
"totpAppGoogleName",
"totpAppMicrosoftAuthenticatorName"
],
"webAuthnPolicyRpEntityName": "keycloak",
"webAuthnPolicySignatureAlgorithms": [
"ES256",
"RS256"
],
"webAuthnPolicyRpId": "",
"webAuthnPolicyAttestationConveyancePreference": "not specified",
"webAuthnPolicyAuthenticatorAttachment": "not specified",
"webAuthnPolicyRequireResidentKey": "not specified",
"webAuthnPolicyUserVerificationRequirement": "not specified",
"webAuthnPolicyCreateTimeout": 0,
"webAuthnPolicyAvoidSameAuthenticatorRegister": false,
"webAuthnPolicyAcceptableAaguids": [],
"webAuthnPolicyExtraOrigins": [],
"webAuthnPolicyPasswordlessRpEntityName": "keycloak",
"webAuthnPolicyPasswordlessSignatureAlgorithms": [
"ES256",
"RS256"
],
"webAuthnPolicyPasswordlessRpId": "",
"webAuthnPolicyPasswordlessAttestationConveyancePreference": "not specified",
"webAuthnPolicyPasswordlessAuthenticatorAttachment": "not specified",
"webAuthnPolicyPasswordlessRequireResidentKey": "not specified",
"webAuthnPolicyPasswordlessUserVerificationRequirement": "not specified",
"webAuthnPolicyPasswordlessCreateTimeout": 0,
"webAuthnPolicyPasswordlessAvoidSameAuthenticatorRegister": false,
"webAuthnPolicyPasswordlessAcceptableAaguids": [],
"webAuthnPolicyPasswordlessExtraOrigins": [],
"browserSecurityHeaders": {
"contentSecurityPolicyReportOnly": "",
"xContentTypeOptions": "nosniff",
"referrerPolicy": "no-referrer",
"xRobotsTag": "none",
"xFrameOptions": "SAMEORIGIN",
"contentSecurityPolicy": "frame-src 'self'; frame-ancestors 'self'; object-src 'none';",
"strictTransportSecurity": "max-age=31536000; includeSubDomains"
},
"smtpServer": {},
"eventsEnabled": true,
"eventsExpiration": 2592000,
"eventsListeners": [
"jboss-logging"
],
"enabledEventTypes": [
"SEND_RESET_PASSWORD",
"UPDATE_CONSENT_ERROR",
"GRANT_CONSENT",
"VERIFY_PROFILE_ERROR",
"REMOVE_TOTP",
"REVOKE_GRANT",
"UPDATE_TOTP",
"LOGIN_ERROR",
"CLIENT_LOGIN",
"RESET_PASSWORD_ERROR",
"UPDATE_CREDENTIAL",
"IMPERSONATE_ERROR",
"CODE_TO_TOKEN_ERROR",
"CUSTOM_REQUIRED_ACTION",
"OAUTH2_DEVICE_CODE_TO_TOKEN_ERROR",
"RESTART_AUTHENTICATION",
"IMPERSONATE",
"UPDATE_PROFILE_ERROR",
"LOGIN",
"OAUTH2_DEVICE_VERIFY_USER_CODE",
"UPDATE_PASSWORD_ERROR",
"CLIENT_INITIATED_ACCOUNT_LINKING",
"OAUTH2_EXTENSION_GRANT",
"USER_DISABLED_BY_PERMANENT_LOCKOUT",
"REMOVE_CREDENTIAL_ERROR",
"TOKEN_EXCHANGE",
"AUTHREQID_TO_TOKEN",
"LOGOUT",
"REGISTER",
"DELETE_ACCOUNT_ERROR",
"CLIENT_REGISTER",
"IDENTITY_PROVIDER_LINK_ACCOUNT",
"USER_DISABLED_BY_TEMPORARY_LOCKOUT",
"DELETE_ACCOUNT",
"UPDATE_PASSWORD",
"CLIENT_DELETE",
"FEDERATED_IDENTITY_LINK_ERROR",
"IDENTITY_PROVIDER_FIRST_LOGIN",
"CLIENT_DELETE_ERROR",
"VERIFY_EMAIL",
"CLIENT_LOGIN_ERROR",
"RESTART_AUTHENTICATION_ERROR",
"EXECUTE_ACTIONS",
"REMOVE_FEDERATED_IDENTITY_ERROR",
"TOKEN_EXCHANGE_ERROR",
"PERMISSION_TOKEN",
"FEDERATED_IDENTITY_OVERRIDE_LINK",
"SEND_IDENTITY_PROVIDER_LINK_ERROR",
"UPDATE_CREDENTIAL_ERROR",
"EXECUTE_ACTION_TOKEN_ERROR",
"OAUTH2_EXTENSION_GRANT_ERROR",
"SEND_VERIFY_EMAIL",
"OAUTH2_DEVICE_AUTH",
"EXECUTE_ACTIONS_ERROR",
"REMOVE_FEDERATED_IDENTITY",
"OAUTH2_DEVICE_CODE_TO_TOKEN",
"IDENTITY_PROVIDER_POST_LOGIN",
"IDENTITY_PROVIDER_LINK_ACCOUNT_ERROR",
"FEDERATED_IDENTITY_OVERRIDE_LINK_ERROR",
"OAUTH2_DEVICE_VERIFY_USER_CODE_ERROR",
"UPDATE_EMAIL",
"REGISTER_ERROR",
"REVOKE_GRANT_ERROR",
"EXECUTE_ACTION_TOKEN",
"LOGOUT_ERROR",
"UPDATE_EMAIL_ERROR",
"CLIENT_UPDATE_ERROR",
"AUTHREQID_TO_TOKEN_ERROR",
"INVITE_ORG_ERROR",
"UPDATE_PROFILE",
"CLIENT_REGISTER_ERROR",
"FEDERATED_IDENTITY_LINK",
"INVITE_ORG",
"SEND_IDENTITY_PROVIDER_LINK",
"SEND_VERIFY_EMAIL_ERROR",
"RESET_PASSWORD",
"CLIENT_INITIATED_ACCOUNT_LINKING_ERROR",
"OAUTH2_DEVICE_AUTH_ERROR",
"REMOVE_CREDENTIAL",
"UPDATE_CONSENT",
"REMOVE_TOTP_ERROR",
"VERIFY_EMAIL_ERROR",
"SEND_RESET_PASSWORD_ERROR",
"CLIENT_UPDATE",
"CUSTOM_REQUIRED_ACTION_ERROR",
"IDENTITY_PROVIDER_POST_LOGIN_ERROR",
"UPDATE_TOTP_ERROR",
"CODE_TO_TOKEN",
"VERIFY_PROFILE",
"GRANT_CONSENT_ERROR",
"IDENTITY_PROVIDER_FIRST_LOGIN_ERROR"
],
"adminEventsEnabled": true,
"adminEventsDetailsEnabled": true,
"internationalizationEnabled": false,
"supportedLocales": [],
"browserFlow": "browser",
"registrationFlow": "registration",
"directGrantFlow": "direct grant",
"resetCredentialsFlow": "reset credentials",
"clientAuthenticationFlow": "clients",
"dockerAuthenticationFlow": "docker auth",
"firstBrokerLoginFlow": "first broker login",
"attributes": {
"cibaBackchannelTokenDeliveryMode": "poll",
"cibaAuthRequestedUserHint": "login_hint",
"oauth2DevicePollingInterval": "5",
"clientOfflineSessionMaxLifespan": "0",
"clientSessionIdleTimeout": "0",
"clientOfflineSessionIdleTimeout": "0",
"cibaInterval": "5",
"realmReusableOtpCode": "false",
"cibaExpiresIn": "120",
"oauth2DeviceCodeLifespan": "600",
"parRequestUriLifespan": "60",
"clientSessionMaxLifespan": "0",
"adminEventsExpiration": 2592000
},
"userManagedAccessAllowed": false,
"organizationsEnabled": true,
"verifiableCredentialsEnabled": false,
"adminPermissionsEnabled": false,
"clientProfiles": {
"profiles": []
},
"clientPolicies": {
"policies": []
}
}
and a second one to
Request URL {HSOT}/admin/realms/example/events/config
Request Method PUT
Status Code 204 No Content
Payload:
{
"eventsEnabled": true,
"adminEventsEnabled": true,
"adminEventsDetailsEnabled": true,
"eventsExpiration": 2505600,
"eventsListeners": [
"jboss-logging"
],
"enabledEventTypes": [
"SEND_RESET_PASSWORD",
"UPDATE_CONSENT_ERROR",
"GRANT_CONSENT",
"VERIFY_PROFILE_ERROR",
"REMOVE_TOTP",
"REVOKE_GRANT",
"UPDATE_TOTP",
"LOGIN_ERROR",
"CLIENT_LOGIN",
"RESET_PASSWORD_ERROR",
"UPDATE_CREDENTIAL",
"IMPERSONATE_ERROR",
"CODE_TO_TOKEN_ERROR",
"CUSTOM_REQUIRED_ACTION",
"OAUTH2_DEVICE_CODE_TO_TOKEN_ERROR",
"RESTART_AUTHENTICATION",
"IMPERSONATE",
"UPDATE_PROFILE_ERROR",
"LOGIN",
"OAUTH2_DEVICE_VERIFY_USER_CODE",
"UPDATE_PASSWORD_ERROR",
"CLIENT_INITIATED_ACCOUNT_LINKING",
"OAUTH2_EXTENSION_GRANT",
"USER_DISABLED_BY_PERMANENT_LOCKOUT",
"REMOVE_CREDENTIAL_ERROR",
"TOKEN_EXCHANGE",
"AUTHREQID_TO_TOKEN",
"LOGOUT",
"REGISTER",
"DELETE_ACCOUNT_ERROR",
"CLIENT_REGISTER",
"IDENTITY_PROVIDER_LINK_ACCOUNT",
"USER_DISABLED_BY_TEMPORARY_LOCKOUT",
"DELETE_ACCOUNT",
"UPDATE_PASSWORD",
"CLIENT_DELETE",
"FEDERATED_IDENTITY_LINK_ERROR",
"IDENTITY_PROVIDER_FIRST_LOGIN",
"CLIENT_DELETE_ERROR",
"VERIFY_EMAIL",
"CLIENT_LOGIN_ERROR",
"RESTART_AUTHENTICATION_ERROR",
"EXECUTE_ACTIONS",
"REMOVE_FEDERATED_IDENTITY_ERROR",
"TOKEN_EXCHANGE_ERROR",
"PERMISSION_TOKEN",
"FEDERATED_IDENTITY_OVERRIDE_LINK",
"SEND_IDENTITY_PROVIDER_LINK_ERROR",
"UPDATE_CREDENTIAL_ERROR",
"EXECUTE_ACTION_TOKEN_ERROR",
"OAUTH2_EXTENSION_GRANT_ERROR",
"SEND_VERIFY_EMAIL",
"OAUTH2_DEVICE_AUTH",
"EXECUTE_ACTIONS_ERROR",
"REMOVE_FEDERATED_IDENTITY",
"OAUTH2_DEVICE_CODE_TO_TOKEN",
"IDENTITY_PROVIDER_POST_LOGIN",
"IDENTITY_PROVIDER_LINK_ACCOUNT_ERROR",
"FEDERATED_IDENTITY_OVERRIDE_LINK_ERROR",
"OAUTH2_DEVICE_VERIFY_USER_CODE_ERROR",
"UPDATE_EMAIL",
"REGISTER_ERROR",
"REVOKE_GRANT_ERROR",
"EXECUTE_ACTION_TOKEN",
"LOGOUT_ERROR",
"UPDATE_EMAIL_ERROR",
"CLIENT_UPDATE_ERROR",
"AUTHREQID_TO_TOKEN_ERROR",
"INVITE_ORG_ERROR",
"UPDATE_PROFILE",
"CLIENT_REGISTER_ERROR",
"FEDERATED_IDENTITY_LINK",
"INVITE_ORG",
"SEND_IDENTITY_PROVIDER_LINK",
"SEND_VERIFY_EMAIL_ERROR",
"RESET_PASSWORD",
"CLIENT_INITIATED_ACCOUNT_LINKING_ERROR",
"OAUTH2_DEVICE_AUTH_ERROR",
"REMOVE_CREDENTIAL",
"UPDATE_CONSENT",
"REMOVE_TOTP_ERROR",
"VERIFY_EMAIL_ERROR",
"SEND_RESET_PASSWORD_ERROR",
"CLIENT_UPDATE",
"CUSTOM_REQUIRED_ACTION_ERROR",
"IDENTITY_PROVIDER_POST_LOGIN_ERROR",
"UPDATE_TOTP_ERROR",
"CODE_TO_TOKEN",
"VERIFY_PROFILE",
"GRANT_CONSENT_ERROR",
"IDENTITY_PROVIDER_FIRST_LOGIN_ERROR"
]
}
Anything else?
It affects core and services