Hello,
Im trying to implement a Required Action where a user has to accept their pending notifications and their timestamp gets recorded (like how the terms and conditions Required Action works). On the backend it looks like its working fine but I wanted the timestamps to be available to see/edit in the admin page. I read that I could use the REST API to modify the user profile but is this really the best/only way ? Also, is it safe to use the API in an SPI ?
Keycloak version: 26.1.3
Thank you !
Found about about the User Profile API. Managed to do what I wanted.
If anyone needs help doing something similar.
https://www.keycloak.org/docs-api/26.1.0/javadocs/org/keycloak/representations/userprofile/config/UPConfig.htmlhttps://www.keycloak.org/docs-api/26.1.0/javadocs/org/keycloak/representations/userprofile/config/UPAttribute.html
@Override
public void processAction(RequiredActionContext context) {
// User acknowledged the notifications, update timestamp attributes
String notificationsJson = context.getAuthenticationSession().getAuthNote(NOTIFICATION_LIST_AUTH_NOTE);
DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("dd-MM-yyyy HH:mm").withZone(ZoneId.systemDefault());
UPAttributePermissions permissions = new UPAttributePermissions();
// Only admins can edit but anyone authenticated can see.
permissions.setEdit(Set.of(AdminRoles.ADMIN));
permissions.setView(Set.of("user"));
UserModel user = context.getUser();
UserProfileProvider provider = context.getSession().getProvider(UserProfileProvider.class);
UPConfig config = provider.getConfiguration();
if (notificationsJson != null) {
try {
ObjectMapper objectMapper = new ObjectMapper();
@SuppressWarnings("unchecked")
List<Map<String, String>> notificationsList = objectMapper.readValue(notificationsJson, List.class);
String currentDateTime = LocalDateTime.now().format(dateFormatter);
for (Map<String, String> notification : notificationsList) {
String notificationName = notification.get("name");
String attributeKey = USER_ATTRIBUTE_PREFIX + notificationName;
// Store the timestamp for the notification in the user's attributes
UPAttribute userProfileAttribute = new UPAttribute();
userProfileAttribute.setGroup(NOTIFICATION_USER_PROFILE_ATTRIBUTE_GROUP);
userProfileAttribute.setName(attributeKey);
userProfileAttribute.setPermissions(permissions);
// MAKE SURE YOU HAVE GOOD NOTIFICATION NAMES IN THE JSON FILE -> Format should be TestNotificationName to have a proper display name
String displayName = notificationName.replaceAll("([a-z])([A-Z])", "$1 $2")+ " Acceptance Date";
userProfileAttribute.setDisplayName(displayName);
config.addOrReplaceAttribute(userProfileAttribute);
user.setAttribute(attributeKey, Arrays.asList(currentDateTime));
}
} catch (Exception e) {
e.printStackTrace();
}
}
provider.setConfiguration(config);
context.success();
}