Skip to content

Instantly share code, notes, and snippets.

@rosariop
Last active February 11, 2024 19:54
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save rosariop/0a689fe221760a3ce9cda77af0255f00 to your computer and use it in GitHub Desktop.
Save rosariop/0a689fe221760a3ce9cda77af0255f00 to your computer and use it in GitHub Desktop.
Adding User to keycloak and assigining a role
//took me 4 weeks to figure that out due to some pretty bad documentation on the interwebs
//hope this helps you folks
@Component
public class KeycloakAdminService {
Logger logger = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME);
@Value("${keycloak.auth-server-url}")
private String serverUrl;
@Value("${keycloak.realm}")
private String realm;
@Value("${keycloak.resource}")
private String clientId;
@Value("${admin-user}")
private String adminUsername;
@Value("${admin-password}")
private String adminPassword;
@Value("${keycloak.credentials.secret}")
private String secret;
private final Map<String, List<String>> roleMapping = new HashMap<>();
public UserRepresentation createKeycloakUser(AppUser appUser) {
if (appUser instanceof Student) {
this.roleMapping.put(this.clientId, appUser.getKeycloakRoleAsList());
} else if (appUser instanceof Teacher) {
this.roleMapping.put(this.clientId, appUser.getKeycloakRoleAsList());
} else {
this.roleMapping.put(this.clientId, Collections.singletonList(""));
}
Keycloak adminKeycloak = getAdminKeycloak();
CredentialRepresentation cr = new CredentialRepresentation();
cr.setType(OAuth2Constants.PASSWORD);
cr.setValue(appUser.getPassword());
UserRepresentation userRepresentation = new UserRepresentation();
userRepresentation.setUsername(appUser.getUsername());
userRepresentation.setClientRoles(roleMapping);
userRepresentation.setCredentials(Collections.singletonList(cr));
userRepresentation.setEnabled(true);
adminKeycloak.realm(realm).users().create(userRepresentation);
List<UserRepresentation> userList = adminKeycloak.realm(realm).users().search(appUser.getUsername()).stream()
.filter(userRep -> userRep.getUsername().equals(appUser.getUsername())).collect(Collectors.toList());
userRepresentation = userList.get(0);
logger.info("User with id: " + userRepresentation.getId() + " created");
this.assignRoleToUser(userRepresentation.getId(), appUser.getKeycloakRoleAsList().get(0));
return userRepresentation;
}
private void assignRoleToUser(String userId, String role) {
Keycloak keycloak = getAdminKeycloak();
UsersResource usersResource = keycloak.realm(realm).users();
UserResource userResource = usersResource.get(userId);
//getting client
ClientRepresentation clientRepresentation = keycloak.realm(realm).clients().findAll().stream().filter(client -> client.getClientId().equals(clientId)).collect(Collectors.toList()).get(0);
ClientResource clientResource = keycloak.realm(realm).clients().get(clientRepresentation.getId());
//getting role
RoleRepresentation roleRepresentation = clientResource.roles().list().stream().filter(element -> element.getName().equals(role)).collect(Collectors.toList()).get(0);
//assigning to user
userResource.roles().clientLevel(clientRepresentation.getId()).add(Collections.singletonList(roleRepresentation));
}
private Keycloak getAdminKeycloak() {
return KeycloakBuilder.builder().serverUrl(serverUrl)
.realm(realm)
.clientId(clientId)
.username(adminUsername)
.password(adminPassword)
.grantType("password")
.clientSecret(secret)
.resteasyClient(
new ResteasyClientBuilder()
.connectionPoolSize(10).build()
).build();
}
public void deleteKeycloakUser(Student student) {
Keycloak keycloak = getAdminKeycloak();
List<UserRepresentation> userList = keycloak.realm(realm).users().search(student.getUsername());
for (UserRepresentation user : userList) {
if (user.getUsername().equals(student.getUsername())) {
keycloak.realm(realm).users().delete(user.getId());
}
}
}
}
@ezci
Copy link

ezci commented Apr 11, 2021

Thanks for sharing, but it didn't worked out for me. What finally solved it for me was to create role based groups and assign the group to the user as userRepresentation.setGroups(Arrays.asList(request.getRole()));

This way there is no need for a 2-phase (create user, flush, add role), the above like is called before creating the user. Also the id's are no longer required, all you have to provide is the name of the group.

@DarkFrak74
Copy link

Thanks for sharing, I've been struggling with toRepresentation() for hours.

@johnm96
Copy link

johnm96 commented Aug 26, 2022

Works like a charm! Thank you very much

@h1to
Copy link

h1to commented May 22, 2023

Can you show your pom.xml?

@rosariop
Copy link
Author

rosariop commented Jun 6, 2023

Can you show your pom.xml?

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.1.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>de.magister</groupId>
    <artifactId>waterloo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>waterloo</name>
    <description>Magister Media waterloo Service</description>

    <properties>
        <java.version>11</java.version>
        <keycloak.version>10.0.2</keycloak.version>
    </properties>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.keycloak.bom</groupId>
                <artifactId>keycloak-adapter-bom</artifactId>
                <version>${keycloak.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.keycloak</groupId>
            <artifactId>keycloak-spring-boot-starter</artifactId>
            <version>${keycloak.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mariadb.jdbc</groupId>
            <artifactId>mariadb-java-client</artifactId>
            <version>2.6.1</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.12</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.mockito</groupId>
            <artifactId>mockito-core</artifactId>
            <version>3.4.4</version>
        </dependency>
    </dependencies>

    <packaging>jar</packaging>
    <build>
        <finalName>waterloo</finalName>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.0</version>
                <configuration>
                    <source>11</source>
                    <target>11</target>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment