두리공장
스프링부트에서 keycloak admin restAPI를 사용하려면,,, 본문
스프링부트에서 keycloak admin restapi 를 사용해야 할 경우가 있다. (사용자 계정에 대한 정보 변경 등등...)
나의 경우에는 사용자가 등록한 OTP 정보를 admin cli 를 사용하여 삭제해 주어야 하는 미션이 있었다.
몇몇 방법이 있지만 구글링 결과 키클락에서 제공하는 라이브러리를 사용하기로 했다.
(순수 restapi를 구현하여 사용하는 방법도 있디만,,,ㅎㅎ)
1. pom.xml 에 디펜던시 추가
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-admin-client</artifactId>
<version>20.0.5</version>
</dependency>
2. application.yml 에 접속정보 추가
keycloak:
server-url: http://localhost:9080/
realm: master
username: admin
password: XXX
3. keycloakUtil.java 만들기(bean으로 사용할 것이므로 Component 어노테이션을 추가해 준다.
package com.durifac.jpa.global.utils;
import lombok.RequiredArgsConstructor;
import org.jboss.resteasy.client.jaxrs.internal.ResteasyClientBuilderImpl;
import org.keycloak.OAuth2Constants;
import org.keycloak.admin.client.Keycloak;
import org.keycloak.admin.client.KeycloakBuilder;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
@RequiredArgsConstructor
public class KeycloakUtil {
@Value("${keycloak.server-url}")
private String serverUrl;
@Value("${keycloak.realm}")
private String realm;
@Value("${keycloak.username}")
private String username;
@Value("${keycloak.password}")
private String password;
public Keycloak conn() {
return KeycloakBuilder.builder()
.serverUrl(serverUrl)
.realm(realm)
.grantType(OAuth2Constants.PASSWORD)
.username(username)
.password(password)
.clientId("admin-cli")
.clientSecret("")
.resteasyClient(new ResteasyClientBuilderImpl()
.connectionPoolSize(10)
.build())
.build();
}
}
4. controller 부분
package com.durifac.jpa.domain.keycloak.controller;
import com.durifac.jpa.domain.keycloak.service.KeycloakService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.RequiredArgsConstructor;
import org.keycloak.admin.client.resource.UserResource;
import org.keycloak.representations.idm.CredentialRepresentation;
import org.keycloak.representations.idm.UserRepresentation;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequiredArgsConstructor
@RequestMapping("/keycloak")
public class KeycloakController {
private final KeycloakService keycloakService;
@Operation(summary = "키클락 유저", description = "키클락 유저정보를 가져옵니다")
@GetMapping("/user")
public UserRepresentation getUser(@RequestParam(name = "id") @Schema(example = "7682bedd-abe0-468f-aedb-4385b0f4b0e3") String id){
UserResource userResource = keycloakService.getUser(id);
return userResource.toRepresentation();
}
@Operation(summary = "키클락 유저의 인증정보", description = "키클락 유저의 인증정보를 가져옵니다")
@GetMapping("/user/credentials")
public List<CredentialRepresentation> getUserCredentials(@RequestParam(name = "id") @Schema(example = "7682bedd-abe0-468f-aedb-4385b0f4b0e3")String id){
List<CredentialRepresentation> credentialRepresentations = keycloakService.getUserCredentials(id);
return credentialRepresentations;
}
@Operation(summary = "키클락 유저의 인증정보 Otp id를 가져온다", description = "키클락 유저의 인증정보otp 아이디를 가져옵니다")
@GetMapping("/user/credentials/ids")
public List<String> getFindbyCredentialList(@RequestParam(name = "id") @Schema(example = "7682bedd-abe0-468f-aedb-4385b0f4b0e3")String id){
List<String> ids = keycloakService.getFindbyCredentialList(id);
return ids;
}
@Operation(summary = "키클락 유저의 인증정보 Otp 를 삭제한다", description = "키클락 유저의 인증정보를 삭제한다")
@PostMapping("/user/credentials/ids")
public void removeOtp(
@RequestParam(name = "id") @Schema(example = "7682bedd-abe0-468f-aedb-4385b0f4b0e3")String id,
@RequestParam(name = "credentialId") @Schema(example = "096cc197-9fc4-413e-b688-357031caaa34")String credentialId
){
keycloakService.removeOtp(id, credentialId);
}
}
4. service 부분
package com.durifac.jpa.domain.keycloak.service;
import com.durifac.jpa.global.utils.KeycloakUtil;
import lombok.AllArgsConstructor;
import org.keycloak.admin.client.resource.UserResource;
import org.keycloak.representations.idm.CredentialRepresentation;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.stream.Collectors;
@Service
@AllArgsConstructor
public class KeycloakService {
private final KeycloakUtil keycloak;
//계정정보를 가져온다.
public UserResource getUser(String id) {
UserResource userResource = keycloak.conn().realm("durifac").users().get(id);
return userResource;
}
//credential 정보를 가져온다.
public List<CredentialRepresentation> getUserCredentials(String id) {
UserResource userResource = keycloak.conn().realm("durifac").users().get(id);
return userResource.credentials();
}
//credential 목록에서 otp id를 찾아온다.
public List<String> getFindbyCredentialList(String id) {
UserResource userResource = getUser(id);
List<CredentialRepresentation> list = userResource.credentials().stream().filter(e -> e.getType().equals("otp"))
.collect(Collectors.toList());
List<String> ids = list.stream().map(e -> e.getId()).toList();
return ids;
}
//otp를 삭제한다.
public void removeOtp(String id, String otpId) {
UserResource userResource = keycloak.conn().realm("durifac").users().get(id);
userResource.removeCredential(otpId);
}
}
키클락 admin rest api 에서는 다음의 링크 문서를 참조한다.
https://www.keycloak.org/docs-api/21.0.1/rest-api/index.html
'cloud' 카테고리의 다른 글
[ELK] 엘라스틱서치에서 logstash 로 RDBMS 데이터 pipeline으로 연결하기 (0) | 2023.06.17 |
---|---|
[keycloak] SPI 에서 custom role 연동하기 (0) | 2023.06.07 |
[keycloak] User Storage SPI 사용시 Create at 필드 동기화 (0) | 2023.06.06 |
[keycloak] SPI (service provider interface) 를 이용하여 사용자DB를 연결하기 (version 20.0.5) (0) | 2023.05.22 |