Get expiration date of user’s password in Keycloak

Lejdi Prifti
3 min readSep 8, 2023

--

In this article, I describe a simple method to use to get the expiration date of a user’s password in Keycloak using Spring & Spring Boot.

The password policy is defined in the Authentication section of your realm. As shown in the image below, the “Expire Password” attribute describes the number of days the password is valid before a new password is required.

In order to read this attribute, first of all we define the Keycloak client and specify the credentials of a user that has access to realm management.

@Configuration
@ConfigurationProperties(prefix = "keycloakclient")
@Getter
@Setter
public class KeycloakConfiguration {

private String serverUrl;
private String realm;
private String grantType;
private String username;
private String password;
private String clientId;
private String secret;

@Bean
public Keycloak keycloakClient() {
return KeycloakBuilder.builder().serverUrl(serverUrl).realm(realm).grantType(grantType).username(username)
.password(password).clientId(clientId).clientSecret(secret).build();
}
}

The password policy is defined at the realm level. If we call Keycloak to get the realm details, we get an JSON object that contains among multiple attributes the expiration policy as follows.

{
...,
"passwordPolicy": "length(10) and digits(1) and lowerCase(1) and upperCase(1) and specialChars(1) and forceExpiredPasswordChange(90)",
...
}

In the following function, we extract the forceExpiredPasswordChange and convert it from days to milliseconds.

private Long getTimestampToExpire() {
RealmRepresentation realm = this.getRealmResource().toRepresentation();

// get realm policy
String passwordPolicy = realm.getPasswordPolicy();

// find the password credential
Optional<String> expirationPolicy = Arrays.asList(passwordPolicy.split(AND_SEPARATOR)).stream()
.filter(policy -> policy.contains(FORCE_EXPIRED_PASSWORD_CHANGE)).findFirst();
if (expirationPolicy.isEmpty()) {
return null;
}
// match pattern
Pattern pattern = Pattern.compile(REGEX_GET_DIGIT_FROM_PASSWORD_POLICY);
Matcher matcher = pattern.matcher(expirationPolicy.get());
if (matcher.find()) {
return Long.valueOf(matcher.group(1)) * 24 * 60 * 60 * 1000;
}

return null;
}

The constants defined above can be found in the following code block.


public static final String PASSWORD = "password";

public static final String FORCE_EXPIRED_PASSWORD_CHANGE = "forceExpiredPasswordChange";

public static final String AND_SEPARATOR = "and";

public static final String REGEX_GET_DIGIT_FROM_PASSWORD_POLICY = "\\((\\d+)\\)";

Now that we have the milliseconds for the expiration period, we can calculate the expiration date adding the milliseconds to the timestamp of the credential creation.

public LocalDateTime getExpirationDate(Long creationDate) {
Long timestampToExpire = this.getTimestampToExpire();
if (timestampToExpire != null) {
return Instant.ofEpochMilli(creationDate + timestampToExpire)
.atZone(ZoneId.systemDefault())
.toLocalDateTime();
}
return null;
}

We use the above method to get the expiration date.

Finally, we search through the credentials of userResource , find the credential representation whose type is password , and get from it the createdDate . We pass the createdDate to the method defined above and we get the expiration date of the password.

Note: id is the id of the user in Keycloak.

UserResource userResource = keycloakClient.realm(realm).users().get(id);
if (userResource.credentials() != null) {
Optional<CredentialRepresentation> passwordCredential = userResource.credentials().stream()
.filter(credential -> PASSWORD.equals(credential.getType())).findFirst();
if (passwordCredential.isPresent()) {
user.setExpirationDate(keycloakUtil.getExpirationDate(passwordCredential.get().getCreatedDate()));
}
}

Thanks for reading!

--

--

Lejdi Prifti
Lejdi Prifti

Written by Lejdi Prifti

Senior Software Engineer @ Linfa | Building high-quality software solutions

Responses (1)