Я думаю, что в клиенте, который я добавил для безопасности Spring, отсутствует что-то, что использует встроенный клиент администратора, когда вы посещаете http://0.0.0.0:8080/realms/testrealm/account/ вручную и входите в систему - инструменты разработчика Chrome показывает, что тот же тип вызова get отлично работает с этим токеном-носителем. Вместо того, чтобы использовать учетную запись службы для вызова API администратора, я бы предпочел попытаться использовать API учетной записи с уже имеющимся у меня токеном для вошедшего в систему пользователя. Это кажется лучшим принципом наименьшей безопасности, поскольку мне нужно только получить/обновить информацию о профиле текущего пользователя.
В чем ключевое различие между клиентом моего приложения Spring Boot, использующим стандартный поток кода авторизации Spring Security для хранения токена вошедшего в систему пользователя в контексте безопасности, и, однако, встроенным клиентом «учетной записи» keycloak, который, похоже, также имеет тот же стандартный код аутентификации поток, который позволяет пользователям входить в систему, но его токены не получают 401, а мои - ..??
Если это поможет, вот код, который я использую, чтобы получить токен и сделать с ним вызов GET учетной записи, но я думаю, что проблема связана с моей конфигурацией области/клиента. Я попытался скопировать роль «профиль просмотра», но не понимаю, какое это имеет значение — выглядит как строковая метка.
Что мне не хватает? Это keycloak 24.0.0, работающий локально.
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import org.keycloak.admin.client.Keycloak;
import org.keycloak.admin.client.spi.ResteasyClientProvider;
import org.keycloak.representations.idm.UserRepresentation;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.oauth2.core.oidc.user.OidcUser;
import org.springframework.stereotype.Service;
import org.jboss.resteasy.client.jaxrs.*;
@Service
public class KeycloakUserService {
@Value("${keycloak.auth-server-url}")
private String serverUrl;
@Value("${keycloak.realm}")
private String realm;
public UserRepresentation getCurrentUser() {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
OidcUser oidcUser = (OidcUser) authentication.getPrincipal();
String accessToken = oidcUser.getIdToken().getTokenValue();
String userId = oidcUser.getSubject();
String url = serverUrl + "/realms/{realm}/account/";
ResteasyClientProvider clientProvider = Keycloak.getClientProvider();
ResteasyClient client = (ResteasyClient) clientProvider.newRestEasyClient(null, null, false);
ResteasyWebTarget target = client.target(url).resolveTemplate("realm", realm);
System.out.println("URL: " + url);
Response response = target.request(MediaType.APPLICATION_JSON)
.header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)
.property("userProfileMetadata","true")
.get();
if (response.getStatus() == 200) {
return response.readEntity(UserRepresentation.class);
} else {
// Handle errors appropriately
System.out.println("Error: " + response.getStatus());
String errorMessage = response.readEntity(String.class);
System.out.println("Error Message: " + errorMessage);
return null;
}
}
В чем ключевое различие между клиентом моего приложения Spring Boot... и встроенным клиентом "учетной записи" keycloak...??
Роли клиентов. Перейдите к сведениям о клиентах и откройте вкладку Roles
для них двоих.
Спасибо, это было полезно - я, вероятно, скоро разберусь с этим здесь. Возможно, есть какая-то документация, которую я не нашел, которая более подробно описывает, какие роли и какое поведение обеспечивают? Имена в некоторой степени описательны, но я не уверен, например, добавлять ли роли с такими же именами в мой клиент или добавлять роли клиента «учетной записи»? Мне нужно только загрузить/сохранить профиль текущего пользователя (userRepresentation), включая некоторые дополнительные атрибуты, и мне нужен минимальный набор ролей, необходимый для этого.