As Stian said - it is really easy to do as a custom required action:
0) Define a custom RequiredActionFactory that returns your custom RequiredActionProvider
package de.tdlabs.keycloak.authentication;
import org.keycloak.Config.Scope;
import org.keycloak.authentication.RequiredActionFactory;
import org.keycloak.authentication.RequiredActionProvider;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory;
public class RecordFirstLoginRequiredActionFactory implements RequiredActionFactory {
@Override
public RequiredActionProvider create(KeycloakSession session) {
return new RecordFirstLoginRequiredActionProvider();
}
@Override
public void init(Scope config) {
// NOOP
}
@Override
public void postInit(KeycloakSessionFactory factory) {
// NOOP
}
@Override
public void close() {
// NOOP
}
@Override
public String getId() {
return "record-first-login-action";
}
@Override
public String getDisplayText() {
return "Record First Login Action";
}
}
package de.tdlabs.keycloak.authentication;
import static java.time.LocalDateTime.now;
import static java.util.Arrays.asList;
import java.util.List;
import org.keycloak.authentication.RequiredActionContext;
import org.keycloak.authentication.RequiredActionProvider;
import org.keycloak.models.UserModel;
public class RecordFirstLoginRequiredActionProvider implements RequiredActionProvider {
@Override
public void close() {
// NOOP
}
@Override
public void evaluateTriggers(RequiredActionContext context) {
UserModel user = context.getUser();
List<String> list = user.getAttribute("login.first-login-date");
if (list == null || list.isEmpty()) {
user.setAttribute("login.first-login-date", asList(now().toString()));
}
}
@Override
public void requiredActionChallenge(RequiredActionContext context) {
// NOOP
}
@Override
public void processAction(RequiredActionContext context) {
context.success();
}
}
Create a service loader file under:
META-INF/services/org.keycloak.authentication.RequiredActionFactory
with:
de.tdlabs.keycloak.authentication.RecordFirstLoginRequiredActionFactory
1) Build the jar or add the project classpath to the keycloak-server.json via providers:
e.g.:
{
"providers": [
"classpath:${jboss.server.config.dir}/providers/*",
"classpath:${de.tdlabs.keycloak-rest-federation-provider.home}/target/classes/",
"classpath:${de.tdlabs.keycloak-event-listener.home}/target/classes/",
"classpath:${de.tdlabs.keycloak-required-actions.home}/target/classes/"
],
...
}
2) Register the required action in keycloak
2.1) Configure Custom Required Action:
Realm -> Authentication -> Required Actions -> Register -> "Record First Login Action" -> mark as "Default Action"
3) Test the required action
2.2) Login once
2.3) Users -> your user -> Attributes -> the 'login.first-login-date' attribute should be there
Cheers,
Thomas