All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.phasetwo.keycloak.magic.auth.token.MagicLinkContinuationLinkActionTokenHandler Maven / Gradle / Ivy

package io.phasetwo.keycloak.magic.auth.token;

import static io.phasetwo.keycloak.magic.auth.util.MagicLinkConstants.SESSION_CONFIRMED;

import io.phasetwo.keycloak.magic.auth.model.MagicLinkContinuationBean;
import io.phasetwo.keycloak.magic.auth.util.MagicLinkConstants;
import jakarta.ws.rs.core.Cookie;
import jakarta.ws.rs.core.Response;
import lombok.extern.jbosslog.JBossLog;
import org.keycloak.authentication.actiontoken.AbstractActionTokenHandler;
import org.keycloak.authentication.actiontoken.ActionTokenContext;
import org.keycloak.events.Errors;
import org.keycloak.events.EventType;
import org.keycloak.forms.login.LoginFormsProvider;
import org.keycloak.models.ClientModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.UserModel;
import org.keycloak.services.managers.AuthenticationManager;
import org.keycloak.services.messages.Messages;
import org.keycloak.sessions.AuthenticationSessionModel;
import org.keycloak.sessions.AuthenticationSessionProvider;
import org.keycloak.sessions.RootAuthenticationSessionModel;

/** Handles the magic link continuation action token */
@JBossLog
public class MagicLinkContinuationLinkActionTokenHandler
    extends AbstractActionTokenHandler {

  public MagicLinkContinuationLinkActionTokenHandler() {
    super(
        MagicLinkContinuationActionToken.TOKEN_TYPE,
        MagicLinkContinuationActionToken.class,
        Messages.INVALID_REQUEST,
        EventType.EXECUTE_ACTION_TOKEN,
        Errors.INVALID_REQUEST);
  }

  @Override
  public Response handleToken(
      MagicLinkContinuationActionToken token,
      ActionTokenContext tokenContext) {
    log.debugf("HandleToken for iss:%s, user:%s", token.getIssuedFor(), token.getUserId());
    UserModel user = tokenContext.getAuthenticationSession().getAuthenticatedUser();

    final AuthenticationSessionModel authSession = tokenContext.getAuthenticationSession();
    final ClientModel client = authSession.getClient();

    user.setEmailVerified(true);
    KeycloakSession session = tokenContext.getSession();
    AuthenticationSessionProvider provider = session.authenticationSessions();
    RootAuthenticationSessionModel rootAuthenticationSession =
        provider.getRootAuthenticationSession(tokenContext.getRealm(), token.getSessionId());
    LoginFormsProvider loginFormsProvider = session.getProvider(LoginFormsProvider.class);

    if (rootAuthenticationSession != null) {
      AuthenticationSessionModel authenticationFlowSession =
          rootAuthenticationSession.getAuthenticationSession(client, token.getTabId());
      if (authenticationFlowSession != null) {
        authenticationFlowSession.setAuthNote(SESSION_CONFIRMED, "true");
        Cookie cookie =
            session
                .getContext()
                .getRequestHeaders()
                .getCookies()
                .get(MagicLinkConstants.AUTH_SESSION_ID);

        boolean sameBrowser = cookie != null && cookie.getValue().equals(token.getSessionId());
        MagicLinkContinuationBean magicLinkContinuationBean =
            new MagicLinkContinuationBean(sameBrowser, token.getRedirectUri());
        tokenContext.getEvent().success();

        return loginFormsProvider
            .setAttribute("magicLinkContinuation", magicLinkContinuationBean)
            .createForm("email-confirmation.ftl");
      }
    }

    tokenContext.getEvent().error("Expired magic link continuation session!");
    return loginFormsProvider.createForm("email-confirmation-error.ftl");
  }

  @Override
  public AuthenticationSessionModel startFreshAuthenticationSession(
      MagicLinkContinuationActionToken token,
      ActionTokenContext tokenContext) {
    log.debugf("startFreshAuthenticationSession %s", token.getIssuedFor());

    ClientModel client =
        tokenContext
            .getSession()
            .clients()
            .getClientByClientId(tokenContext.getRealm(), token.getIssuedFor());
    AuthenticationSessionProvider provider = tokenContext.getSession().authenticationSessions();
    RootAuthenticationSessionModel rootAuthenticationSession =
        provider.getRootAuthenticationSession(tokenContext.getRealm(), token.getSessionId());
    if (rootAuthenticationSession == null) {
      AuthenticationSessionModel authSession =
          tokenContext.createAuthenticationSessionForClient(token.getIssuedFor());
      authSession.setAuthNote(AuthenticationManager.INVALIDATE_ACTION_TOKEN, "true");
      return authSession;
    }

    AuthenticationSessionModel authSession =
        rootAuthenticationSession.createAuthenticationSession(client);
    return authSession;
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy