<div dir="ltr"><div>As Stian said - it is really easy to do as a custom required action:</div><div><br></div><div>0) Define a custom RequiredActionFactory that returns your custom RequiredActionProvider</div><div><br></div><div>package de.tdlabs.keycloak.authentication;</div><div><br></div><div>import org.keycloak.Config.Scope;</div><div>import org.keycloak.authentication.RequiredActionFactory;</div><div>import org.keycloak.authentication.RequiredActionProvider;</div><div>import org.keycloak.models.KeycloakSession;</div><div>import org.keycloak.models.KeycloakSessionFactory;</div><div><br></div><div>public class RecordFirstLoginRequiredActionFactory implements RequiredActionFactory {</div><div><br></div><div> @Override</div><div> public RequiredActionProvider create(KeycloakSession session) {</div><div> return new RecordFirstLoginRequiredActionProvider();</div><div> }</div><div><br></div><div> @Override</div><div> public void init(Scope config) {</div><div> // NOOP</div><div> }</div><div><br></div><div> @Override</div><div> public void postInit(KeycloakSessionFactory factory) {</div><div> // NOOP</div><div> }</div><div><br></div><div> @Override</div><div> public void close() {</div><div> // NOOP</div><div> }</div><div><br></div><div> @Override</div><div> public String getId() {</div><div> return "record-first-login-action";</div><div> }</div><div><br></div><div> @Override</div><div> public String getDisplayText() {</div><div> return "Record First Login Action";</div><div> }</div><div>}</div><div><br></div><div>package de.tdlabs.keycloak.authentication;</div><div><br></div><div>import static java.time.LocalDateTime.now;</div><div>import static java.util.Arrays.asList;</div><div><br></div><div>import java.util.List;</div><div><br></div><div>import org.keycloak.authentication.RequiredActionContext;</div><div>import org.keycloak.authentication.RequiredActionProvider;</div><div>import org.keycloak.models.UserModel;</div><div><br></div><div>public class RecordFirstLoginRequiredActionProvider implements RequiredActionProvider {</div><div><br></div><div> @Override</div><div> public void close() {</div><div> // NOOP</div><div> }</div><div><br></div><div> @Override</div><div> public void evaluateTriggers(RequiredActionContext context) {</div><div><br></div><div> UserModel user = context.getUser();</div><div><br></div><div> List<String> list = user.getAttribute("login.first-login-date");</div><div><br></div><div> if (list == null || list.isEmpty()) {</div><div> user.setAttribute("login.first-login-date", asList(now().toString()));</div><div> }</div><div> }</div><div><br></div><div> @Override</div><div> public void requiredActionChallenge(RequiredActionContext context) {</div><div> // NOOP</div><div> }</div><div><br></div><div> @Override</div><div> public void processAction(RequiredActionContext context) {</div><div> context.success();</div><div> }</div><div>}</div><div><br></div><div>Create a service loader file under:</div><div>META-INF/services/org.keycloak.authentication.RequiredActionFactory</div><div><br></div><div>with:</div><div>de.tdlabs.keycloak.authentication.RecordFirstLoginRequiredActionFactory</div><div><br></div><div>1) Build the jar or add the project classpath to the keycloak-server.json via providers:</div><div>e.g.:</div><div><br></div><div>{</div><div> "providers": [</div><div> "classpath:${jboss.server.config.dir}/providers/*",</div><div> "classpath:${de.tdlabs.keycloak-rest-federation-provider.home}/target/classes/",</div><div> "classpath:${de.tdlabs.keycloak-event-listener.home}/target/classes/",</div><div> "classpath:${de.tdlabs.keycloak-required-actions.home}/target/classes/"</div><div> ],</div><div> ...</div><div>}</div><div><br></div><div>2) Register the required action in keycloak</div><div><br></div><div>2.1) Configure Custom Required Action:</div><div>Realm -> Authentication -> Required Actions -> Register -> "Record First Login Action" -> mark as "Default Action"</div><div><br></div><div>3) Test the required action</div><div>2.2) Login once</div><div>2.3) Users -> your user -> Attributes -> the 'login.first-login-date' attribute should be there</div><div><br></div><div>Cheers,</div><div>Thomas</div></div><div class="gmail_extra"><br><div class="gmail_quote">2016-01-20 12:35 GMT+01:00 Stian Thorgersen <span dir="ltr"><<a href="mailto:sthorger@redhat.com" target="_blank">sthorger@redhat.com</a>></span>:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">Not built-in, but you can create a required action that does that and enable it as a default action. Take a look at <a href="http://keycloak.github.io/docs/userguide/keycloak-server/html/auth_spi.html" target="_blank">http://keycloak.github.io/docs/userguide/keycloak-server/html/auth_spi.html</a></div><div class="gmail_extra"><br><div class="gmail_quote"><div><div class="h5">On 20 January 2016 at 11:58, LIEVRE Olivier <span dir="ltr"><<a href="mailto:olivier.lievre@altran.com" target="_blank">olivier.lievre@altran.com</a>></span> wrote:<br></div></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div><div class="h5">
<div lang="FR" link="blue" vlink="purple">
<div>
<div>
<div>
<div>
<div>
<div>
<div>
<div>
<div>
<div>
<div>
<div>
<div>
<div>
<div>
<div>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d">Hello,<u></u><u></u></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d"><u></u> <u></u></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d">Is there a possibility to store in user attributes the timestamp of first user login to keycloak ?<u></u><u></u></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d"><u></u> <u></u></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d">KR,<u></u><u></u></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d">Olivier<u></u><u></u></span></p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<br></div></div>_______________________________________________<br>
keycloak-user mailing list<br>
<a href="mailto:keycloak-user@lists.jboss.org" target="_blank">keycloak-user@lists.jboss.org</a><br>
<a href="https://lists.jboss.org/mailman/listinfo/keycloak-user" rel="noreferrer" target="_blank">https://lists.jboss.org/mailman/listinfo/keycloak-user</a><br></blockquote></div><br></div>
<br>_______________________________________________<br>
keycloak-user mailing list<br>
<a href="mailto:keycloak-user@lists.jboss.org">keycloak-user@lists.jboss.org</a><br>
<a href="https://lists.jboss.org/mailman/listinfo/keycloak-user" rel="noreferrer" target="_blank">https://lists.jboss.org/mailman/listinfo/keycloak-user</a><br></blockquote></div><br></div>