I checked the paritalImport
approach as suggested by others, it seems not available anymore in later versions such as 19.0.1. The error message is something like {"error":"RESTEASY003210: Could not find resource for full path: localhost:8080/auth/admin/realms/myrealm/partialImport"}%.
So I invoke Keycloak API to create users, one by one though. But as long as we can use a program to do it, it's also acceptable.
For example, we can write some java code to invoke the creating user API:
public String createUser(UserPayload user) throws IOException {
var url = "https://keycloak.jiwai.win/auth/admin/realms/UniHeart/users";
var payload = java.lang.String.format("{\"firstName\":\"Sergey\",\"lastName\":\"Kargopolov\", \"email\":\"%s\", \"enabled\":\"true\", \"username\":\"%s\", \"credentials\":[{\"type\":\"password\",\"value\":\"%s\",\"temporary\":false}]}", user.getEmail(), user.getUsername(), user.getPassword());
return this.jsonRequest(url, payload).toString();
}
The above code is merely calling the create user API. But to call it successfully we need firstly got the admin access token:
public KeycloakAccessTokenPayload getAdminAccessToken() throws IOException {
var username = System.getenv("KC_ADMIN");
var password = System.getenv("KC_PASSWORD");
System.out.println(java.lang.String.format("username = %s; password = %s", username, password));
var mediaType = MediaType.parse("application/x-www-form-urlencoded");
var body = RequestBody.create(mediaType, java.lang.String.format("username=%s&password=%s&grant_type=password&client_id=admin-cli", username, password));
var request = new Request.Builder()
.url("https://keycloak.jiwai.win/auth/realms/master/protocol/openid-connect/token")
.method("POST", body)
.addHeader("Content-Type", "application/x-www-form-urlencoded")
.build();
var response = client.newCall(request).execute();
var s = Objects.requireNonNull(response.body()).string();
System.out.println(java.lang.String.format("token response = %s", s));
return JsonHelper.parseFrom(s);
}
And then pass the admin access token to the target API by setting the HTTP header:
public Response jsonRequest(String url, String payload) throws IOException {
var mediaType = MediaType.parse("application/json");
var body = RequestBody.create(mediaType, payload);
var request = new Request.Builder().url(url).method("POST", body).addHeader("Content-Type", "application/json").addHeader("Authorization", java.lang.String.format("Bearer %s", getAdminAccessToken().access_token)).build();
var res = client.newCall(request).execute();
System.out.println(java.lang.String.format("jsonRequest response = %s", res.toString()));
return res;
}
The fully working example is here: https://github.com/Jeff-Tian/keycloak-springboot/blob/main/src/main/java/com/example/keycloakspringboot/KeycloakHelper.java#L29