commit
57780b6520
33 changed files with 1990 additions and 109 deletions
|
@ -22,6 +22,44 @@
|
||||||
<column name="REPRESENTATION" type="VARCHAR(25500)"/>
|
<column name="REPRESENTATION" type="VARCHAR(25500)"/>
|
||||||
<column name="ERROR" type="VARCHAR(255)"/>
|
<column name="ERROR" type="VARCHAR(255)"/>
|
||||||
</createTable>
|
</createTable>
|
||||||
|
<createTable tableName="AUTHENTICATOR">
|
||||||
|
<column name="ID" type="VARCHAR(36)">
|
||||||
|
<constraints nullable="false"/>
|
||||||
|
</column>
|
||||||
|
<column name="ALIAS" type="VARCHAR(255)"/>
|
||||||
|
<column name="REALM_ID" type="VARCHAR(36)"/>
|
||||||
|
<column name="PROVIDER_ID" type="VARCHAR(36)"/>
|
||||||
|
</createTable>
|
||||||
|
<createTable tableName="AUTHENTICATION_FLOW">
|
||||||
|
<column name="ID" type="VARCHAR(36)">
|
||||||
|
<constraints nullable="false"/>
|
||||||
|
</column>
|
||||||
|
<column name="ALIAS" type="VARCHAR(255)"/>
|
||||||
|
<column name="DESCRIPTION" type="VARCHAR(255)"/>
|
||||||
|
<column name="REALM_ID" type="VARCHAR(36)"/>
|
||||||
|
</createTable>
|
||||||
|
<createTable tableName="AUTHENTICATION_EXECUTION">
|
||||||
|
<column name="ID" type="VARCHAR(36)">
|
||||||
|
<constraints nullable="false"/>
|
||||||
|
</column>
|
||||||
|
<column name="ALIAS" type="VARCHAR(255)"/>
|
||||||
|
<column name="AUTHENTICATOR" type="VARCHAR(36)"/>
|
||||||
|
<column name="REALM_ID" type="VARCHAR(36)"/>
|
||||||
|
<column name="FLOW_ID" type="VARCHAR(36)"/>
|
||||||
|
<column name="REQUIREMENT" type="INT"/>
|
||||||
|
<column name="PRIORITY" type="INT"/>
|
||||||
|
<column name="USER_SETUP_ALLOWED" type="BOOLEAN" defaultValueBoolean="false"/>
|
||||||
|
<column name="AUTHENTICATOR_FLOW" type="BOOLEAN" defaultValueBoolean="false"/>
|
||||||
|
</createTable>
|
||||||
|
<createTable tableName="AUTHENTICATOR_CONFIG">
|
||||||
|
<column name="AUTHENTICATOR_ID" type="VARCHAR(36)">
|
||||||
|
<constraints nullable="false"/>
|
||||||
|
</column>
|
||||||
|
<column name="VALUE" type="CLOB"/>
|
||||||
|
<column name="NAME" type="VARCHAR(255)">
|
||||||
|
<constraints nullable="false"/>
|
||||||
|
</column>
|
||||||
|
</createTable>
|
||||||
<createTable tableName="USER_FEDERATION_MAPPER">
|
<createTable tableName="USER_FEDERATION_MAPPER">
|
||||||
<column name="ID" type="VARCHAR(36)">
|
<column name="ID" type="VARCHAR(36)">
|
||||||
<constraints nullable="false"/>
|
<constraints nullable="false"/>
|
||||||
|
@ -58,7 +96,7 @@
|
||||||
</column>
|
</column>
|
||||||
</addColumn>
|
</addColumn>
|
||||||
<createTable tableName="CLIENT_SESSION_AUTH_STATUS">
|
<createTable tableName="CLIENT_SESSION_AUTH_STATUS">
|
||||||
<column name="AUTHENTICATOR" type="VARCHAR(32)">
|
<column name="AUTHENTICATOR" type="VARCHAR(36)">
|
||||||
<constraints nullable="false"/>
|
<constraints nullable="false"/>
|
||||||
</column>
|
</column>
|
||||||
<column name="STATUS" type="INT"/>
|
<column name="STATUS" type="INT"/>
|
||||||
|
@ -67,10 +105,10 @@
|
||||||
</column>
|
</column>
|
||||||
</createTable>
|
</createTable>
|
||||||
<addColumn tableName="CLIENT_SESSION">
|
<addColumn tableName="CLIENT_SESSION">
|
||||||
<column name="AUTH_USER_ID" type="VARCHAR(32)"/>
|
<column name="AUTH_USER_ID" type="VARCHAR(36)"/>
|
||||||
</addColumn>
|
</addColumn>
|
||||||
<addColumn tableName="USER_REQUIRED_ACTION">
|
<addColumn tableName="USER_REQUIRED_ACTION">
|
||||||
<column name="REQUIRED_ACTION" type="VARCHAR(32)">
|
<column name="REQUIRED_ACTION" type="VARCHAR(36)">
|
||||||
<constraints nullable="false"/>
|
<constraints nullable="false"/>
|
||||||
</column>
|
</column>
|
||||||
</addColumn>
|
</addColumn>
|
||||||
|
@ -91,6 +129,10 @@
|
||||||
<column name="REQUIRED_ACTION" value="UPDATE_PASSWORD"/>
|
<column name="REQUIRED_ACTION" value="UPDATE_PASSWORD"/>
|
||||||
<where>ACTION = 3</where>
|
<where>ACTION = 3</where>
|
||||||
</update>
|
</update>
|
||||||
|
<addPrimaryKey columnNames="ID" constraintName="CONSTRAINT_AUTHENTICATOR_PK" tableName="AUTHENTICATOR"/>
|
||||||
|
<addPrimaryKey columnNames="ID" constraintName="CONSTRAINT_AUTHENTICATION_FLOW_PK" tableName="AUTHENTICATION_FLOW"/>
|
||||||
|
<addPrimaryKey columnNames="ID" constraintName="CONSTRAINT_AUTHENTICATION_EXECUTION_PK" tableName="AUTHENTICATION_EXECUTION"/>
|
||||||
|
<addPrimaryKey columnNames="AUTHENTICATOR_ID, NAME" constraintName="CONSTRAINT_AUTHENTICATOR_CONFIG_PK" tableName="AUTHENTICATOR_CONFIG"/>
|
||||||
<dropPrimaryKey constraintName="CONSTRAINT_2" tableName="USER_REQUIRED_ACTION"/>
|
<dropPrimaryKey constraintName="CONSTRAINT_2" tableName="USER_REQUIRED_ACTION"/>
|
||||||
<dropColumn tableName="USER_REQUIRED_ACTION" columnName="ACTION"/>
|
<dropColumn tableName="USER_REQUIRED_ACTION" columnName="ACTION"/>
|
||||||
<addPrimaryKey columnNames="REQUIRED_ACTION, USER_ID" constraintName="CONSTRAINT_REQUIRED_ACTION" tableName="USER_REQUIRED_ACTION"/>
|
<addPrimaryKey columnNames="REQUIRED_ACTION, USER_ID" constraintName="CONSTRAINT_REQUIRED_ACTION" tableName="USER_REQUIRED_ACTION"/>
|
||||||
|
@ -98,6 +140,10 @@
|
||||||
<addPrimaryKey columnNames="ID" constraintName="CONSTRAINT_FEDMAPPERPM" tableName="USER_FEDERATION_MAPPER"/>
|
<addPrimaryKey columnNames="ID" constraintName="CONSTRAINT_FEDMAPPERPM" tableName="USER_FEDERATION_MAPPER"/>
|
||||||
<addPrimaryKey columnNames="USER_FEDERATION_MAPPER_ID, NAME" constraintName="CONSTRAINT_FEDMAPPER_CFG_PM" tableName="USER_FEDERATION_MAPPER_CONFIG"/>
|
<addPrimaryKey columnNames="USER_FEDERATION_MAPPER_ID, NAME" constraintName="CONSTRAINT_FEDMAPPER_CFG_PM" tableName="USER_FEDERATION_MAPPER_CONFIG"/>
|
||||||
<addForeignKeyConstraint baseColumnNames="CLIENT_SESSION" baseTableName="CLIENT_SESSION_AUTH_STATUS" constraintName="AUTH_STATUS_CONSTRAINT" referencedColumnNames="ID" referencedTableName="CLIENT_SESSION"/>
|
<addForeignKeyConstraint baseColumnNames="CLIENT_SESSION" baseTableName="CLIENT_SESSION_AUTH_STATUS" constraintName="AUTH_STATUS_CONSTRAINT" referencedColumnNames="ID" referencedTableName="CLIENT_SESSION"/>
|
||||||
|
<addForeignKeyConstraint baseColumnNames="REALM_ID" baseTableName="AUTHENTICATOR" constraintName="FK_AUTHENTICATOR_REALM" referencedColumnNames="ID" referencedTableName="REALM"/>
|
||||||
|
<addForeignKeyConstraint baseColumnNames="REALM_ID" baseTableName="AUTHENTICATION_FLOW" constraintName="FK_AUTHENTICATION_FLOW_REALM" referencedColumnNames="ID" referencedTableName="REALM"/>
|
||||||
|
<addForeignKeyConstraint baseColumnNames="REALM_ID" baseTableName="AUTHENTICATION_EXECUTION" constraintName="FK_AUTHENTICATION_EXECUTION_REALM" referencedColumnNames="ID" referencedTableName="REALM"/>
|
||||||
|
<addForeignKeyConstraint baseColumnNames="FLOW_ID" baseTableName="AUTHENTICATION_EXECUTION" constraintName="FK_AUTHENTICATION_EXECUTION_FLOW" referencedColumnNames="ID" referencedTableName="AUTHENTICATION_FLOW"/>
|
||||||
<addForeignKeyConstraint baseColumnNames="REALM_ID" baseTableName="USER_FEDERATION_MAPPER" constraintName="FK_FEDMAPPERPM_REALM" referencedColumnNames="ID" referencedTableName="REALM"/>
|
<addForeignKeyConstraint baseColumnNames="REALM_ID" baseTableName="USER_FEDERATION_MAPPER" constraintName="FK_FEDMAPPERPM_REALM" referencedColumnNames="ID" referencedTableName="REALM"/>
|
||||||
<addForeignKeyConstraint baseColumnNames="FEDERATION_PROVIDER_ID" baseTableName="USER_FEDERATION_MAPPER" constraintName="FK_FEDMAPPERPM_FEDPRV" referencedColumnNames="ID" referencedTableName="USER_FEDERATION_PROVIDER"/>
|
<addForeignKeyConstraint baseColumnNames="FEDERATION_PROVIDER_ID" baseTableName="USER_FEDERATION_MAPPER" constraintName="FK_FEDMAPPERPM_FEDPRV" referencedColumnNames="ID" referencedTableName="USER_FEDERATION_PROVIDER"/>
|
||||||
<addForeignKeyConstraint baseColumnNames="USER_FEDERATION_MAPPER_ID" baseTableName="USER_FEDERATION_MAPPER_CONFIG" constraintName="FK_FEDMAPPER_CFG" referencedColumnNames="ID" referencedTableName="USER_FEDERATION_MAPPER"/>
|
<addForeignKeyConstraint baseColumnNames="USER_FEDERATION_MAPPER_ID" baseTableName="USER_FEDERATION_MAPPER_CONFIG" constraintName="FK_FEDMAPPER_CFG" referencedColumnNames="ID" referencedTableName="USER_FEDERATION_MAPPER"/>
|
||||||
|
|
|
@ -25,6 +25,9 @@
|
||||||
<class>org.keycloak.models.jpa.entities.UserConsentEntity</class>
|
<class>org.keycloak.models.jpa.entities.UserConsentEntity</class>
|
||||||
<class>org.keycloak.models.jpa.entities.UserConsentRoleEntity</class>
|
<class>org.keycloak.models.jpa.entities.UserConsentRoleEntity</class>
|
||||||
<class>org.keycloak.models.jpa.entities.UserConsentProtocolMapperEntity</class>
|
<class>org.keycloak.models.jpa.entities.UserConsentProtocolMapperEntity</class>
|
||||||
|
<class>org.keycloak.models.jpa.entities.AuthenticationFlowEntity</class>
|
||||||
|
<class>org.keycloak.models.jpa.entities.AuthenticationExecutionEntity</class>
|
||||||
|
<class>org.keycloak.models.jpa.entities.AuthenticatorEntity</class>
|
||||||
|
|
||||||
<!-- JpaUserSessionProvider -->
|
<!-- JpaUserSessionProvider -->
|
||||||
<class>org.keycloak.models.sessions.jpa.entities.ClientSessionEntity</class>
|
<class>org.keycloak.models.sessions.jpa.entities.ClientSessionEntity</class>
|
||||||
|
|
|
@ -0,0 +1,83 @@
|
||||||
|
package org.keycloak.models;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
* @version $Revision: 1 $
|
||||||
|
*/
|
||||||
|
public class AuthenticationExecutionModel {
|
||||||
|
|
||||||
|
private String id;
|
||||||
|
private String authenticator;
|
||||||
|
private boolean autheticatorFlow;
|
||||||
|
private Requirement requirement;
|
||||||
|
private boolean userSetupAllowed;
|
||||||
|
private int priority;
|
||||||
|
private String parentFlow;
|
||||||
|
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(String id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAuthenticator() {
|
||||||
|
return authenticator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAuthenticator(String authenticator) {
|
||||||
|
this.authenticator = authenticator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Requirement getRequirement() {
|
||||||
|
return requirement;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRequirement(Requirement requirement) {
|
||||||
|
this.requirement = requirement;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getPriority() {
|
||||||
|
return priority;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPriority(int priority) {
|
||||||
|
this.priority = priority;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isUserSetupAllowed() {
|
||||||
|
return userSetupAllowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUserSetupAllowed(boolean userSetupAllowed) {
|
||||||
|
this.userSetupAllowed = userSetupAllowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getParentFlow() {
|
||||||
|
return parentFlow;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setParentFlow(String parentFlow) {
|
||||||
|
this.parentFlow = parentFlow;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is the referenced authenticator a flow?
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public boolean isAutheticatorFlow() {
|
||||||
|
return autheticatorFlow;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAutheticatorFlow(boolean autheticatorFlow) {
|
||||||
|
this.autheticatorFlow = autheticatorFlow;
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum Requirement {
|
||||||
|
REQUIRED,
|
||||||
|
OPTIONAL,
|
||||||
|
ALTERNATIVE
|
||||||
|
}
|
||||||
|
}
|
35
model/api/src/main/java/org/keycloak/models/AuthenticationFlowModel.java
Executable file
35
model/api/src/main/java/org/keycloak/models/AuthenticationFlowModel.java
Executable file
|
@ -0,0 +1,35 @@
|
||||||
|
package org.keycloak.models;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
* @version $Revision: 1 $
|
||||||
|
*/
|
||||||
|
public class AuthenticationFlowModel {
|
||||||
|
private String id;
|
||||||
|
private String alias;
|
||||||
|
private String description;
|
||||||
|
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(String id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAlias() {
|
||||||
|
return alias;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAlias(String alias) {
|
||||||
|
this.alias = alias;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDescription() {
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDescription(String description) {
|
||||||
|
this.description = description;
|
||||||
|
}
|
||||||
|
}
|
|
@ -9,23 +9,9 @@ import java.util.Map;
|
||||||
*/
|
*/
|
||||||
public class AuthenticatorModel {
|
public class AuthenticatorModel {
|
||||||
|
|
||||||
public enum Requirement {
|
|
||||||
REQUIRED,
|
|
||||||
OPTIONAL,
|
|
||||||
ALTERNATIVE
|
|
||||||
}
|
|
||||||
|
|
||||||
private String id;
|
private String id;
|
||||||
private String alias;
|
private String alias;
|
||||||
private String providerId;
|
private String providerId;
|
||||||
private boolean masterAuthenticator;
|
|
||||||
private boolean formBased;
|
|
||||||
private String inputPage;
|
|
||||||
private String actionUrl;
|
|
||||||
private String setupUrl;
|
|
||||||
private Requirement requirement;
|
|
||||||
private boolean userSetupAllowed;
|
|
||||||
private int priority;
|
|
||||||
private Map<String, String> config = new HashMap<String, String>();
|
private Map<String, String> config = new HashMap<String, String>();
|
||||||
|
|
||||||
|
|
||||||
|
@ -53,70 +39,6 @@ public class AuthenticatorModel {
|
||||||
this.providerId = providerId;
|
this.providerId = providerId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isFormBased() {
|
|
||||||
return formBased;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setFormBased(boolean formBased) {
|
|
||||||
this.formBased = formBased;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getInputPage() {
|
|
||||||
return inputPage;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setInputPage(String inputPage) {
|
|
||||||
this.inputPage = inputPage;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getActionUrl() {
|
|
||||||
return actionUrl;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setActionUrl(String actionUrl) {
|
|
||||||
this.actionUrl = actionUrl;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getSetupUrl() {
|
|
||||||
return setupUrl;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSetupUrl(String setupUrl) {
|
|
||||||
this.setupUrl = setupUrl;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Requirement getRequirement() {
|
|
||||||
return requirement;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setRequirement(Requirement requirement) {
|
|
||||||
this.requirement = requirement;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getPriority() {
|
|
||||||
return priority;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPriority(int priority) {
|
|
||||||
this.priority = priority;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isUserSetupAllowed() {
|
|
||||||
return userSetupAllowed;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setUserSetupAllowed(boolean userSetupAllowed) {
|
|
||||||
this.userSetupAllowed = userSetupAllowed;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isMasterAuthenticator() {
|
|
||||||
return masterAuthenticator;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setMasterAuthenticator(boolean masterAuthenticator) {
|
|
||||||
this.masterAuthenticator = masterAuthenticator;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Map<String, String> getConfig() {
|
public Map<String, String> getConfig() {
|
||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
|
|
|
@ -173,6 +173,25 @@ public interface RealmModel extends RoleContainerModel {
|
||||||
|
|
||||||
void setSmtpConfig(Map<String, String> smtpConfig);
|
void setSmtpConfig(Map<String, String> smtpConfig);
|
||||||
|
|
||||||
|
List<AuthenticationFlowModel> getAuthenticationFlows();
|
||||||
|
AuthenticationFlowModel addAuthenticationFlow(AuthenticationFlowModel model);
|
||||||
|
AuthenticationFlowModel getAuthenticationFlowById(String id);
|
||||||
|
void removeAuthenticationFlow(AuthenticationFlowModel model);
|
||||||
|
void updateAuthenticationFlow(AuthenticationFlowModel model);
|
||||||
|
|
||||||
|
List<AuthenticationExecutionModel> getAuthenticationExecutions(String flowId);
|
||||||
|
AuthenticationExecutionModel getAuthenticationExecutionById(String id);
|
||||||
|
AuthenticationExecutionModel addAuthenticatorExecution(AuthenticationExecutionModel model);
|
||||||
|
void updateAuthenticatorExecution(AuthenticationExecutionModel model);
|
||||||
|
void removeAuthenticatorExecution(AuthenticationExecutionModel model);
|
||||||
|
|
||||||
|
|
||||||
|
List<AuthenticatorModel> getAuthenticators();
|
||||||
|
AuthenticatorModel addAuthenticator(AuthenticatorModel model);
|
||||||
|
void updateAuthenticator(AuthenticatorModel model);
|
||||||
|
void removeAuthenticator(AuthenticatorModel model);
|
||||||
|
AuthenticatorModel getAuthenticatorById(String id);
|
||||||
|
|
||||||
List<IdentityProviderModel> getIdentityProviders();
|
List<IdentityProviderModel> getIdentityProviders();
|
||||||
IdentityProviderModel getIdentityProviderByAlias(String alias);
|
IdentityProviderModel getIdentityProviderByAlias(String alias);
|
||||||
void addIdentityProvider(IdentityProviderModel identityProvider);
|
void addIdentityProvider(IdentityProviderModel identityProvider);
|
||||||
|
|
|
@ -0,0 +1,74 @@
|
||||||
|
package org.keycloak.models.entities;
|
||||||
|
|
||||||
|
import org.keycloak.models.AuthenticationExecutionModel;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
* @version $Revision: 1 $
|
||||||
|
*/
|
||||||
|
public class AuthenticationExecutionEntity {
|
||||||
|
protected String id;
|
||||||
|
protected String authenticator;
|
||||||
|
protected AuthenticationExecutionModel.Requirement requirement;
|
||||||
|
protected int priority;
|
||||||
|
private boolean userSetupAllowed;
|
||||||
|
private boolean autheticatorFlow;
|
||||||
|
private String parentFlow;
|
||||||
|
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(String id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAuthenticator() {
|
||||||
|
return authenticator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAuthenticator(String authenticator) {
|
||||||
|
this.authenticator = authenticator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AuthenticationExecutionModel.Requirement getRequirement() {
|
||||||
|
return requirement;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRequirement(AuthenticationExecutionModel.Requirement requirement) {
|
||||||
|
this.requirement = requirement;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getPriority() {
|
||||||
|
return priority;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPriority(int priority) {
|
||||||
|
this.priority = priority;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isUserSetupAllowed() {
|
||||||
|
return userSetupAllowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUserSetupAllowed(boolean userSetupAllowed) {
|
||||||
|
this.userSetupAllowed = userSetupAllowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isAutheticatorFlow() {
|
||||||
|
return autheticatorFlow;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAutheticatorFlow(boolean autheticatorFlow) {
|
||||||
|
this.autheticatorFlow = autheticatorFlow;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getParentFlow() {
|
||||||
|
return parentFlow;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setParentFlow(String parentFlow) {
|
||||||
|
this.parentFlow = parentFlow;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
package org.keycloak.models.entities;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
* @version $Revision: 1 $
|
||||||
|
*/
|
||||||
|
public class AuthenticationFlowEntity {
|
||||||
|
protected String id;
|
||||||
|
protected String alias;
|
||||||
|
protected String description;
|
||||||
|
List<AuthenticationExecutionEntity> executions = new ArrayList<AuthenticationExecutionEntity>();
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(String id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAlias() {
|
||||||
|
return alias;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAlias(String alias) {
|
||||||
|
this.alias = alias;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDescription() {
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDescription(String description) {
|
||||||
|
this.description = description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<AuthenticationExecutionEntity> getExecutions() {
|
||||||
|
return executions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setExecutions(List<AuthenticationExecutionEntity> executions) {
|
||||||
|
this.executions = executions;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,46 @@
|
||||||
|
package org.keycloak.models.entities;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
* @version $Revision: 1 $
|
||||||
|
*/
|
||||||
|
public class AuthenticatorEntity {
|
||||||
|
protected String id;
|
||||||
|
protected String alias;
|
||||||
|
protected String providerId;
|
||||||
|
private Map<String, String> config;
|
||||||
|
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(String id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAlias() {
|
||||||
|
return alias;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAlias(String alias) {
|
||||||
|
this.alias = alias;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getProviderId() {
|
||||||
|
return providerId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setProviderId(String providerId) {
|
||||||
|
this.providerId = providerId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, String> getConfig() {
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setConfig(Map<String, String> config) {
|
||||||
|
this.config = config;
|
||||||
|
}
|
||||||
|
}
|
|
@ -74,6 +74,8 @@ public class RealmEntity extends AbstractIdentifiableEntity {
|
||||||
private List<String> supportedLocales = new ArrayList<String>();
|
private List<String> supportedLocales = new ArrayList<String>();
|
||||||
private String defaultLocale;
|
private String defaultLocale;
|
||||||
private List<IdentityProviderMapperEntity> identityProviderMappers = new ArrayList<IdentityProviderMapperEntity>();
|
private List<IdentityProviderMapperEntity> identityProviderMappers = new ArrayList<IdentityProviderMapperEntity>();
|
||||||
|
private List<AuthenticationFlowEntity> authenticationFlows = new ArrayList<>();
|
||||||
|
private List<AuthenticatorEntity> authenticators = new ArrayList<>();
|
||||||
|
|
||||||
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
|
@ -482,6 +484,22 @@ public class RealmEntity extends AbstractIdentifiableEntity {
|
||||||
public void setIdentityProviderMappers(List<IdentityProviderMapperEntity> identityProviderMappers) {
|
public void setIdentityProviderMappers(List<IdentityProviderMapperEntity> identityProviderMappers) {
|
||||||
this.identityProviderMappers = identityProviderMappers;
|
this.identityProviderMappers = identityProviderMappers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<AuthenticationFlowEntity> getAuthenticationFlows() {
|
||||||
|
return authenticationFlows;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAuthenticationFlows(List<AuthenticationFlowEntity> authenticationFlows) {
|
||||||
|
this.authenticationFlows = authenticationFlows;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<AuthenticatorEntity> getAuthenticators() {
|
||||||
|
return authenticators;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAuthenticators(List<AuthenticatorEntity> authenticators) {
|
||||||
|
this.authenticators = authenticators;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,9 @@ package org.keycloak.models.file.adapter;
|
||||||
|
|
||||||
import org.keycloak.connections.file.InMemoryModel;
|
import org.keycloak.connections.file.InMemoryModel;
|
||||||
import org.keycloak.enums.SslRequired;
|
import org.keycloak.enums.SslRequired;
|
||||||
|
import org.keycloak.models.AuthenticationExecutionModel;
|
||||||
|
import org.keycloak.models.AuthenticationFlowModel;
|
||||||
|
import org.keycloak.models.AuthenticatorModel;
|
||||||
import org.keycloak.models.ClientModel;
|
import org.keycloak.models.ClientModel;
|
||||||
import org.keycloak.models.IdentityProviderMapperModel;
|
import org.keycloak.models.IdentityProviderMapperModel;
|
||||||
import org.keycloak.models.IdentityProviderModel;
|
import org.keycloak.models.IdentityProviderModel;
|
||||||
|
@ -31,6 +34,9 @@ import org.keycloak.models.UserFederationMapperModel;
|
||||||
import org.keycloak.models.UserFederationProviderCreationEventImpl;
|
import org.keycloak.models.UserFederationProviderCreationEventImpl;
|
||||||
import org.keycloak.models.UserFederationProviderModel;
|
import org.keycloak.models.UserFederationProviderModel;
|
||||||
import org.keycloak.models.UserModel;
|
import org.keycloak.models.UserModel;
|
||||||
|
import org.keycloak.models.entities.AuthenticationExecutionEntity;
|
||||||
|
import org.keycloak.models.entities.AuthenticationFlowEntity;
|
||||||
|
import org.keycloak.models.entities.AuthenticatorEntity;
|
||||||
import org.keycloak.models.entities.ClientEntity;
|
import org.keycloak.models.entities.ClientEntity;
|
||||||
import org.keycloak.models.entities.IdentityProviderMapperEntity;
|
import org.keycloak.models.entities.IdentityProviderMapperEntity;
|
||||||
import org.keycloak.models.entities.RealmEntity;
|
import org.keycloak.models.entities.RealmEntity;
|
||||||
|
@ -1191,6 +1197,234 @@ public class RealmAdapter implements RealmModel {
|
||||||
return mapping;
|
return mapping;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<AuthenticationFlowModel> getAuthenticationFlows() {
|
||||||
|
List<AuthenticationFlowEntity> flows = realm.getAuthenticationFlows();
|
||||||
|
if (flows.size() == 0) return Collections.EMPTY_LIST;
|
||||||
|
List<AuthenticationFlowModel> models = new LinkedList<>();
|
||||||
|
for (AuthenticationFlowEntity entity : flows) {
|
||||||
|
AuthenticationFlowModel model = entityToModel(entity);
|
||||||
|
models.add(model);
|
||||||
|
}
|
||||||
|
return models;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected AuthenticationFlowModel entityToModel(AuthenticationFlowEntity entity) {
|
||||||
|
AuthenticationFlowModel model = new AuthenticationFlowModel();
|
||||||
|
model.setId(entity.getId());
|
||||||
|
model.setAlias(entity.getAlias());
|
||||||
|
model.setDescription(entity.getDescription());
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AuthenticationFlowModel getAuthenticationFlowById(String id) {
|
||||||
|
for (AuthenticationFlowModel model : getAuthenticationFlows()) {
|
||||||
|
if (model.getId().equals(id)) return model;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected AuthenticationFlowEntity getFlowEntity(String id) {
|
||||||
|
List<AuthenticationFlowEntity> flows = realm.getAuthenticationFlows();
|
||||||
|
for (AuthenticationFlowEntity entity : flows) {
|
||||||
|
if (id.equals(entity.getId())) return entity;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeAuthenticationFlow(AuthenticationFlowModel model) {
|
||||||
|
AuthenticationFlowEntity toDelete = getFlowEntity(model.getId());
|
||||||
|
if (toDelete == null) return;
|
||||||
|
realm.getAuthenticationFlows().remove(toDelete);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateAuthenticationFlow(AuthenticationFlowModel model) {
|
||||||
|
AuthenticationFlowEntity toUpdate = getFlowEntity(model.getId());
|
||||||
|
if (toUpdate == null) return;
|
||||||
|
toUpdate.setAlias(model.getAlias());
|
||||||
|
toUpdate.setDescription(model.getDescription());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AuthenticationFlowModel addAuthenticationFlow(AuthenticationFlowModel model) {
|
||||||
|
AuthenticationFlowEntity entity = new AuthenticationFlowEntity();
|
||||||
|
entity.setId(KeycloakModelUtils.generateId());
|
||||||
|
entity.setAlias(model.getAlias());
|
||||||
|
entity.setDescription(model.getDescription());
|
||||||
|
realm.getAuthenticationFlows().add(entity);
|
||||||
|
model.setId(entity.getId());
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<AuthenticationExecutionModel> getAuthenticationExecutions(String flowId) {
|
||||||
|
AuthenticationFlowEntity flow = getFlowEntity(flowId);
|
||||||
|
if (flow == null) return Collections.EMPTY_LIST;
|
||||||
|
|
||||||
|
List<AuthenticationExecutionEntity> queryResult = flow.getExecutions();
|
||||||
|
List<AuthenticationExecutionModel> executions = new LinkedList<>();
|
||||||
|
for (AuthenticationExecutionEntity entity : queryResult) {
|
||||||
|
AuthenticationExecutionModel model = entityToModel(entity);
|
||||||
|
executions.add(model);
|
||||||
|
}
|
||||||
|
return executions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AuthenticationExecutionModel entityToModel(AuthenticationExecutionEntity entity) {
|
||||||
|
AuthenticationExecutionModel model = new AuthenticationExecutionModel();
|
||||||
|
model.setId(entity.getId());
|
||||||
|
model.setUserSetupAllowed(entity.isUserSetupAllowed());
|
||||||
|
model.setRequirement(entity.getRequirement());
|
||||||
|
model.setPriority(entity.getPriority());
|
||||||
|
model.setAuthenticator(entity.getAuthenticator());
|
||||||
|
model.setParentFlow(entity.getParentFlow());
|
||||||
|
model.setAutheticatorFlow(entity.isAutheticatorFlow());
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AuthenticationExecutionModel getAuthenticationExecutionById(String id) {
|
||||||
|
AuthenticationExecutionEntity execution = getAuthenticationExecutionEntity(id);
|
||||||
|
return entityToModel(execution);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AuthenticationExecutionEntity getAuthenticationExecutionEntity(String id) {
|
||||||
|
List<AuthenticationFlowEntity> flows = realm.getAuthenticationFlows();
|
||||||
|
for (AuthenticationFlowEntity entity : flows) {
|
||||||
|
for (AuthenticationExecutionEntity exe : entity.getExecutions()) {
|
||||||
|
if (exe.getId().equals(id)) {
|
||||||
|
return exe;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AuthenticationExecutionModel addAuthenticatorExecution(AuthenticationExecutionModel model) {
|
||||||
|
AuthenticationExecutionEntity entity = new AuthenticationExecutionEntity();
|
||||||
|
entity.setId(KeycloakModelUtils.generateId());
|
||||||
|
entity.setAuthenticator(model.getAuthenticator());
|
||||||
|
entity.setPriority(model.getPriority());
|
||||||
|
entity.setRequirement(model.getRequirement());
|
||||||
|
entity.setUserSetupAllowed(model.isUserSetupAllowed());
|
||||||
|
entity.setAutheticatorFlow(model.isAutheticatorFlow());
|
||||||
|
AuthenticationFlowEntity flow = getFlowEntity(model.getId());
|
||||||
|
flow.getExecutions().add(entity);
|
||||||
|
model.setId(entity.getId());
|
||||||
|
return model;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateAuthenticatorExecution(AuthenticationExecutionModel model) {
|
||||||
|
AuthenticationExecutionEntity entity = null;
|
||||||
|
AuthenticationFlowEntity flow = getFlowEntity(model.getParentFlow());
|
||||||
|
for (AuthenticationExecutionEntity exe : flow.getExecutions()) {
|
||||||
|
if (exe.getId().equals(model.getId())) {
|
||||||
|
entity = exe;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (entity == null) return;
|
||||||
|
entity.setAutheticatorFlow(model.isAutheticatorFlow());
|
||||||
|
entity.setAuthenticator(model.getAuthenticator());
|
||||||
|
entity.setPriority(model.getPriority());
|
||||||
|
entity.setRequirement(model.getRequirement());
|
||||||
|
entity.setUserSetupAllowed(model.isUserSetupAllowed());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeAuthenticatorExecution(AuthenticationExecutionModel model) {
|
||||||
|
AuthenticationExecutionEntity entity = null;
|
||||||
|
AuthenticationFlowEntity flow = getFlowEntity(model.getParentFlow());
|
||||||
|
for (AuthenticationExecutionEntity exe : flow.getExecutions()) {
|
||||||
|
if (exe.getId().equals(model.getId())) {
|
||||||
|
entity = exe;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (entity == null) return;
|
||||||
|
flow.getExecutions().remove(entity);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<AuthenticatorModel> getAuthenticators() {
|
||||||
|
List<AuthenticatorModel> authenticators = new LinkedList<>();
|
||||||
|
for (AuthenticatorEntity entity : realm.getAuthenticators()) {
|
||||||
|
authenticators.add(entityToModel(entity));
|
||||||
|
}
|
||||||
|
return authenticators;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AuthenticatorModel addAuthenticator(AuthenticatorModel model) {
|
||||||
|
AuthenticatorEntity auth = new AuthenticatorEntity();
|
||||||
|
auth.setId(KeycloakModelUtils.generateId());
|
||||||
|
auth.setAlias(model.getAlias());
|
||||||
|
auth.setProviderId(model.getProviderId());
|
||||||
|
auth.setConfig(model.getConfig());
|
||||||
|
realm.getAuthenticators().add(auth);
|
||||||
|
model.setId(auth.getId());
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeAuthenticator(AuthenticatorModel model) {
|
||||||
|
AuthenticatorEntity entity = getAuthenticatorEntity(model.getId());
|
||||||
|
if (entity == null) return;
|
||||||
|
realm.getAuthenticators().remove(entity);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AuthenticatorModel getAuthenticatorById(String id) {
|
||||||
|
AuthenticatorEntity entity = getAuthenticatorEntity(id);
|
||||||
|
if (entity == null) return null;
|
||||||
|
return entityToModel(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AuthenticatorEntity getAuthenticatorEntity(String id) {
|
||||||
|
AuthenticatorEntity entity = null;
|
||||||
|
for (AuthenticatorEntity auth : realm.getAuthenticators()) {
|
||||||
|
if (auth.getId().equals(id)) {
|
||||||
|
entity = auth;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AuthenticatorModel entityToModel(AuthenticatorEntity entity) {
|
||||||
|
AuthenticatorModel model = new AuthenticatorModel();
|
||||||
|
model.setId(entity.getId());
|
||||||
|
model.setProviderId(entity.getProviderId());
|
||||||
|
model.setAlias(entity.getAlias());
|
||||||
|
Map<String, String> config = new HashMap<>();
|
||||||
|
if (entity.getConfig() != null) config.putAll(entity.getConfig());
|
||||||
|
model.setConfig(config);
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateAuthenticator(AuthenticatorModel model) {
|
||||||
|
AuthenticatorEntity entity = getAuthenticatorEntity(model.getId());
|
||||||
|
if (entity == null) return;
|
||||||
|
entity.setAlias(model.getAlias());
|
||||||
|
entity.setProviderId(model.getProviderId());
|
||||||
|
if (entity.getConfig() == null) {
|
||||||
|
entity.setConfig(model.getConfig());
|
||||||
|
} else {
|
||||||
|
entity.getConfig().clear();
|
||||||
|
entity.getConfig().putAll(model.getConfig());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<UserFederationMapperModel> getUserFederationMappers() {
|
public Set<UserFederationMapperModel> getUserFederationMappers() {
|
||||||
Set<UserFederationMapperModel> mappers = new HashSet<UserFederationMapperModel>();
|
Set<UserFederationMapperModel> mappers = new HashSet<UserFederationMapperModel>();
|
||||||
|
|
|
@ -2,6 +2,9 @@ package org.keycloak.models.cache;
|
||||||
|
|
||||||
import org.keycloak.Config;
|
import org.keycloak.Config;
|
||||||
import org.keycloak.enums.SslRequired;
|
import org.keycloak.enums.SslRequired;
|
||||||
|
import org.keycloak.models.AuthenticationExecutionModel;
|
||||||
|
import org.keycloak.models.AuthenticationFlowModel;
|
||||||
|
import org.keycloak.models.AuthenticatorModel;
|
||||||
import org.keycloak.models.ClientModel;
|
import org.keycloak.models.ClientModel;
|
||||||
import org.keycloak.models.IdentityProviderMapperModel;
|
import org.keycloak.models.IdentityProviderMapperModel;
|
||||||
import org.keycloak.models.IdentityProviderModel;
|
import org.keycloak.models.IdentityProviderModel;
|
||||||
|
@ -1015,4 +1018,104 @@ public class RealmAdapter implements RealmModel {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<AuthenticationFlowModel> getAuthenticationFlows() {
|
||||||
|
if (updated != null) return updated.getAuthenticationFlows();
|
||||||
|
List<AuthenticationFlowModel> models = new ArrayList<>();
|
||||||
|
models.addAll(cached.getAuthenticationFlows().values());
|
||||||
|
return models;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AuthenticationFlowModel addAuthenticationFlow(AuthenticationFlowModel model) {
|
||||||
|
getDelegateForUpdate();
|
||||||
|
return updated.addAuthenticationFlow(model);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AuthenticationFlowModel getAuthenticationFlowById(String id) {
|
||||||
|
if (updated != null) return updated.getAuthenticationFlowById(id);
|
||||||
|
return cached.getAuthenticationFlows().get(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeAuthenticationFlow(AuthenticationFlowModel model) {
|
||||||
|
getDelegateForUpdate();
|
||||||
|
updated.removeAuthenticationFlow(model);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateAuthenticationFlow(AuthenticationFlowModel model) {
|
||||||
|
getDelegateForUpdate();
|
||||||
|
updated.updateAuthenticationFlow(model);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<AuthenticationExecutionModel> getAuthenticationExecutions(String flowId) {
|
||||||
|
if (updated != null) return updated.getAuthenticationExecutions(flowId);
|
||||||
|
List<AuthenticationExecutionModel> models = new ArrayList<>();
|
||||||
|
return cached.getAuthenticationExecutions().get(flowId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AuthenticationExecutionModel getAuthenticationExecutionById(String id) {
|
||||||
|
if (updated != null) return updated.getAuthenticationExecutionById(id);
|
||||||
|
return cached.getExecutionsById().get(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AuthenticationExecutionModel addAuthenticatorExecution(AuthenticationExecutionModel model) {
|
||||||
|
getDelegateForUpdate();
|
||||||
|
return updated.addAuthenticatorExecution(model);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateAuthenticatorExecution(AuthenticationExecutionModel model) {
|
||||||
|
getDelegateForUpdate();
|
||||||
|
updated.updateAuthenticatorExecution(model);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeAuthenticatorExecution(AuthenticationExecutionModel model) {
|
||||||
|
getDelegateForUpdate();
|
||||||
|
updated.removeAuthenticatorExecution(model);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<AuthenticatorModel> getAuthenticators() {
|
||||||
|
if (updated != null) return updated.getAuthenticators();
|
||||||
|
List<AuthenticatorModel> models = new ArrayList<>();
|
||||||
|
models.addAll(cached.getAuthenticators().values());
|
||||||
|
return models;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AuthenticatorModel addAuthenticator(AuthenticatorModel model) {
|
||||||
|
getDelegateForUpdate();
|
||||||
|
return updated.addAuthenticator(model);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateAuthenticator(AuthenticatorModel model) {
|
||||||
|
getDelegateForUpdate();
|
||||||
|
updated.updateAuthenticator(model);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeAuthenticator(AuthenticatorModel model) {
|
||||||
|
getDelegateForUpdate();
|
||||||
|
updated.removeAuthenticator(model);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AuthenticatorModel getAuthenticatorById(String id) {
|
||||||
|
if (updated != null) return updated.getAuthenticatorById(id);
|
||||||
|
return cached.getAuthenticators().get(id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
package org.keycloak.models.cache.entities;
|
package org.keycloak.models.cache.entities;
|
||||||
|
|
||||||
import org.keycloak.enums.SslRequired;
|
import org.keycloak.enums.SslRequired;
|
||||||
|
import org.keycloak.models.AuthenticationExecutionModel;
|
||||||
|
import org.keycloak.models.AuthenticationFlowModel;
|
||||||
|
import org.keycloak.models.AuthenticatorModel;
|
||||||
import org.keycloak.models.ClientModel;
|
import org.keycloak.models.ClientModel;
|
||||||
import org.keycloak.models.IdentityProviderMapperModel;
|
import org.keycloak.models.IdentityProviderMapperModel;
|
||||||
import org.keycloak.models.IdentityProviderModel;
|
import org.keycloak.models.IdentityProviderModel;
|
||||||
|
@ -76,6 +79,10 @@ public class CachedRealm {
|
||||||
|
|
||||||
private Map<String, String> browserSecurityHeaders = new HashMap<String, String>();
|
private Map<String, String> browserSecurityHeaders = new HashMap<String, String>();
|
||||||
private Map<String, String> smtpConfig = new HashMap<String, String>();
|
private Map<String, String> smtpConfig = new HashMap<String, String>();
|
||||||
|
private Map<String, AuthenticationFlowModel> authenticationFlows = new HashMap<>();
|
||||||
|
private Map<String, AuthenticatorModel> authenticators = new HashMap<>();
|
||||||
|
private MultivaluedHashMap<String, AuthenticationExecutionModel> authenticationExecutions = new MultivaluedHashMap<>();
|
||||||
|
private Map<String, AuthenticationExecutionModel> executionsById = new HashMap<>();
|
||||||
|
|
||||||
private boolean eventsEnabled;
|
private boolean eventsEnabled;
|
||||||
private long eventsExpiration;
|
private long eventsExpiration;
|
||||||
|
@ -183,6 +190,16 @@ public class CachedRealm {
|
||||||
internationalizationEnabled = model.isInternationalizationEnabled();
|
internationalizationEnabled = model.isInternationalizationEnabled();
|
||||||
supportedLocales.addAll(model.getSupportedLocales());
|
supportedLocales.addAll(model.getSupportedLocales());
|
||||||
defaultLocale = model.getDefaultLocale();
|
defaultLocale = model.getDefaultLocale();
|
||||||
|
for (AuthenticationFlowModel flow : model.getAuthenticationFlows()) {
|
||||||
|
authenticationFlows.put(flow.getId(), flow);
|
||||||
|
for (AuthenticationExecutionModel execution : model.getAuthenticationExecutions(flow.getId())) {
|
||||||
|
authenticationExecutions.add(flow.getId(), execution);
|
||||||
|
executionsById.put(execution.getId(), execution);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (AuthenticatorModel authenticator : model.getAuthenticators()) {
|
||||||
|
authenticators.put(authenticator.getId(), authenticator);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -405,4 +422,20 @@ public class CachedRealm {
|
||||||
public MultivaluedHashMap<String, IdentityProviderMapperModel> getIdentityProviderMappers() {
|
public MultivaluedHashMap<String, IdentityProviderMapperModel> getIdentityProviderMappers() {
|
||||||
return identityProviderMappers;
|
return identityProviderMappers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Map<String, AuthenticationFlowModel> getAuthenticationFlows() {
|
||||||
|
return authenticationFlows;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, AuthenticatorModel> getAuthenticators() {
|
||||||
|
return authenticators;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MultivaluedHashMap<String, AuthenticationExecutionModel> getAuthenticationExecutions() {
|
||||||
|
return authenticationExecutions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, AuthenticationExecutionModel> getExecutionsById() {
|
||||||
|
return executionsById;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
package org.keycloak.models.jpa;
|
package org.keycloak.models.jpa;
|
||||||
|
|
||||||
import org.keycloak.enums.SslRequired;
|
import org.keycloak.enums.SslRequired;
|
||||||
|
import org.keycloak.models.AuthenticationExecutionModel;
|
||||||
|
import org.keycloak.models.AuthenticationFlowModel;
|
||||||
|
import org.keycloak.models.AuthenticatorModel;
|
||||||
import org.keycloak.models.ClientModel;
|
import org.keycloak.models.ClientModel;
|
||||||
import org.keycloak.models.IdentityProviderMapperModel;
|
import org.keycloak.models.IdentityProviderMapperModel;
|
||||||
import org.keycloak.models.IdentityProviderModel;
|
import org.keycloak.models.IdentityProviderModel;
|
||||||
|
@ -13,6 +16,9 @@ import org.keycloak.models.RoleModel;
|
||||||
import org.keycloak.models.UserFederationMapperModel;
|
import org.keycloak.models.UserFederationMapperModel;
|
||||||
import org.keycloak.models.UserFederationProviderCreationEventImpl;
|
import org.keycloak.models.UserFederationProviderCreationEventImpl;
|
||||||
import org.keycloak.models.UserFederationProviderModel;
|
import org.keycloak.models.UserFederationProviderModel;
|
||||||
|
import org.keycloak.models.jpa.entities.AuthenticationExecutionEntity;
|
||||||
|
import org.keycloak.models.jpa.entities.AuthenticationFlowEntity;
|
||||||
|
import org.keycloak.models.jpa.entities.AuthenticatorEntity;
|
||||||
import org.keycloak.models.jpa.entities.ClientEntity;
|
import org.keycloak.models.jpa.entities.ClientEntity;
|
||||||
import org.keycloak.models.jpa.entities.IdentityProviderEntity;
|
import org.keycloak.models.jpa.entities.IdentityProviderEntity;
|
||||||
import org.keycloak.models.jpa.entities.IdentityProviderMapperEntity;
|
import org.keycloak.models.jpa.entities.IdentityProviderMapperEntity;
|
||||||
|
@ -1486,4 +1492,207 @@ public class RealmAdapter implements RealmModel {
|
||||||
return mapper;
|
return mapper;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<AuthenticationFlowModel> getAuthenticationFlows() {
|
||||||
|
TypedQuery<AuthenticationFlowEntity> query = em.createNamedQuery("getAuthenticationFlowsByRealm", AuthenticationFlowEntity.class);
|
||||||
|
query.setParameter("realm", realm);
|
||||||
|
List<AuthenticationFlowEntity> flows = query.getResultList();
|
||||||
|
if (flows.size() == 0) return Collections.EMPTY_LIST;
|
||||||
|
List<AuthenticationFlowModel> models = new LinkedList<>();
|
||||||
|
for (AuthenticationFlowEntity entity : flows) {
|
||||||
|
AuthenticationFlowModel model = entityToModel(entity);
|
||||||
|
models.add(model);
|
||||||
|
}
|
||||||
|
return models;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected AuthenticationFlowModel entityToModel(AuthenticationFlowEntity entity) {
|
||||||
|
AuthenticationFlowModel model = new AuthenticationFlowModel();
|
||||||
|
model.setId(entity.getId());
|
||||||
|
model.setAlias(entity.getAlias());
|
||||||
|
model.setDescription(entity.getDescription());
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AuthenticationFlowModel getAuthenticationFlowById(String id) {
|
||||||
|
AuthenticationFlowEntity entity = em.find(AuthenticationFlowEntity.class, id);
|
||||||
|
if (entity == null) return null;
|
||||||
|
return entityToModel(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeAuthenticationFlow(AuthenticationFlowModel model) {
|
||||||
|
AuthenticationFlowEntity entity = em.find(AuthenticationFlowEntity.class, model.getId());
|
||||||
|
if (entity == null) return;
|
||||||
|
em.remove(entity);
|
||||||
|
em.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateAuthenticationFlow(AuthenticationFlowModel model) {
|
||||||
|
AuthenticationFlowEntity entity = em.find(AuthenticationFlowEntity.class, model.getId());
|
||||||
|
if (entity == null) return;
|
||||||
|
entity.setAlias(model.getAlias());
|
||||||
|
entity.setDescription(model.getDescription());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AuthenticationFlowModel addAuthenticationFlow(AuthenticationFlowModel model) {
|
||||||
|
AuthenticationFlowEntity entity = new AuthenticationFlowEntity();
|
||||||
|
entity.setId(KeycloakModelUtils.generateId());
|
||||||
|
entity.setAlias(model.getAlias());
|
||||||
|
entity.setDescription(model.getDescription());
|
||||||
|
entity.setRealm(realm);
|
||||||
|
realm.getAuthenticationFlows().add(entity);
|
||||||
|
em.persist(entity);
|
||||||
|
em.flush();
|
||||||
|
model.setId(entity.getId());
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<AuthenticationExecutionModel> getAuthenticationExecutions(String flowId) {
|
||||||
|
TypedQuery<AuthenticationExecutionEntity> query = em.createNamedQuery("getAuthenticationExecutionsByFlow", AuthenticationExecutionEntity.class);
|
||||||
|
AuthenticationFlowEntity flow = em.getReference(AuthenticationFlowEntity.class, flowId);
|
||||||
|
query.setParameter("realm", realm);
|
||||||
|
query.setParameter("flow", flow);
|
||||||
|
List<AuthenticationExecutionEntity> queryResult = query.getResultList();
|
||||||
|
List<AuthenticationExecutionModel> executions = new LinkedList<>();
|
||||||
|
for (AuthenticationExecutionEntity entity : queryResult) {
|
||||||
|
AuthenticationExecutionModel model = entityToModel(entity);
|
||||||
|
executions.add(model);
|
||||||
|
}
|
||||||
|
return executions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AuthenticationExecutionModel entityToModel(AuthenticationExecutionEntity entity) {
|
||||||
|
AuthenticationExecutionModel model = new AuthenticationExecutionModel();
|
||||||
|
model.setId(entity.getId());
|
||||||
|
model.setUserSetupAllowed(entity.isUserSetupAllowed());
|
||||||
|
model.setRequirement(entity.getRequirement());
|
||||||
|
model.setPriority(entity.getPriority());
|
||||||
|
model.setAuthenticator(entity.getAuthenticator());
|
||||||
|
model.setParentFlow(entity.getFlow().getId());
|
||||||
|
model.setAutheticatorFlow(entity.isAutheticatorFlow());
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AuthenticationExecutionModel getAuthenticationExecutionById(String id) {
|
||||||
|
AuthenticationExecutionEntity entity = em.find(AuthenticationExecutionEntity.class, id);
|
||||||
|
if (entity == null) return null;
|
||||||
|
return entityToModel(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AuthenticationExecutionModel addAuthenticatorExecution(AuthenticationExecutionModel model) {
|
||||||
|
AuthenticationExecutionEntity entity = new AuthenticationExecutionEntity();
|
||||||
|
entity.setId(KeycloakModelUtils.generateId());
|
||||||
|
entity.setAuthenticator(model.getAuthenticator());
|
||||||
|
entity.setPriority(model.getPriority());
|
||||||
|
entity.setRequirement(model.getRequirement());
|
||||||
|
AuthenticationFlowEntity flow = em.find(AuthenticationFlowEntity.class, model.getParentFlow());
|
||||||
|
entity.setFlow(flow);
|
||||||
|
flow.getExecutions().add(entity);
|
||||||
|
entity.setRealm(realm);
|
||||||
|
entity.setUserSetupAllowed(model.isUserSetupAllowed());
|
||||||
|
entity.setAutheticatorFlow(model.isAutheticatorFlow());
|
||||||
|
em.persist(entity);
|
||||||
|
em.flush();
|
||||||
|
model.setId(entity.getId());
|
||||||
|
return model;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateAuthenticatorExecution(AuthenticationExecutionModel model) {
|
||||||
|
AuthenticationExecutionEntity entity = em.find(AuthenticationExecutionEntity.class, model.getId());
|
||||||
|
if (entity == null) return;
|
||||||
|
entity.setAutheticatorFlow(model.isAutheticatorFlow());
|
||||||
|
entity.setAuthenticator(model.getAuthenticator());
|
||||||
|
entity.setPriority(model.getPriority());
|
||||||
|
entity.setRequirement(model.getRequirement());
|
||||||
|
entity.setUserSetupAllowed(model.isUserSetupAllowed());
|
||||||
|
em.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeAuthenticatorExecution(AuthenticationExecutionModel model) {
|
||||||
|
AuthenticationExecutionEntity entity = em.find(AuthenticationExecutionEntity.class, model.getId());
|
||||||
|
if (entity == null) return;
|
||||||
|
em.remove(entity);
|
||||||
|
em.flush();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AuthenticatorModel addAuthenticator(AuthenticatorModel model) {
|
||||||
|
AuthenticatorEntity auth = new AuthenticatorEntity();
|
||||||
|
auth.setId(KeycloakModelUtils.generateId());
|
||||||
|
auth.setAlias(model.getAlias());
|
||||||
|
auth.setRealm(realm);
|
||||||
|
auth.setProviderId(model.getProviderId());
|
||||||
|
auth.setConfig(model.getConfig());
|
||||||
|
realm.getAuthenticators().add(auth);
|
||||||
|
em.persist(auth);
|
||||||
|
em.flush();
|
||||||
|
model.setId(auth.getId());
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeAuthenticator(AuthenticatorModel model) {
|
||||||
|
AuthenticatorEntity entity = em.find(AuthenticatorEntity.class, model.getId());
|
||||||
|
if (entity == null) return;
|
||||||
|
em.remove(entity);
|
||||||
|
em.flush();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AuthenticatorModel getAuthenticatorById(String id) {
|
||||||
|
AuthenticatorEntity entity = em.find(AuthenticatorEntity.class, id);
|
||||||
|
if (entity == null) return null;
|
||||||
|
return entityToModel(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AuthenticatorModel entityToModel(AuthenticatorEntity entity) {
|
||||||
|
AuthenticatorModel model = new AuthenticatorModel();
|
||||||
|
model.setId(entity.getId());
|
||||||
|
model.setProviderId(entity.getProviderId());
|
||||||
|
model.setAlias(entity.getAlias());
|
||||||
|
Map<String, String> config = new HashMap<>();
|
||||||
|
if (entity.getConfig() != null) config.putAll(entity.getConfig());
|
||||||
|
model.setConfig(config);
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateAuthenticator(AuthenticatorModel model) {
|
||||||
|
AuthenticatorEntity entity = em.find(AuthenticatorEntity.class, model.getId());
|
||||||
|
if (entity == null) return;
|
||||||
|
entity.setAlias(model.getAlias());
|
||||||
|
entity.setProviderId(model.getProviderId());
|
||||||
|
if (entity.getConfig() == null) {
|
||||||
|
entity.setConfig(model.getConfig());
|
||||||
|
} else {
|
||||||
|
entity.getConfig().clear();
|
||||||
|
entity.getConfig().putAll(model.getConfig());
|
||||||
|
}
|
||||||
|
em.flush();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<AuthenticatorModel> getAuthenticators() {
|
||||||
|
List<AuthenticatorModel> authenticators = new LinkedList<>();
|
||||||
|
for (AuthenticatorEntity entity : realm.getAuthenticators()) {
|
||||||
|
authenticators.add(entityToModel(entity));
|
||||||
|
}
|
||||||
|
return authenticators;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -0,0 +1,117 @@
|
||||||
|
package org.keycloak.models.jpa.entities;
|
||||||
|
|
||||||
|
import org.keycloak.models.AuthenticationExecutionModel;
|
||||||
|
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.FetchType;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.JoinColumn;
|
||||||
|
import javax.persistence.ManyToOne;
|
||||||
|
import javax.persistence.NamedQueries;
|
||||||
|
import javax.persistence.NamedQuery;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
* @version $Revision: 1 $
|
||||||
|
*/
|
||||||
|
@Table(name="AUTHENTICATION_EXECUTION")
|
||||||
|
@Entity
|
||||||
|
@NamedQueries({
|
||||||
|
@NamedQuery(name="getAuthenticationExecutionsByFlow", query="select authenticator from AuthenticationExecutionEntity authenticator where authenticator.realm = :realm and authenticator.flow = :flow"),
|
||||||
|
@NamedQuery(name="deleteAuthenticationExecutionsByRealm", query="delete from AuthenticationExecutionEntity authenticator where authenticator.realm = :realm"),
|
||||||
|
@NamedQuery(name="deleteAuthenticationExecutionsByRealmAndFlow", query="delete from AuthenticationExecutionEntity authenticator where authenticator.realm = :realm and authenticator.flow = :flow"),
|
||||||
|
})
|
||||||
|
public class AuthenticationExecutionEntity {
|
||||||
|
@Id
|
||||||
|
@Column(name="ID", length = 36)
|
||||||
|
protected String id;
|
||||||
|
|
||||||
|
@ManyToOne(fetch = FetchType.LAZY)
|
||||||
|
@JoinColumn(name = "REALM_ID")
|
||||||
|
protected RealmEntity realm;
|
||||||
|
|
||||||
|
@ManyToOne(fetch = FetchType.LAZY)
|
||||||
|
@JoinColumn(name = "FLOW_ID")
|
||||||
|
protected AuthenticationFlowEntity flow;
|
||||||
|
|
||||||
|
@Column(name="AUTHENTICATOR")
|
||||||
|
protected String authenticator;
|
||||||
|
|
||||||
|
@Column(name="REQUIREMENT")
|
||||||
|
protected AuthenticationExecutionModel.Requirement requirement;
|
||||||
|
|
||||||
|
@Column(name="PRIORITY")
|
||||||
|
protected int priority;
|
||||||
|
|
||||||
|
@Column(name="USER_SETUP_ALLOWED")
|
||||||
|
private boolean userSetupAllowed;
|
||||||
|
|
||||||
|
@Column(name="AUTHENTICATOR_FLOW")
|
||||||
|
private boolean autheticatorFlow;
|
||||||
|
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(String id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RealmEntity getRealm() {
|
||||||
|
return realm;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRealm(RealmEntity realm) {
|
||||||
|
this.realm = realm;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAuthenticator() {
|
||||||
|
return authenticator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAuthenticator(String authenticator) {
|
||||||
|
this.authenticator = authenticator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AuthenticationExecutionModel.Requirement getRequirement() {
|
||||||
|
return requirement;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRequirement(AuthenticationExecutionModel.Requirement requirement) {
|
||||||
|
this.requirement = requirement;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getPriority() {
|
||||||
|
return priority;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPriority(int priority) {
|
||||||
|
this.priority = priority;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isUserSetupAllowed() {
|
||||||
|
return userSetupAllowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUserSetupAllowed(boolean userSetupAllowed) {
|
||||||
|
this.userSetupAllowed = userSetupAllowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isAutheticatorFlow() {
|
||||||
|
return autheticatorFlow;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAutheticatorFlow(boolean autheticatorFlow) {
|
||||||
|
this.autheticatorFlow = autheticatorFlow;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AuthenticationFlowEntity getFlow() {
|
||||||
|
return flow;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFlow(AuthenticationFlowEntity flow) {
|
||||||
|
this.flow = flow;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,89 @@
|
||||||
|
package org.keycloak.models.jpa.entities;
|
||||||
|
|
||||||
|
import org.keycloak.models.AuthenticatorModel;
|
||||||
|
|
||||||
|
import javax.persistence.CascadeType;
|
||||||
|
import javax.persistence.CollectionTable;
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.ElementCollection;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.FetchType;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.JoinColumn;
|
||||||
|
import javax.persistence.ManyToOne;
|
||||||
|
import javax.persistence.MapKeyColumn;
|
||||||
|
import javax.persistence.NamedQueries;
|
||||||
|
import javax.persistence.NamedQuery;
|
||||||
|
import javax.persistence.OneToMany;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
* @version $Revision: 1 $
|
||||||
|
*/
|
||||||
|
@Table(name="AUTHENTICATION_FLOW")
|
||||||
|
@Entity
|
||||||
|
@NamedQueries({
|
||||||
|
@NamedQuery(name="getAuthenticationFlowsByRealm", query="select flow from AuthenticationFlowEntity flow where flow.realm = :realm"),
|
||||||
|
@NamedQuery(name="deleteAuthenticationFlowByRealm", query="delete from AuthenticationFlowEntity flow where flow.realm = :realm")
|
||||||
|
})
|
||||||
|
public class AuthenticationFlowEntity {
|
||||||
|
@Id
|
||||||
|
@Column(name="ID", length = 36)
|
||||||
|
protected String id;
|
||||||
|
|
||||||
|
@ManyToOne(fetch = FetchType.LAZY)
|
||||||
|
@JoinColumn(name = "REALM_ID")
|
||||||
|
protected RealmEntity realm;
|
||||||
|
|
||||||
|
@Column(name="ALIAS")
|
||||||
|
protected String alias;
|
||||||
|
|
||||||
|
@Column(name="DESCRIPTION")
|
||||||
|
protected String description;
|
||||||
|
|
||||||
|
@OneToMany(fetch = FetchType.LAZY, cascade ={CascadeType.REMOVE}, orphanRemoval = true, mappedBy = "flow")
|
||||||
|
Collection<AuthenticationExecutionEntity> executions = new ArrayList<AuthenticationExecutionEntity>();
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(String id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RealmEntity getRealm() {
|
||||||
|
return realm;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRealm(RealmEntity realm) {
|
||||||
|
this.realm = realm;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAlias() {
|
||||||
|
return alias;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAlias(String alias) {
|
||||||
|
this.alias = alias;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDescription() {
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDescription(String description) {
|
||||||
|
this.description = description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<AuthenticationExecutionEntity> getExecutions() {
|
||||||
|
return executions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setExecutions(Collection<AuthenticationExecutionEntity> executions) {
|
||||||
|
this.executions = executions;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,89 @@
|
||||||
|
package org.keycloak.models.jpa.entities;
|
||||||
|
|
||||||
|
import org.keycloak.models.AuthenticatorModel;
|
||||||
|
|
||||||
|
import javax.persistence.CollectionTable;
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.ElementCollection;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.FetchType;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.IdClass;
|
||||||
|
import javax.persistence.JoinColumn;
|
||||||
|
import javax.persistence.ManyToOne;
|
||||||
|
import javax.persistence.MapKeyColumn;
|
||||||
|
import javax.persistence.NamedQueries;
|
||||||
|
import javax.persistence.NamedQuery;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
* @version $Revision: 1 $
|
||||||
|
*/
|
||||||
|
@Table(name="AUTHENTICATOR")
|
||||||
|
@Entity
|
||||||
|
@NamedQueries({
|
||||||
|
@NamedQuery(name="deleteAuthenticatorsByRealm", query="delete from AuthenticatorEntity authenticator where authenticator.realm = :realm"),})
|
||||||
|
public class AuthenticatorEntity {
|
||||||
|
@Id
|
||||||
|
@Column(name="ID", length = 36)
|
||||||
|
protected String id;
|
||||||
|
|
||||||
|
@Column(name="ALIAS")
|
||||||
|
protected String alias;
|
||||||
|
|
||||||
|
@ManyToOne(fetch = FetchType.LAZY)
|
||||||
|
@JoinColumn(name = "REALM_ID")
|
||||||
|
protected RealmEntity realm;
|
||||||
|
|
||||||
|
@Column(name="PROVIDER_ID")
|
||||||
|
protected String providerId;
|
||||||
|
|
||||||
|
@ElementCollection
|
||||||
|
@MapKeyColumn(name="NAME")
|
||||||
|
@Column(name="VALUE")
|
||||||
|
@CollectionTable(name="AUTHENTICATOR_CONFIG", joinColumns={ @JoinColumn(name="AUTHENTICATOR_ID") })
|
||||||
|
private Map<String, String> config;
|
||||||
|
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(String id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAlias() {
|
||||||
|
return alias;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAlias(String alias) {
|
||||||
|
this.alias = alias;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getProviderId() {
|
||||||
|
return providerId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setProviderId(String providerId) {
|
||||||
|
this.providerId = providerId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RealmEntity getRealm() {
|
||||||
|
return realm;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRealm(RealmEntity realm) {
|
||||||
|
this.realm = realm;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, String> getConfig() {
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setConfig(Map<String, String> config) {
|
||||||
|
this.config = config;
|
||||||
|
}
|
||||||
|
}
|
|
@ -154,6 +154,12 @@ public class RealmEntity {
|
||||||
@OneToMany(cascade ={CascadeType.REMOVE}, orphanRemoval = true, mappedBy = "realm")
|
@OneToMany(cascade ={CascadeType.REMOVE}, orphanRemoval = true, mappedBy = "realm")
|
||||||
Collection<IdentityProviderMapperEntity> identityProviderMappers = new ArrayList<IdentityProviderMapperEntity>();
|
Collection<IdentityProviderMapperEntity> identityProviderMappers = new ArrayList<IdentityProviderMapperEntity>();
|
||||||
|
|
||||||
|
@OneToMany(cascade ={CascadeType.REMOVE}, orphanRemoval = true, mappedBy = "realm")
|
||||||
|
Collection<AuthenticatorEntity> authenticators = new ArrayList<>();
|
||||||
|
|
||||||
|
@OneToMany(cascade ={CascadeType.REMOVE}, orphanRemoval = true, mappedBy = "realm")
|
||||||
|
Collection<AuthenticationFlowEntity> authenticationFlows = new ArrayList<>();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Column(name="INTERNATIONALIZATION_ENABLED")
|
@Column(name="INTERNATIONALIZATION_ENABLED")
|
||||||
|
@ -546,5 +552,21 @@ public class RealmEntity {
|
||||||
public void setIdentityProviderMappers(Collection<IdentityProviderMapperEntity> identityProviderMappers) {
|
public void setIdentityProviderMappers(Collection<IdentityProviderMapperEntity> identityProviderMappers) {
|
||||||
this.identityProviderMappers = identityProviderMappers;
|
this.identityProviderMappers = identityProviderMappers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Collection<AuthenticatorEntity> getAuthenticators() {
|
||||||
|
return authenticators;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAuthenticators(Collection<AuthenticatorEntity> authenticators) {
|
||||||
|
this.authenticators = authenticators;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<AuthenticationFlowEntity> getAuthenticationFlows() {
|
||||||
|
return authenticationFlows;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAuthenticationFlows(Collection<AuthenticationFlowEntity> authenticationFlows) {
|
||||||
|
this.authenticationFlows = authenticationFlows;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,9 @@ import com.mongodb.QueryBuilder;
|
||||||
|
|
||||||
import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
|
import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
|
||||||
import org.keycloak.enums.SslRequired;
|
import org.keycloak.enums.SslRequired;
|
||||||
|
import org.keycloak.models.AuthenticationExecutionModel;
|
||||||
|
import org.keycloak.models.AuthenticationFlowModel;
|
||||||
|
import org.keycloak.models.AuthenticatorModel;
|
||||||
import org.keycloak.models.ClientModel;
|
import org.keycloak.models.ClientModel;
|
||||||
import org.keycloak.models.IdentityProviderMapperModel;
|
import org.keycloak.models.IdentityProviderMapperModel;
|
||||||
import org.keycloak.models.IdentityProviderModel;
|
import org.keycloak.models.IdentityProviderModel;
|
||||||
|
@ -18,6 +21,9 @@ import org.keycloak.models.RoleModel;
|
||||||
import org.keycloak.models.UserFederationMapperModel;
|
import org.keycloak.models.UserFederationMapperModel;
|
||||||
import org.keycloak.models.UserFederationProviderCreationEventImpl;
|
import org.keycloak.models.UserFederationProviderCreationEventImpl;
|
||||||
import org.keycloak.models.UserFederationProviderModel;
|
import org.keycloak.models.UserFederationProviderModel;
|
||||||
|
import org.keycloak.models.entities.AuthenticationExecutionEntity;
|
||||||
|
import org.keycloak.models.entities.AuthenticationFlowEntity;
|
||||||
|
import org.keycloak.models.entities.AuthenticatorEntity;
|
||||||
import org.keycloak.models.entities.IdentityProviderEntity;
|
import org.keycloak.models.entities.IdentityProviderEntity;
|
||||||
import org.keycloak.models.entities.IdentityProviderMapperEntity;
|
import org.keycloak.models.entities.IdentityProviderMapperEntity;
|
||||||
import org.keycloak.models.entities.RequiredCredentialEntity;
|
import org.keycloak.models.entities.RequiredCredentialEntity;
|
||||||
|
@ -1178,7 +1184,6 @@ public class RealmAdapter extends AbstractMongoAdapter<MongoRealmEntity> impleme
|
||||||
this.realm.getIdentityProviderMappers().remove(toDelete);
|
this.realm.getIdentityProviderMappers().remove(toDelete);
|
||||||
updateMongoEntity();
|
updateMongoEntity();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -1222,6 +1227,243 @@ public class RealmAdapter extends AbstractMongoAdapter<MongoRealmEntity> impleme
|
||||||
return mapping;
|
return mapping;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<AuthenticationFlowModel> getAuthenticationFlows() {
|
||||||
|
List<AuthenticationFlowEntity> flows = getMongoEntity().getAuthenticationFlows();
|
||||||
|
if (flows.size() == 0) return Collections.EMPTY_LIST;
|
||||||
|
List<AuthenticationFlowModel> models = new LinkedList<>();
|
||||||
|
for (AuthenticationFlowEntity entity : flows) {
|
||||||
|
AuthenticationFlowModel model = entityToModel(entity);
|
||||||
|
models.add(model);
|
||||||
|
}
|
||||||
|
return models;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected AuthenticationFlowModel entityToModel(AuthenticationFlowEntity entity) {
|
||||||
|
AuthenticationFlowModel model = new AuthenticationFlowModel();
|
||||||
|
model.setId(entity.getId());
|
||||||
|
model.setAlias(entity.getAlias());
|
||||||
|
model.setDescription(entity.getDescription());
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AuthenticationFlowModel getAuthenticationFlowById(String id) {
|
||||||
|
for (AuthenticationFlowModel model : getAuthenticationFlows()) {
|
||||||
|
if (model.getId().equals(id)) return model;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected AuthenticationFlowEntity getFlowEntity(String id) {
|
||||||
|
List<AuthenticationFlowEntity> flows = getMongoEntity().getAuthenticationFlows();
|
||||||
|
for (AuthenticationFlowEntity entity : flows) {
|
||||||
|
if (id.equals(entity.getId())) return entity;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeAuthenticationFlow(AuthenticationFlowModel model) {
|
||||||
|
AuthenticationFlowEntity toDelete = getFlowEntity(model.getId());
|
||||||
|
if (toDelete == null) return;
|
||||||
|
getMongoEntity().getAuthenticationFlows().remove(toDelete);
|
||||||
|
updateMongoEntity();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateAuthenticationFlow(AuthenticationFlowModel model) {
|
||||||
|
List<AuthenticationFlowEntity> flows = getMongoEntity().getAuthenticationFlows();
|
||||||
|
AuthenticationFlowEntity toUpdate = getFlowEntity(model.getId());;
|
||||||
|
if (toUpdate == null) return;
|
||||||
|
toUpdate.setAlias(model.getAlias());
|
||||||
|
toUpdate.setDescription(model.getDescription());
|
||||||
|
updateMongoEntity();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AuthenticationFlowModel addAuthenticationFlow(AuthenticationFlowModel model) {
|
||||||
|
AuthenticationFlowEntity entity = new AuthenticationFlowEntity();
|
||||||
|
entity.setId(KeycloakModelUtils.generateId());
|
||||||
|
entity.setAlias(model.getAlias());
|
||||||
|
entity.setDescription(model.getDescription());
|
||||||
|
getMongoEntity().getAuthenticationFlows().add(entity);
|
||||||
|
model.setId(entity.getId());
|
||||||
|
updateMongoEntity();
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<AuthenticationExecutionModel> getAuthenticationExecutions(String flowId) {
|
||||||
|
AuthenticationFlowEntity flow = getFlowEntity(flowId);
|
||||||
|
if (flow == null) return Collections.EMPTY_LIST;
|
||||||
|
|
||||||
|
List<AuthenticationExecutionEntity> queryResult = flow.getExecutions();
|
||||||
|
List<AuthenticationExecutionModel> executions = new LinkedList<>();
|
||||||
|
for (AuthenticationExecutionEntity entity : queryResult) {
|
||||||
|
AuthenticationExecutionModel model = entityToModel(entity);
|
||||||
|
executions.add(model);
|
||||||
|
}
|
||||||
|
return executions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AuthenticationExecutionModel entityToModel(AuthenticationExecutionEntity entity) {
|
||||||
|
AuthenticationExecutionModel model = new AuthenticationExecutionModel();
|
||||||
|
model.setId(entity.getId());
|
||||||
|
model.setUserSetupAllowed(entity.isUserSetupAllowed());
|
||||||
|
model.setRequirement(entity.getRequirement());
|
||||||
|
model.setPriority(entity.getPriority());
|
||||||
|
model.setAuthenticator(entity.getAuthenticator());
|
||||||
|
model.setParentFlow(entity.getParentFlow());
|
||||||
|
model.setAutheticatorFlow(entity.isAutheticatorFlow());
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AuthenticationExecutionModel getAuthenticationExecutionById(String id) {
|
||||||
|
AuthenticationExecutionEntity execution = getAuthenticationExecutionEntity(id);
|
||||||
|
return entityToModel(execution);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AuthenticationExecutionEntity getAuthenticationExecutionEntity(String id) {
|
||||||
|
List<AuthenticationFlowEntity> flows = getMongoEntity().getAuthenticationFlows();
|
||||||
|
for (AuthenticationFlowEntity entity : flows) {
|
||||||
|
for (AuthenticationExecutionEntity exe : entity.getExecutions()) {
|
||||||
|
if (exe.getId().equals(id)) {
|
||||||
|
return exe;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AuthenticationExecutionModel addAuthenticatorExecution(AuthenticationExecutionModel model) {
|
||||||
|
AuthenticationExecutionEntity entity = new AuthenticationExecutionEntity();
|
||||||
|
entity.setId(KeycloakModelUtils.generateId());
|
||||||
|
entity.setAuthenticator(model.getAuthenticator());
|
||||||
|
entity.setPriority(model.getPriority());
|
||||||
|
entity.setRequirement(model.getRequirement());
|
||||||
|
entity.setUserSetupAllowed(model.isUserSetupAllowed());
|
||||||
|
entity.setAutheticatorFlow(model.isAutheticatorFlow());
|
||||||
|
AuthenticationFlowEntity flow = getFlowEntity(model.getId());
|
||||||
|
flow.getExecutions().add(entity);
|
||||||
|
updateMongoEntity();
|
||||||
|
model.setId(entity.getId());
|
||||||
|
return model;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateAuthenticatorExecution(AuthenticationExecutionModel model) {
|
||||||
|
AuthenticationExecutionEntity entity = null;
|
||||||
|
AuthenticationFlowEntity flow = getFlowEntity(model.getParentFlow());
|
||||||
|
for (AuthenticationExecutionEntity exe : flow.getExecutions()) {
|
||||||
|
if (exe.getId().equals(model.getId())) {
|
||||||
|
entity = exe;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (entity == null) return;
|
||||||
|
entity.setAutheticatorFlow(model.isAutheticatorFlow());
|
||||||
|
entity.setAuthenticator(model.getAuthenticator());
|
||||||
|
entity.setPriority(model.getPriority());
|
||||||
|
entity.setRequirement(model.getRequirement());
|
||||||
|
entity.setUserSetupAllowed(model.isUserSetupAllowed());
|
||||||
|
updateMongoEntity();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeAuthenticatorExecution(AuthenticationExecutionModel model) {
|
||||||
|
AuthenticationExecutionEntity entity = null;
|
||||||
|
AuthenticationFlowEntity flow = getFlowEntity(model.getParentFlow());
|
||||||
|
for (AuthenticationExecutionEntity exe : flow.getExecutions()) {
|
||||||
|
if (exe.getId().equals(model.getId())) {
|
||||||
|
entity = exe;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (entity == null) return;
|
||||||
|
flow.getExecutions().remove(entity);
|
||||||
|
updateMongoEntity();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<AuthenticatorModel> getAuthenticators() {
|
||||||
|
List<AuthenticatorModel> authenticators = new LinkedList<>();
|
||||||
|
for (AuthenticatorEntity entity : getMongoEntity().getAuthenticators()) {
|
||||||
|
authenticators.add(entityToModel(entity));
|
||||||
|
}
|
||||||
|
return authenticators;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AuthenticatorModel addAuthenticator(AuthenticatorModel model) {
|
||||||
|
AuthenticatorEntity auth = new AuthenticatorEntity();
|
||||||
|
auth.setId(KeycloakModelUtils.generateId());
|
||||||
|
auth.setAlias(model.getAlias());
|
||||||
|
auth.setProviderId(model.getProviderId());
|
||||||
|
auth.setConfig(model.getConfig());
|
||||||
|
realm.getAuthenticators().add(auth);
|
||||||
|
model.setId(auth.getId());
|
||||||
|
updateMongoEntity();
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeAuthenticator(AuthenticatorModel model) {
|
||||||
|
AuthenticatorEntity entity = getAuthenticatorEntity(model.getId());
|
||||||
|
if (entity == null) return;
|
||||||
|
getMongoEntity().getAuthenticators().remove(entity);
|
||||||
|
updateMongoEntity();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AuthenticatorModel getAuthenticatorById(String id) {
|
||||||
|
AuthenticatorEntity entity = getAuthenticatorEntity(id);
|
||||||
|
if (entity == null) return null;
|
||||||
|
return entityToModel(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AuthenticatorEntity getAuthenticatorEntity(String id) {
|
||||||
|
AuthenticatorEntity entity = null;
|
||||||
|
for (AuthenticatorEntity auth : getMongoEntity().getAuthenticators()) {
|
||||||
|
if (auth.getId().equals(id)) {
|
||||||
|
entity = auth;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AuthenticatorModel entityToModel(AuthenticatorEntity entity) {
|
||||||
|
AuthenticatorModel model = new AuthenticatorModel();
|
||||||
|
model.setId(entity.getId());
|
||||||
|
model.setProviderId(entity.getProviderId());
|
||||||
|
model.setAlias(entity.getAlias());
|
||||||
|
Map<String, String> config = new HashMap<>();
|
||||||
|
if (entity.getConfig() != null) config.putAll(entity.getConfig());
|
||||||
|
model.setConfig(config);
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateAuthenticator(AuthenticatorModel model) {
|
||||||
|
AuthenticatorEntity entity = getAuthenticatorEntity(model.getId());
|
||||||
|
if (entity == null) return;
|
||||||
|
entity.setAlias(model.getAlias());
|
||||||
|
entity.setProviderId(model.getProviderId());
|
||||||
|
if (entity.getConfig() == null) {
|
||||||
|
entity.setConfig(model.getConfig());
|
||||||
|
} else {
|
||||||
|
entity.getConfig().clear();
|
||||||
|
entity.getConfig().putAll(model.getConfig());
|
||||||
|
}
|
||||||
|
updateMongoEntity();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<UserFederationMapperModel> getUserFederationMappers() {
|
public Set<UserFederationMapperModel> getUserFederationMappers() {
|
||||||
Set<UserFederationMapperModel> mappers = new HashSet<UserFederationMapperModel>();
|
Set<UserFederationMapperModel> mappers = new HashSet<UserFederationMapperModel>();
|
||||||
|
|
|
@ -3,6 +3,7 @@ package org.keycloak.authentication;
|
||||||
import org.jboss.resteasy.spi.HttpRequest;
|
import org.jboss.resteasy.spi.HttpRequest;
|
||||||
import org.keycloak.ClientConnection;
|
import org.keycloak.ClientConnection;
|
||||||
import org.keycloak.events.EventBuilder;
|
import org.keycloak.events.EventBuilder;
|
||||||
|
import org.keycloak.models.AuthenticationExecutionModel;
|
||||||
import org.keycloak.models.AuthenticatorModel;
|
import org.keycloak.models.AuthenticatorModel;
|
||||||
import org.keycloak.models.ClientSessionModel;
|
import org.keycloak.models.ClientSessionModel;
|
||||||
import org.keycloak.models.KeycloakSession;
|
import org.keycloak.models.KeycloakSession;
|
||||||
|
@ -52,7 +53,7 @@ public class AuthenticationProcessor {
|
||||||
protected ClientConnection connection;
|
protected ClientConnection connection;
|
||||||
protected UriInfo uriInfo;
|
protected UriInfo uriInfo;
|
||||||
protected KeycloakSession session;
|
protected KeycloakSession session;
|
||||||
protected List<AuthenticatorModel> authenticators;
|
protected List<AuthenticationExecutionModel> executions;
|
||||||
protected BruteForceProtector protector;
|
protected BruteForceProtector protector;
|
||||||
protected EventBuilder eventBuilder;
|
protected EventBuilder eventBuilder;
|
||||||
protected HttpRequest request;
|
protected HttpRequest request;
|
||||||
|
@ -159,6 +160,13 @@ public class AuthenticationProcessor {
|
||||||
this.status = Status.FAILURE_CHALLENGE;
|
this.status = Status.FAILURE_CHALLENGE;
|
||||||
this.challenge = challenge;
|
this.challenge = challenge;
|
||||||
|
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void failure(Error error, Response challenge) {
|
||||||
|
this.error = error;
|
||||||
|
this.status = Status.FAILED;
|
||||||
|
this.challenge = challenge;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -264,28 +272,29 @@ public class AuthenticationProcessor {
|
||||||
validateUser(authUser);
|
validateUser(authUser);
|
||||||
Response challenge = null;
|
Response challenge = null;
|
||||||
Map<String, UserSessionModel.AuthenticatorStatus> previousAttempts = clientSession.getAuthenticators();
|
Map<String, UserSessionModel.AuthenticatorStatus> previousAttempts = clientSession.getAuthenticators();
|
||||||
for (AuthenticatorModel model : authenticators) {
|
for (AuthenticationExecutionModel model : executions) {
|
||||||
UserSessionModel.AuthenticatorStatus oldStatus = previousAttempts.get(model.getAlias());
|
UserSessionModel.AuthenticatorStatus oldStatus = previousAttempts.get(model.getId());
|
||||||
if (isProcessed(oldStatus)) continue;
|
if (isProcessed(oldStatus)) continue;
|
||||||
|
|
||||||
AuthenticatorFactory factory = (AuthenticatorFactory)session.getKeycloakSessionFactory().getProviderFactory(Authenticator.class, model.getProviderId());
|
AuthenticatorModel authenticatorModel = realm.getAuthenticatorById(model.getAuthenticator());
|
||||||
Authenticator authenticator = factory.create(model);
|
AuthenticatorFactory factory = (AuthenticatorFactory)session.getKeycloakSessionFactory().getProviderFactory(Authenticator.class, authenticatorModel.getProviderId());
|
||||||
|
Authenticator authenticator = factory.create(authenticatorModel);
|
||||||
if (authenticator.requiresUser() && authUser == null){
|
if (authenticator.requiresUser() && authUser == null){
|
||||||
if ( authenticator.requiresUser()) {
|
if ( authenticator.requiresUser()) {
|
||||||
if (challenge != null) return challenge;
|
if (challenge != null) return challenge;
|
||||||
throw new AuthException(Error.UNKNOWN_USER);
|
throw new AuthException(Error.UNKNOWN_USER);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (authUser != null && model.getRequirement() == AuthenticatorModel.Requirement.ALTERNATIVE) {
|
if (authUser != null && model.getRequirement() == AuthenticationExecutionModel.Requirement.ALTERNATIVE) {
|
||||||
clientSession.setAuthenticatorStatus(model.getAlias(), UserSessionModel.AuthenticatorStatus.SKIPPED);
|
clientSession.setAuthenticatorStatus(model.getId(), UserSessionModel.AuthenticatorStatus.SKIPPED);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
authUser = clientSession.getAuthenticatedUser();
|
authUser = clientSession.getAuthenticatedUser();
|
||||||
|
|
||||||
if (authenticator.requiresUser() && authUser != null && !authenticator.configuredFor(authUser)) {
|
if (authenticator.requiresUser() && authUser != null && !authenticator.configuredFor(authUser)) {
|
||||||
if (model.getRequirement() == AuthenticatorModel.Requirement.REQUIRED) {
|
if (model.getRequirement() == AuthenticationExecutionModel.Requirement.REQUIRED) {
|
||||||
if (model.isUserSetupAllowed()) {
|
if (model.isUserSetupAllowed()) {
|
||||||
clientSession.setAuthenticatorStatus(model.getAlias(), UserSessionModel.AuthenticatorStatus.SETUP_REQUIRED);
|
clientSession.setAuthenticatorStatus(model.getId(), UserSessionModel.AuthenticatorStatus.SETUP_REQUIRED);
|
||||||
authUser.addRequiredAction(authenticator.getRequiredAction());
|
authUser.addRequiredAction(authenticator.getRequiredAction());
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
@ -294,25 +303,26 @@ public class AuthenticationProcessor {
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
Result context = new Result(model, authenticator);
|
Result context = new Result(authenticatorModel, authenticator);
|
||||||
authenticator.authenticate(context);
|
authenticator.authenticate(context);
|
||||||
Status result = context.getStatus();
|
Status result = context.getStatus();
|
||||||
if (result == Status.SUCCESS){
|
if (result == Status.SUCCESS){
|
||||||
clientSession.setAuthenticatorStatus(model.getAlias(), UserSessionModel.AuthenticatorStatus.SUCCESS);
|
clientSession.setAuthenticatorStatus(model.getId(), UserSessionModel.AuthenticatorStatus.SUCCESS);
|
||||||
if (model.isMasterAuthenticator()) return authenticationComplete();
|
//if (model.isMasterAuthenticator()) return authenticationComplete();
|
||||||
continue;
|
continue;
|
||||||
} else if (result == Status.FAILED) {
|
} else if (result == Status.FAILED) {
|
||||||
|
if (context.challenge != null) return context.challenge;
|
||||||
throw new AuthException(context.error);
|
throw new AuthException(context.error);
|
||||||
} else if (result == Status.CHALLENGE) {
|
} else if (result == Status.CHALLENGE) {
|
||||||
if (model.getRequirement() == AuthenticatorModel.Requirement.REQUIRED) return context.challenge;
|
if (model.getRequirement() == AuthenticationExecutionModel.Requirement.REQUIRED) return context.challenge;
|
||||||
if (challenge != null) challenge = context.challenge;
|
if (challenge != null) challenge = context.challenge;
|
||||||
continue;
|
continue;
|
||||||
} else if (result == Status.FAILURE_CHALLENGE) {
|
} else if (result == Status.FAILURE_CHALLENGE) {
|
||||||
logUserFailure();
|
logUserFailure();
|
||||||
return context.challenge;
|
return context.challenge;
|
||||||
} else if (result == Status.ATTEMPTED) {
|
} else if (result == Status.ATTEMPTED) {
|
||||||
if (model.getRequirement() == AuthenticatorModel.Requirement.REQUIRED) throw new AuthException(Error.INVALID_CREDENTIALS);
|
if (model.getRequirement() == AuthenticationExecutionModel.Requirement.REQUIRED) throw new AuthException(Error.INVALID_CREDENTIALS);
|
||||||
clientSession.setAuthenticatorStatus(model.getAlias(), UserSessionModel.AuthenticatorStatus.ATTEMPTED);
|
clientSession.setAuthenticatorStatus(model.getId(), UserSessionModel.AuthenticatorStatus.ATTEMPTED);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ import org.keycloak.models.RealmModel;
|
||||||
import org.keycloak.models.UserModel;
|
import org.keycloak.models.UserModel;
|
||||||
import org.keycloak.models.UserSessionModel;
|
import org.keycloak.models.UserSessionModel;
|
||||||
import org.keycloak.services.managers.BruteForceProtector;
|
import org.keycloak.services.managers.BruteForceProtector;
|
||||||
|
import org.keycloak.services.managers.ClientSessionCode;
|
||||||
|
|
||||||
import javax.ws.rs.core.Response;
|
import javax.ws.rs.core.Response;
|
||||||
import javax.ws.rs.core.UriInfo;
|
import javax.ws.rs.core.UriInfo;
|
||||||
|
@ -48,6 +49,7 @@ public interface AuthenticatorContext {
|
||||||
|
|
||||||
void success();
|
void success();
|
||||||
void failure(AuthenticationProcessor.Error error);
|
void failure(AuthenticationProcessor.Error error);
|
||||||
|
void failure(AuthenticationProcessor.Error error, Response response);
|
||||||
void challenge(Response challenge);
|
void challenge(Response challenge);
|
||||||
void failureChallenge(AuthenticationProcessor.Error error, Response challenge);
|
void failureChallenge(AuthenticationProcessor.Error error, Response challenge);
|
||||||
void attempted();
|
void attempted();
|
||||||
|
|
|
@ -1,13 +1,16 @@
|
||||||
package org.keycloak.authentication;
|
package org.keycloak.authentication;
|
||||||
|
|
||||||
import org.keycloak.models.AuthenticatorModel;
|
import org.keycloak.models.AuthenticatorModel;
|
||||||
|
import org.keycloak.provider.ConfiguredProvider;
|
||||||
import org.keycloak.provider.ProviderFactory;
|
import org.keycloak.provider.ProviderFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
* @version $Revision: 1 $
|
* @version $Revision: 1 $
|
||||||
*/
|
*/
|
||||||
public interface AuthenticatorFactory extends ProviderFactory<Authenticator> {
|
public interface AuthenticatorFactory extends ProviderFactory<Authenticator>, ConfiguredProvider {
|
||||||
Authenticator create(AuthenticatorModel model);
|
Authenticator create(AuthenticatorModel model);
|
||||||
|
String getDisplayCategory();
|
||||||
|
String getDisplayType();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
33
services/src/main/java/org/keycloak/authentication/AuthenticatorSpi.java
Executable file
33
services/src/main/java/org/keycloak/authentication/AuthenticatorSpi.java
Executable file
|
@ -0,0 +1,33 @@
|
||||||
|
package org.keycloak.authentication;
|
||||||
|
|
||||||
|
import org.keycloak.protocol.ProtocolMapper;
|
||||||
|
import org.keycloak.provider.Provider;
|
||||||
|
import org.keycloak.provider.ProviderFactory;
|
||||||
|
import org.keycloak.provider.Spi;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
||||||
|
*/
|
||||||
|
public class AuthenticatorSpi implements Spi {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isPrivate() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "authenticator";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<? extends Provider> getProviderClass() {
|
||||||
|
return Authenticator.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<? extends ProviderFactory> getProviderFactoryClass() {
|
||||||
|
return AuthenticatorFactory.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,60 @@
|
||||||
|
package org.keycloak.authentication.authenticators;
|
||||||
|
|
||||||
|
import org.keycloak.models.AuthenticationExecutionModel;
|
||||||
|
import org.keycloak.models.AuthenticatorModel;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
* @version $Revision: 1 $
|
||||||
|
*/
|
||||||
|
public class AuthenticationFlow {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hardcoded models just to test this stuff. It is temporary
|
||||||
|
*/
|
||||||
|
static List<AuthenticationExecutionModel> hardcoded = new ArrayList<>();
|
||||||
|
|
||||||
|
/*
|
||||||
|
static {
|
||||||
|
AuthenticationExecutionModel model = new AuthenticationExecutionModel();
|
||||||
|
model.setId("1");
|
||||||
|
model.setAlias("cookie");
|
||||||
|
model.setMasterAuthenticator(true);
|
||||||
|
model.setProviderId(CookieAuthenticatorFactory.PROVIDER_ID);
|
||||||
|
model.setPriority(0);
|
||||||
|
model.setRequirement(AuthenticationExecutionModel.Requirement.ALTERNATIVE);
|
||||||
|
model.setUserSetupAllowed(false);
|
||||||
|
hardcoded.add(model);
|
||||||
|
model = new AuthenticatorModel();
|
||||||
|
model.setId("2");
|
||||||
|
model.setAlias("user form");
|
||||||
|
model.setMasterAuthenticator(false);
|
||||||
|
model.setProviderId(LoginFormUsernameAuthenticatorFactory.PROVIDER_ID);
|
||||||
|
model.setPriority(1);
|
||||||
|
model.setRequirement(AuthenticationExecutionModel.Requirement.REQUIRED);
|
||||||
|
model.setUserSetupAllowed(false);
|
||||||
|
hardcoded.add(model);
|
||||||
|
model = new AuthenticatorModel();
|
||||||
|
model.setId("3");
|
||||||
|
model.setAlias("password form");
|
||||||
|
model.setMasterAuthenticator(false);
|
||||||
|
model.setProviderId(LoginFormUsernameAuthenticatorFactory.PROVIDER_ID);
|
||||||
|
model.setPriority(2);
|
||||||
|
model.setRequirement(AuthenticationExecutionModel.Requirement.REQUIRED);
|
||||||
|
model.setUserSetupAllowed(false);
|
||||||
|
hardcoded.add(model);
|
||||||
|
model = new AuthenticatorModel();
|
||||||
|
model.setId("4");
|
||||||
|
model.setAlias("otp form");
|
||||||
|
model.setMasterAuthenticator(false);
|
||||||
|
model.setProviderId(OTPFormAuthenticatorFactory.PROVIDER_ID);
|
||||||
|
model.setPriority(3);
|
||||||
|
model.setRequirement(AuthenticationExecutionModel.Requirement.OPTIONAL);
|
||||||
|
model.setUserSetupAllowed(false);
|
||||||
|
hardcoded.add(model);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
|
@ -6,12 +6,16 @@ import org.keycloak.authentication.AuthenticatorFactory;
|
||||||
import org.keycloak.models.AuthenticatorModel;
|
import org.keycloak.models.AuthenticatorModel;
|
||||||
import org.keycloak.models.KeycloakSession;
|
import org.keycloak.models.KeycloakSession;
|
||||||
import org.keycloak.models.KeycloakSessionFactory;
|
import org.keycloak.models.KeycloakSessionFactory;
|
||||||
|
import org.keycloak.provider.ProviderConfigProperty;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
* @version $Revision: 1 $
|
* @version $Revision: 1 $
|
||||||
*/
|
*/
|
||||||
public class CookieAuthenticatorFactory implements AuthenticatorFactory {
|
public class CookieAuthenticatorFactory implements AuthenticatorFactory {
|
||||||
|
public static final String PROVIDER_ID = "auth-cookie";
|
||||||
static CookieAuthenticator SINGLETON = new CookieAuthenticator();
|
static CookieAuthenticator SINGLETON = new CookieAuthenticator();
|
||||||
@Override
|
@Override
|
||||||
public Authenticator create(AuthenticatorModel model) {
|
public Authenticator create(AuthenticatorModel model) {
|
||||||
|
@ -40,6 +44,26 @@ public class CookieAuthenticatorFactory implements AuthenticatorFactory {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getId() {
|
public String getId() {
|
||||||
return "auth-cookie";
|
return PROVIDER_ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDisplayCategory() {
|
||||||
|
return "Complete Authenticator";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDisplayType() {
|
||||||
|
return "Cookie Authenticator";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getHelpText() {
|
||||||
|
return "Validates the SSO cookie set by the auth server.";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<ProviderConfigProperty> getConfigProperties() {
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ import org.keycloak.models.AuthenticatorModel;
|
||||||
import org.keycloak.models.UserCredentialModel;
|
import org.keycloak.models.UserCredentialModel;
|
||||||
import org.keycloak.models.UserModel;
|
import org.keycloak.models.UserModel;
|
||||||
import org.keycloak.representations.idm.CredentialRepresentation;
|
import org.keycloak.representations.idm.CredentialRepresentation;
|
||||||
|
import org.keycloak.services.messages.Messages;
|
||||||
|
|
||||||
import javax.ws.rs.core.MultivaluedMap;
|
import javax.ws.rs.core.MultivaluedMap;
|
||||||
import javax.ws.rs.core.Response;
|
import javax.ws.rs.core.Response;
|
||||||
|
@ -31,19 +32,23 @@ public class LoginFormOTPAuthenticator extends LoginFormUsernameAuthenticator {
|
||||||
validateOTP(context);
|
validateOTP(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected Response badPassword(AuthenticatorContext context) {
|
||||||
|
return loginForm(context).setError(Messages.INVALID_USER).createLogin();
|
||||||
|
}
|
||||||
|
|
||||||
public void validateOTP(AuthenticatorContext context) {
|
public void validateOTP(AuthenticatorContext context) {
|
||||||
MultivaluedMap<String, String> inputData = context.getHttpRequest().getFormParameters();
|
MultivaluedMap<String, String> inputData = context.getHttpRequest().getFormParameters();
|
||||||
List<UserCredentialModel> credentials = new LinkedList<>();
|
List<UserCredentialModel> credentials = new LinkedList<>();
|
||||||
String password = inputData.getFirst(CredentialRepresentation.TOTP);
|
String password = inputData.getFirst(CredentialRepresentation.TOTP);
|
||||||
if (password == null) {
|
if (password == null) {
|
||||||
Response challengeResponse = challenge(context);
|
Response challengeResponse = badPassword(context);
|
||||||
context.failureChallenge(AuthenticationProcessor.Error.INVALID_CREDENTIALS, challengeResponse);
|
context.failureChallenge(AuthenticationProcessor.Error.INVALID_CREDENTIALS, challengeResponse);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
credentials.add(UserCredentialModel.totp(password));
|
credentials.add(UserCredentialModel.totp(password));
|
||||||
boolean valid = context.getSession().users().validCredentials(context.getRealm(), context.getUser(), credentials);
|
boolean valid = context.getSession().users().validCredentials(context.getRealm(), context.getUser(), credentials);
|
||||||
if (!valid) {
|
if (!valid) {
|
||||||
Response challengeResponse = challenge(context);
|
Response challengeResponse = badPassword(context);
|
||||||
context.failureChallenge(AuthenticationProcessor.Error.INVALID_CREDENTIALS, challengeResponse);
|
context.failureChallenge(AuthenticationProcessor.Error.INVALID_CREDENTIALS, challengeResponse);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,70 @@
|
||||||
|
package org.keycloak.authentication.authenticators;
|
||||||
|
|
||||||
|
import org.keycloak.Config;
|
||||||
|
import org.keycloak.authentication.Authenticator;
|
||||||
|
import org.keycloak.authentication.AuthenticatorFactory;
|
||||||
|
import org.keycloak.models.AuthenticatorModel;
|
||||||
|
import org.keycloak.models.KeycloakSession;
|
||||||
|
import org.keycloak.models.KeycloakSessionFactory;
|
||||||
|
import org.keycloak.provider.ProviderConfigProperty;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
* @version $Revision: 1 $
|
||||||
|
*/
|
||||||
|
public class LoginFormOTPAuthenticatorFactory implements AuthenticatorFactory {
|
||||||
|
|
||||||
|
public static final String PROVIDER_ID = "auth-login-form-otp";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Authenticator create(AuthenticatorModel model) {
|
||||||
|
return new LoginFormOTPAuthenticator(model);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Authenticator create(KeycloakSession session) {
|
||||||
|
throw new IllegalStateException("illegal call");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init(Config.Scope config) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void postInit(KeycloakSessionFactory factory) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getId() {
|
||||||
|
return PROVIDER_ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDisplayCategory() {
|
||||||
|
return "Credential Validation";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDisplayType() {
|
||||||
|
return "Login Form OTP";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getHelpText() {
|
||||||
|
return "Validates an OTP that is specified on the login page.";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<ProviderConfigProperty> getConfigProperties() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,6 +6,7 @@ import org.keycloak.models.AuthenticatorModel;
|
||||||
import org.keycloak.models.UserCredentialModel;
|
import org.keycloak.models.UserCredentialModel;
|
||||||
import org.keycloak.models.UserModel;
|
import org.keycloak.models.UserModel;
|
||||||
import org.keycloak.representations.idm.CredentialRepresentation;
|
import org.keycloak.representations.idm.CredentialRepresentation;
|
||||||
|
import org.keycloak.services.messages.Messages;
|
||||||
|
|
||||||
import javax.ws.rs.core.MultivaluedMap;
|
import javax.ws.rs.core.MultivaluedMap;
|
||||||
import javax.ws.rs.core.Response;
|
import javax.ws.rs.core.Response;
|
||||||
|
@ -31,19 +32,24 @@ public class LoginFormPasswordAuthenticator extends LoginFormUsernameAuthenticat
|
||||||
validatePassword(context);
|
validatePassword(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected Response badPassword(AuthenticatorContext context) {
|
||||||
|
return loginForm(context).setError(Messages.INVALID_USER).createLogin();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public void validatePassword(AuthenticatorContext context) {
|
public void validatePassword(AuthenticatorContext context) {
|
||||||
MultivaluedMap<String, String> inputData = context.getHttpRequest().getFormParameters();
|
MultivaluedMap<String, String> inputData = context.getHttpRequest().getFormParameters();
|
||||||
List<UserCredentialModel> credentials = new LinkedList<>();
|
List<UserCredentialModel> credentials = new LinkedList<>();
|
||||||
String password = inputData.getFirst(CredentialRepresentation.PASSWORD);
|
String password = inputData.getFirst(CredentialRepresentation.PASSWORD);
|
||||||
if (password == null) {
|
if (password == null) {
|
||||||
Response challengeResponse = challenge(context);
|
Response challengeResponse = badPassword(context);
|
||||||
context.failureChallenge(AuthenticationProcessor.Error.INVALID_CREDENTIALS, challengeResponse);
|
context.failureChallenge(AuthenticationProcessor.Error.INVALID_CREDENTIALS, challengeResponse);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
credentials.add(UserCredentialModel.password(password));
|
credentials.add(UserCredentialModel.password(password));
|
||||||
boolean valid = context.getSession().users().validCredentials(context.getRealm(), context.getUser(), credentials);
|
boolean valid = context.getSession().users().validCredentials(context.getRealm(), context.getUser(), credentials);
|
||||||
if (!valid) {
|
if (!valid) {
|
||||||
Response challengeResponse = challenge(context);
|
Response challengeResponse = badPassword(context);
|
||||||
context.failureChallenge(AuthenticationProcessor.Error.INVALID_CREDENTIALS, challengeResponse);
|
context.failureChallenge(AuthenticationProcessor.Error.INVALID_CREDENTIALS, challengeResponse);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,70 @@
|
||||||
|
package org.keycloak.authentication.authenticators;
|
||||||
|
|
||||||
|
import org.keycloak.Config;
|
||||||
|
import org.keycloak.authentication.Authenticator;
|
||||||
|
import org.keycloak.authentication.AuthenticatorFactory;
|
||||||
|
import org.keycloak.models.AuthenticatorModel;
|
||||||
|
import org.keycloak.models.KeycloakSession;
|
||||||
|
import org.keycloak.models.KeycloakSessionFactory;
|
||||||
|
import org.keycloak.provider.ProviderConfigProperty;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
* @version $Revision: 1 $
|
||||||
|
*/
|
||||||
|
public class LoginFormPasswordAuthenticatorFactory implements AuthenticatorFactory {
|
||||||
|
|
||||||
|
public static final String PROVIDER_ID = "auth-login-form-password";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Authenticator create(AuthenticatorModel model) {
|
||||||
|
return new LoginFormPasswordAuthenticator(model);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Authenticator create(KeycloakSession session) {
|
||||||
|
throw new IllegalStateException("illegal call");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init(Config.Scope config) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void postInit(KeycloakSessionFactory factory) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getId() {
|
||||||
|
return PROVIDER_ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDisplayCategory() {
|
||||||
|
return "Credential Validation";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDisplayType() {
|
||||||
|
return "Login Form Password";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getHelpText() {
|
||||||
|
return "Validates a user password that is specified on the login page.";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<ProviderConfigProperty> getConfigProperties() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,11 +6,13 @@ import org.keycloak.authentication.Authenticator;
|
||||||
import org.keycloak.authentication.AuthenticatorContext;
|
import org.keycloak.authentication.AuthenticatorContext;
|
||||||
import org.keycloak.login.LoginFormsProvider;
|
import org.keycloak.login.LoginFormsProvider;
|
||||||
import org.keycloak.models.AuthenticatorModel;
|
import org.keycloak.models.AuthenticatorModel;
|
||||||
|
import org.keycloak.models.ClientSessionModel;
|
||||||
import org.keycloak.models.UserModel;
|
import org.keycloak.models.UserModel;
|
||||||
import org.keycloak.models.utils.KeycloakModelUtils;
|
import org.keycloak.models.utils.KeycloakModelUtils;
|
||||||
import org.keycloak.protocol.oidc.OIDCLoginProtocol;
|
import org.keycloak.protocol.oidc.OIDCLoginProtocol;
|
||||||
import org.keycloak.services.managers.AuthenticationManager;
|
import org.keycloak.services.managers.AuthenticationManager;
|
||||||
import org.keycloak.services.managers.ClientSessionCode;
|
import org.keycloak.services.managers.ClientSessionCode;
|
||||||
|
import org.keycloak.services.messages.Messages;
|
||||||
import org.keycloak.services.resources.LoginActionsService;
|
import org.keycloak.services.resources.LoginActionsService;
|
||||||
|
|
||||||
import javax.ws.rs.core.MultivaluedMap;
|
import javax.ws.rs.core.MultivaluedMap;
|
||||||
|
@ -59,19 +61,37 @@ public class LoginFormUsernameAuthenticator implements Authenticator {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Response challenge(AuthenticatorContext context, MultivaluedMap<String, String> formData) {
|
protected Response challenge(AuthenticatorContext context, MultivaluedMap<String, String> formData) {
|
||||||
LoginFormsProvider forms = context.getSession().getProvider(LoginFormsProvider.class)
|
LoginFormsProvider forms = loginForm(context);
|
||||||
.setClientSessionCode(new ClientSessionCode(context.getRealm(), context.getClientSession()).getCode());
|
|
||||||
|
|
||||||
if (formData.size() > 0) forms.setFormData(formData);
|
if (formData.size() > 0) forms.setFormData(formData);
|
||||||
|
|
||||||
return forms.createLogin();
|
return forms.createLogin();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected LoginFormsProvider loginForm(AuthenticatorContext context) {
|
||||||
|
ClientSessionCode code = new ClientSessionCode(context.getRealm(), context.getClientSession());
|
||||||
|
code.setAction(ClientSessionModel.Action.AUTHENTICATE);
|
||||||
|
return context.getSession().getProvider(LoginFormsProvider.class)
|
||||||
|
.setClientSessionCode(code.getCode());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Response invalidUser(AuthenticatorContext context) {
|
||||||
|
return loginForm(context).setError(Messages.INVALID_USER).createLogin();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Response disabledUser(AuthenticatorContext context) {
|
||||||
|
return loginForm(context).setError(Messages.ACCOUNT_DISABLED).createLogin();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Response temporarilyDisabledUser(AuthenticatorContext context) {
|
||||||
|
return loginForm(context).setError(Messages.ACCOUNT_TEMPORARILY_DISABLED).createLogin();
|
||||||
|
}
|
||||||
|
|
||||||
public void validateUser(AuthenticatorContext context) {
|
public void validateUser(AuthenticatorContext context) {
|
||||||
MultivaluedMap<String, String> inputData = context.getHttpRequest().getFormParameters();
|
MultivaluedMap<String, String> inputData = context.getHttpRequest().getFormParameters();
|
||||||
String username = inputData.getFirst(AuthenticationManager.FORM_USERNAME);
|
String username = inputData.getFirst(AuthenticationManager.FORM_USERNAME);
|
||||||
if (username == null) {
|
if (username == null) {
|
||||||
Response challengeResponse = challenge(context);
|
Response challengeResponse = invalidUser(context);
|
||||||
context.failureChallenge(AuthenticationProcessor.Error.INVALID_USER, challengeResponse);
|
context.failureChallenge(AuthenticationProcessor.Error.INVALID_USER, challengeResponse);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -82,17 +102,19 @@ public class LoginFormUsernameAuthenticator implements Authenticator {
|
||||||
|
|
||||||
public boolean invalidUser(AuthenticatorContext context, UserModel user) {
|
public boolean invalidUser(AuthenticatorContext context, UserModel user) {
|
||||||
if (user == null) {
|
if (user == null) {
|
||||||
Response challengeResponse = challenge(context);
|
Response challengeResponse = invalidUser(context);
|
||||||
context.failureChallenge(AuthenticationProcessor.Error.INVALID_USER, challengeResponse);
|
context.failureChallenge(AuthenticationProcessor.Error.INVALID_USER, challengeResponse);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (!user.isEnabled()) {
|
if (!user.isEnabled()) {
|
||||||
context.failure(AuthenticationProcessor.Error.USER_DISABLED);
|
Response challengeResponse = disabledUser(context);
|
||||||
|
context.failureChallenge(AuthenticationProcessor.Error.USER_DISABLED, challengeResponse);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (context.getRealm().isBruteForceProtected()) {
|
if (context.getRealm().isBruteForceProtected()) {
|
||||||
if (context.getProtector().isTemporarilyDisabled(context.getSession(), context.getRealm(), user.getUsername())) {
|
if (context.getProtector().isTemporarilyDisabled(context.getSession(), context.getRealm(), user.getUsername())) {
|
||||||
context.failure(AuthenticationProcessor.Error.USER_TEMPORARILY_DISABLED);
|
Response challengeResponse = temporarilyDisabledUser(context);
|
||||||
|
context.failureChallenge(AuthenticationProcessor.Error.USER_TEMPORARILY_DISABLED, challengeResponse);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,70 @@
|
||||||
|
package org.keycloak.authentication.authenticators;
|
||||||
|
|
||||||
|
import org.keycloak.Config;
|
||||||
|
import org.keycloak.authentication.Authenticator;
|
||||||
|
import org.keycloak.authentication.AuthenticatorFactory;
|
||||||
|
import org.keycloak.models.AuthenticatorModel;
|
||||||
|
import org.keycloak.models.KeycloakSession;
|
||||||
|
import org.keycloak.models.KeycloakSessionFactory;
|
||||||
|
import org.keycloak.provider.ProviderConfigProperty;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
* @version $Revision: 1 $
|
||||||
|
*/
|
||||||
|
public class LoginFormUsernameAuthenticatorFactory implements AuthenticatorFactory {
|
||||||
|
|
||||||
|
public static final String PROVIDER_ID = "auth-login-form-username";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Authenticator create(AuthenticatorModel model) {
|
||||||
|
return new LoginFormUsernameAuthenticator(model);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Authenticator create(KeycloakSession session) {
|
||||||
|
throw new IllegalStateException("illegal call");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init(Config.Scope config) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void postInit(KeycloakSessionFactory factory) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getId() {
|
||||||
|
return PROVIDER_ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDisplayCategory() {
|
||||||
|
return "User Validation";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDisplayType() {
|
||||||
|
return "Login Form Username";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getHelpText() {
|
||||||
|
return "Validates a username that is specified on the login page.";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<ProviderConfigProperty> getConfigProperties() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,70 @@
|
||||||
|
package org.keycloak.authentication.authenticators;
|
||||||
|
|
||||||
|
import org.keycloak.Config;
|
||||||
|
import org.keycloak.authentication.Authenticator;
|
||||||
|
import org.keycloak.authentication.AuthenticatorFactory;
|
||||||
|
import org.keycloak.models.AuthenticatorModel;
|
||||||
|
import org.keycloak.models.KeycloakSession;
|
||||||
|
import org.keycloak.models.KeycloakSessionFactory;
|
||||||
|
import org.keycloak.provider.ProviderConfigProperty;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
* @version $Revision: 1 $
|
||||||
|
*/
|
||||||
|
public class OTPFormAuthenticatorFactory implements AuthenticatorFactory {
|
||||||
|
|
||||||
|
public static final String PROVIDER_ID = "auth-otp-form";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Authenticator create(AuthenticatorModel model) {
|
||||||
|
return new OTPFormAuthenticator(model);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Authenticator create(KeycloakSession session) {
|
||||||
|
throw new IllegalStateException("illegal call");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init(Config.Scope config) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void postInit(KeycloakSessionFactory factory) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getId() {
|
||||||
|
return PROVIDER_ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDisplayCategory() {
|
||||||
|
return "Credential Validation";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDisplayType() {
|
||||||
|
return "OTP Form";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getHelpText() {
|
||||||
|
return "Validates a OTP on a separate OTP form.";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<ProviderConfigProperty> getConfigProperties() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
org.keycloak.authentication.authenticators.CookieAuthenticatorFactory
|
||||||
|
org.keycloak.authentication.authenticators.LoginFormOTPAuthenticatorFactory
|
||||||
|
org.keycloak.authentication.authenticators.LoginFormPasswordAuthenticatorFactory
|
||||||
|
org.keycloak.authentication.authenticators.LoginFormUsernameAuthenticatorFactory
|
||||||
|
org.keycloak.authentication.authenticators.OTPFormAuthenticatorFactory
|
Loading…
Reference in a new issue