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

io.phasetwo.keycloak.magic.auth.MagicLinkAuthenticatorFactory Maven / Gradle / Ivy

package io.phasetwo.keycloak.magic.auth;

import static io.phasetwo.keycloak.magic.MagicLink.CREATE_NONEXISTENT_USER_CONFIG_PROPERTY;

import com.google.auto.service.AutoService;
import io.phasetwo.keycloak.magic.MagicLink;
import java.util.List;
import lombok.extern.jbosslog.JBossLog;
import org.keycloak.Config;
import org.keycloak.authentication.Authenticator;
import org.keycloak.authentication.AuthenticatorFactory;
import org.keycloak.models.AuthenticationExecutionModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.models.RealmModel;
import org.keycloak.provider.ProviderConfigProperty;
import org.keycloak.provider.ProviderEvent;

@JBossLog
@AutoService(AuthenticatorFactory.class)
public class MagicLinkAuthenticatorFactory implements AuthenticatorFactory {

  public static final String PROVIDER_ID = "ext-magic-form";

  private static final AuthenticationExecutionModel.Requirement[] REQUIREMENT_CHOICES = {
    AuthenticationExecutionModel.Requirement.REQUIRED,
    AuthenticationExecutionModel.Requirement.ALTERNATIVE,
    AuthenticationExecutionModel.Requirement.DISABLED
  };

  @Override
  public Authenticator create(KeycloakSession session) {
    return new MagicLinkAuthenticator();
  }

  @Override
  public String getId() {
    return PROVIDER_ID;
  }

  @Override
  public String getReferenceCategory() {
    return "alternate-auth";
  }

  @Override
  public boolean isConfigurable() {
    return true;
  }

  @Override
  public boolean isUserSetupAllowed() {
    return true;
  }

  @Override
  public AuthenticationExecutionModel.Requirement[] getRequirementChoices() {
    return REQUIREMENT_CHOICES;
  }

  @Override
  public String getDisplayType() {
    return "Magic Link";
  }

  @Override
  public String getHelpText() {
    return "Sign in with a magic link that will be sent to your email.";
  }

  @Override
  public List getConfigProperties() {
    ProviderConfigProperty createUser = new ProviderConfigProperty();
    createUser.setType(ProviderConfigProperty.BOOLEAN_TYPE);
    createUser.setName(CREATE_NONEXISTENT_USER_CONFIG_PROPERTY);
    createUser.setLabel("Force create user");
    createUser.setHelpText(
        "Creates a new user when an email is provided that does not match an existing user.");
    createUser.setDefaultValue(true);

    ProviderConfigProperty updateProfile = new ProviderConfigProperty();
    updateProfile.setType(ProviderConfigProperty.BOOLEAN_TYPE);
    updateProfile.setName(MagicLinkAuthenticator.UPDATE_PROFILE_ACTION_CONFIG_PROPERTY);
    updateProfile.setLabel("Update profile on create");
    updateProfile.setHelpText("Add an UPDATE_PROFILE required action if the user was created.");
    updateProfile.setDefaultValue(false);

    ProviderConfigProperty updatePassword = new ProviderConfigProperty();
    updatePassword.setType(ProviderConfigProperty.BOOLEAN_TYPE);
    updatePassword.setName(MagicLinkAuthenticator.UPDATE_PASSWORD_ACTION_CONFIG_PROPERTY);
    updatePassword.setLabel("Update password on create");
    updatePassword.setHelpText("Add an UPDATE_PASSWORD required action if the user was created.");
    updatePassword.setDefaultValue(false);

    ProviderConfigProperty actionTokenPersistent = new ProviderConfigProperty();
    actionTokenPersistent.setType(ProviderConfigProperty.BOOLEAN_TYPE);
    actionTokenPersistent.setName(MagicLinkAuthenticator.ACTION_TOKEN_PERSISTENT_CONFIG_PROPERTY);
    actionTokenPersistent.setLabel("Allow magic link to be reusable");
    actionTokenPersistent.setHelpText(
        "Toggle whether magic link should be persistent until expired.");
    actionTokenPersistent.setDefaultValue(true);

    ProviderConfigProperty actionTokenLifeSpan = new ProviderConfigProperty();
    actionTokenLifeSpan.setType(ProviderConfigProperty.STRING_TYPE);
    actionTokenLifeSpan.setName(MagicLinkAuthenticator.ACTION_TOKEN_LIFE_SPAN);
    actionTokenLifeSpan.setLabel("Token lifespan");
    actionTokenLifeSpan.setHelpText(
        "Amount of time the magic link is valid, in seconds. If this value is not specific, it will use the default 86400s (1 day)");

    return List.of(
        createUser, updateProfile, updatePassword, actionTokenPersistent, actionTokenLifeSpan);
  }

  @Override
  public void init(Config.Scope config) {}

  @Override
  public void postInit(KeycloakSessionFactory factory) {
    factory.register(
        (ProviderEvent ev) -> {
          if (ev instanceof RealmModel.RealmPostCreateEvent) {
            MagicLink.realmPostCreate(factory, (RealmModel.RealmPostCreateEvent) ev);
          }
        });
  }

  @Override
  public void close() {}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy