Судя по тому, что вы сказали, у вас есть три варианта.
Один - сохранить страницу Keycloak «Редактировать учетную запись» и использовать прослушиватель профиля обновления , чтобы проверить, какие атрибуты сохраняются или какие обновляются кем, что-то вроде этого:
public class UpdateProfile implements RequiredActionProvider, RequiredActionFactory, DisplayTypeRequiredActionFactory {
@Override
public InitiatedActionSupport initiatedActionSupport() {
return InitiatedActionSupport.SUPPORTED;
}
@Override
public void evaluateTriggers(RequiredActionContext context) {
}
@Override
public void requiredActionChallenge(RequiredActionContext context) {
Response challenge = context.form()
.createResponse(UserModel.RequiredAction.UPDATE_PROFILE);
context.challenge(challenge);
}
// Check the custom attribute 1 not being modified by the user
@Override
public void processAction(RequiredActionContext context) {
EventBuilder event = context.getEvent();
event.event(EventType.UPDATE_PROFILE);
MultivaluedMap<String, String> formData = context.getHttpRequest().getDecodedFormParameters();
UserModel user = context.getUser();
KeycloakSession session = context.getSession();
RealmModel realm = context.getRealm();
String newYourCustomAttribute1 = formData.getFirst("yourCustomAttribute1");
String oldYourCustomAttribute1 = user.getFirstAttribute("yourCustomAttribute1")
if (!newYourCustomAttribute1.equals(oldYourCustomAttribute1)) {
Response challenge = context.form()
.setError("User cannot change the attribute")
.setFormData(formData)
.createResponse(UserModel.RequiredAction.UPDATE_PROFILE);
context.challenge(challenge);
return;
}
context.success();
}
@Override
public void close() {
}
@Override
public RequiredActionProvider create(KeycloakSession session) {
return this;
}
@Override
public RequiredActionProvider createDisplay(KeycloakSession session, String displayType) {
if (displayType == null) return this;
if (!OAuth2Constants.DISPLAY_CONSOLE.equalsIgnoreCase(displayType)) return null;
return ConsoleUpdateProfile.SINGLETON;
}
@Override
public void init(Config.Scope config) {
}
@Override
public void postInit(KeycloakSessionFactory factory) {
}
@Override
public String getDisplayText() {
return "Update Profile";
}
@Override
public String getId() {
return UserModel.RequiredAction.UPDATE_PROFILE.name();
}
}
Я не знаю, будет ли вызываться этот слушатель, когда вы также обновляете профиль из своего клиентского приложения. Если он будет вызван, вам нужно будет проверить, какой клиент вошел в систему, если это клиент publi c, не позволяйте обновлять атрибуты, если это ваш клиент службы, позвольте ему.
Второй будет только позволить вашему сервисному клиенту обновлять профили пользователей и создавать настраиваемое представление в вашем приложении, которое отправляет POST формы вашему клиенту, а не напрямую keycloak. Таким образом, вы можете проверить его в службе перед отправкой в keycloak.
Третий - это для реализации интерфейса a FormAction
, который позволит вам проверить входящую форму на стороне сервера:
Основной интерфейс, который вы должны реализовать, - это интерфейс FormAction. FormAction отвечает за рендеринг и обработку части страницы. Рендеринг выполняется в методе buildPage (), проверка выполняется в методе validate (), операции пост-проверки выполняются успешно ().
@Override
public void validate(ValidationContext context) {
MultivaluedMap<String, String> formData = context.getHttpRequest().getDecodedFormParameters();
UserModel user = context.getUser();
KeycloakSession session = context.getSession();
RealmModel realm = context.getRealm();
String newYourCustomAttribute1 = formData.getFirst("yourCustomAttribute1");
String oldYourCustomAttribute1 = user.getFirstAttribute("yourCustomAttribute1")
if (!newYourCustomAttribute1.equals(oldYourCustomAttribute1)) {
Response challenge = context.form()
.setError("User cannot change the attribute")
.setFormData(formData)
.createResponse(UserModel.RequiredAction.UPDATE_PROFILE);
context.challenge(challenge);
return;
}
context.success();
}