2

Currently, we have successfully implemented custom login page in keycloak, however we are facing another issue which is user password update on the first login. When i access to keycloak with the username and password like

val token = keycloak.keycloakForFetchUserToken(
                    authentication.principal.toString(),
                    authentication.credentials.toString()
                ).tokenManager().accessToken


fun keycloakForFetchUserToken(username:String, password: String): Keycloak {
        return KeycloakBuilder.builder()
            .serverUrl(KeycloakAttributes.SERVER_URL.value())
            .username(username)
            .password(password)
            .realm(KeycloakAttributes.REALM.value())
            .clientId(KeycloakAttributes.CLIENT_ID.value())
            .clientSecret(KeycloakAttributes.CLIENT_SECRET.value())
            .resteasyClient(ResteasyClientBuilder().connectionPoolSize(20).register(CustomJacksonProvider()).build())
            .build()
    }

When tried to get access token it is throwing 401 unauthorized so it is obvious i cant access to the token of this user because it is locked by keycloak. BUT, as long as I know i can connect to the keycloak and fetch this user's data and see it has required actions like update_password right?, So lets say I got it BUT the question is how can i go forward? like sending the user to the update page?

Has anybody have solution to this problem.

Aliy
  • 406
  • 6
  • 21

1 Answers1

2

I think in this case the best option to let keyklock handle the user's require action not spring security by this following code :

Keycloak keycloak = KeycloakBuilder.builder()
            .serverUrl("localhost")
            .realm("myRealm")
            .grantType(OAuth2Constants.PASSWORD)
            .clientId("myclient")
            .clientSecret("xxxx-xxxxx-xxxx-xxx")
            .username("foo")//the admin user
            .password("password")
            .build();

UsersResource usersResource = keycloak.realm("myRealm").users();

Optional<UserRepresentation> userList = usersResource.list(0, MAX_RESULTS).stream().filter(usr -> usr.getUsername().equals(userName)).findAny();

if (userList.isPresent()) {
        UserRepresentation usr = userList.get();
        if(usr.getRequiredActions().contains("UPDATE_PASSWORD")){

            CredentialRepresentation credential = new CredentialRepresentation();
            credential.setType(CredentialRepresentation.PASSWORD);
            credential.setValue("pwd1234");
            credential.setTemporary(false);

            UserRepresentation user = userRepresentation.get();
            user.setRequiredActions(new ArrayList());

            UserResource userResource = usersResource.get(usr.getId());
            userResource.resetPassword(credential);

        }
    }

Hope is could help

Noa
  • 315
  • 1
  • 7
  • 31
  • Hi @Fateh, in the line "UserRepresentation user = userRepresentation.get();" which is the "userRepresentation" on the right side of the equation? And why do we need to perform a get() on it when we already have the UserRepresentation as "usr" – Mohammed Idris Sep 07 '21 at 22:02