brute force refactr, mv protocol
This commit is contained in:
parent
5017d71383
commit
007e9530ec
33 changed files with 159 additions and 88 deletions
|
@ -32,8 +32,8 @@ import java.util.List;
|
||||||
public class SamlProtocolFactory extends AbstractLoginProtocolFactory {
|
public class SamlProtocolFactory extends AbstractLoginProtocolFactory {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object createProtocolEndpoint(RealmModel realm, EventBuilder event, AuthenticationManager authManager) {
|
public Object createProtocolEndpoint(RealmModel realm, EventBuilder event) {
|
||||||
return new SamlService(realm, event, authManager);
|
return new SamlService(realm, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -61,8 +61,8 @@ public class SamlService extends AuthorizationEndpointBase {
|
||||||
|
|
||||||
protected static final Logger logger = Logger.getLogger(SamlService.class);
|
protected static final Logger logger = Logger.getLogger(SamlService.class);
|
||||||
|
|
||||||
public SamlService(RealmModel realm, EventBuilder event, AuthenticationManager authManager) {
|
public SamlService(RealmModel realm, EventBuilder event) {
|
||||||
super(realm, event, authManager);
|
super(realm, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract class BindingProtocol {
|
public abstract class BindingProtocol {
|
||||||
|
@ -556,7 +556,7 @@ public class SamlService extends AuthorizationEndpointBase {
|
||||||
@POST
|
@POST
|
||||||
@Consumes("application/soap+xml")
|
@Consumes("application/soap+xml")
|
||||||
public Response soapBinding(InputStream inputStream) {
|
public Response soapBinding(InputStream inputStream) {
|
||||||
SamlEcpProfileService bindingService = new SamlEcpProfileService(realm, event, authManager);
|
SamlEcpProfileService bindingService = new SamlEcpProfileService(realm, event);
|
||||||
|
|
||||||
ResteasyProviderFactory.getInstance().injectProperties(bindingService);
|
ResteasyProviderFactory.getInstance().injectProperties(bindingService);
|
||||||
|
|
||||||
|
|
|
@ -36,8 +36,8 @@ public class SamlEcpProfileService extends SamlService {
|
||||||
private static final String NS_PREFIX_SAML_PROTOCOL = "samlp";
|
private static final String NS_PREFIX_SAML_PROTOCOL = "samlp";
|
||||||
private static final String NS_PREFIX_SAML_ASSERTION = "saml";
|
private static final String NS_PREFIX_SAML_ASSERTION = "saml";
|
||||||
|
|
||||||
public SamlEcpProfileService(RealmModel realm, EventBuilder event, AuthenticationManager authManager) {
|
public SamlEcpProfileService(RealmModel realm, EventBuilder event) {
|
||||||
super(realm, event, authManager);
|
super(realm, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Response authenticate(InputStream inputStream) {
|
public Response authenticate(InputStream inputStream) {
|
||||||
|
|
|
@ -30,7 +30,7 @@ public interface LoginProtocolFactory extends ProviderFactory<LoginProtocol> {
|
||||||
*/
|
*/
|
||||||
List<ProtocolMapperModel> getDefaultBuiltinMappers();
|
List<ProtocolMapperModel> getDefaultBuiltinMappers();
|
||||||
|
|
||||||
Object createProtocolEndpoint(RealmModel realm, EventBuilder event, AuthenticationManager authManager);
|
Object createProtocolEndpoint(RealmModel realm, EventBuilder event);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Setup default values for new clients. This expects that the representation has already set up the client
|
* Setup default values for new clients. This expects that the representation has already set up the client
|
|
@ -0,0 +1,16 @@
|
||||||
|
package org.keycloak.services.managers;
|
||||||
|
|
||||||
|
import org.keycloak.common.ClientConnection;
|
||||||
|
import org.keycloak.models.KeycloakSession;
|
||||||
|
import org.keycloak.models.RealmModel;
|
||||||
|
import org.keycloak.provider.Provider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
* @version $Revision: 1 $
|
||||||
|
*/
|
||||||
|
public interface BruteForceProtector extends Provider {
|
||||||
|
void failedLogin(RealmModel realm, String username, ClientConnection clientConnection);
|
||||||
|
|
||||||
|
boolean isTemporarilyDisabled(KeycloakSession session, RealmModel realm, String username);
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
package org.keycloak.services.managers;
|
||||||
|
|
||||||
|
import org.keycloak.provider.ProviderFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
* @version $Revision: 1 $
|
||||||
|
*/
|
||||||
|
public interface BruteForceProtectorFactory extends ProviderFactory<BruteForceProtector> {
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
package org.keycloak.services.managers;
|
||||||
|
|
||||||
|
import org.keycloak.models.UserFederationProvider;
|
||||||
|
import org.keycloak.models.UserFederationProviderFactory;
|
||||||
|
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 BruteForceProtectorSpi implements Spi {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isInternal() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "bruteForceProtector";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<? extends Provider> getProviderClass() {
|
||||||
|
return BruteForceProtector.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<? extends ProviderFactory> getProviderFactoryClass() {
|
||||||
|
return BruteForceProtectorFactory.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -11,3 +11,8 @@ org.keycloak.events.EventStoreSpi
|
||||||
org.keycloak.exportimport.ExportSpi
|
org.keycloak.exportimport.ExportSpi
|
||||||
org.keycloak.exportimport.ImportSpi
|
org.keycloak.exportimport.ImportSpi
|
||||||
org.keycloak.timer.TimerSpi
|
org.keycloak.timer.TimerSpi
|
||||||
|
org.keycloak.services.managers.BruteForceProtectorSpi
|
||||||
|
org.keycloak.protocol.ClientInstallationSpi
|
||||||
|
org.keycloak.protocol.LoginProtocolSpi
|
||||||
|
org.keycloak.protocol.ProtocolMapperSpi
|
||||||
|
|
||||||
|
|
|
@ -84,6 +84,13 @@ public class AuthenticationProcessor {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public BruteForceProtector getBruteForceProtector() {
|
||||||
|
if (protector == null) {
|
||||||
|
protector = session.getProvider(BruteForceProtector.class);
|
||||||
|
}
|
||||||
|
return protector;
|
||||||
|
}
|
||||||
|
|
||||||
public RealmModel getRealm() {
|
public RealmModel getRealm() {
|
||||||
return realm;
|
return realm;
|
||||||
}
|
}
|
||||||
|
@ -149,11 +156,6 @@ public class AuthenticationProcessor {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AuthenticationProcessor setProtector(BruteForceProtector protector) {
|
|
||||||
this.protector = protector;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public AuthenticationProcessor setEventBuilder(EventBuilder eventBuilder) {
|
public AuthenticationProcessor setEventBuilder(EventBuilder eventBuilder) {
|
||||||
this.event = eventBuilder;
|
this.event = eventBuilder;
|
||||||
return this;
|
return this;
|
||||||
|
@ -405,7 +407,7 @@ public class AuthenticationProcessor {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BruteForceProtector getProtector() {
|
public BruteForceProtector getProtector() {
|
||||||
return AuthenticationProcessor.this.protector;
|
return AuthenticationProcessor.this.getBruteForceProtector();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -571,7 +573,6 @@ public class AuthenticationProcessor {
|
||||||
.setForwardedSuccessMessage(reset.getSuccessMessage())
|
.setForwardedSuccessMessage(reset.getSuccessMessage())
|
||||||
.setConnection(connection)
|
.setConnection(connection)
|
||||||
.setEventBuilder(event)
|
.setEventBuilder(event)
|
||||||
.setProtector(protector)
|
|
||||||
.setRealm(realm)
|
.setRealm(realm)
|
||||||
.setSession(session)
|
.setSession(session)
|
||||||
.setUriInfo(uriInfo)
|
.setUriInfo(uriInfo)
|
||||||
|
|
|
@ -48,10 +48,9 @@ public abstract class AuthorizationEndpointBase {
|
||||||
@Context
|
@Context
|
||||||
protected ClientConnection clientConnection;
|
protected ClientConnection clientConnection;
|
||||||
|
|
||||||
public AuthorizationEndpointBase(RealmModel realm, EventBuilder event, AuthenticationManager authManager) {
|
public AuthorizationEndpointBase(RealmModel realm, EventBuilder event) {
|
||||||
this.realm = realm;
|
this.realm = realm;
|
||||||
this.event = event;
|
this.event = event;
|
||||||
this.authManager = authManager;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected AuthenticationProcessor createProcessor(ClientSessionModel clientSession, String flowId, String flowPath) {
|
protected AuthenticationProcessor createProcessor(ClientSessionModel clientSession, String flowId, String flowPath) {
|
||||||
|
@ -62,7 +61,6 @@ public abstract class AuthorizationEndpointBase {
|
||||||
.setBrowserFlow(true)
|
.setBrowserFlow(true)
|
||||||
.setConnection(clientConnection)
|
.setConnection(clientConnection)
|
||||||
.setEventBuilder(event)
|
.setEventBuilder(event)
|
||||||
.setProtector(authManager.getProtector())
|
|
||||||
.setRealm(realm)
|
.setRealm(realm)
|
||||||
.setSession(session)
|
.setSession(session)
|
||||||
.setUriInfo(uriInfo)
|
.setUriInfo(uriInfo)
|
||||||
|
|
|
@ -160,8 +160,8 @@ public class OIDCLoginProtocolFactory extends AbstractLoginProtocolFactory {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object createProtocolEndpoint(RealmModel realm, EventBuilder event, AuthenticationManager authManager) {
|
public Object createProtocolEndpoint(RealmModel realm, EventBuilder event) {
|
||||||
return new OIDCLoginProtocolService(realm, event, authManager);
|
return new OIDCLoginProtocolService(realm, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -45,7 +45,6 @@ public class OIDCLoginProtocolService {
|
||||||
private RealmModel realm;
|
private RealmModel realm;
|
||||||
private TokenManager tokenManager;
|
private TokenManager tokenManager;
|
||||||
private EventBuilder event;
|
private EventBuilder event;
|
||||||
private AuthenticationManager authManager;
|
|
||||||
|
|
||||||
@Context
|
@Context
|
||||||
private UriInfo uriInfo;
|
private UriInfo uriInfo;
|
||||||
|
@ -56,11 +55,10 @@ public class OIDCLoginProtocolService {
|
||||||
@Context
|
@Context
|
||||||
private HttpHeaders headers;
|
private HttpHeaders headers;
|
||||||
|
|
||||||
public OIDCLoginProtocolService(RealmModel realm, EventBuilder event, AuthenticationManager authManager) {
|
public OIDCLoginProtocolService(RealmModel realm, EventBuilder event) {
|
||||||
this.realm = realm;
|
this.realm = realm;
|
||||||
this.tokenManager = new TokenManager();
|
this.tokenManager = new TokenManager();
|
||||||
this.event = event;
|
this.event = event;
|
||||||
this.authManager = authManager;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UriBuilder tokenServiceBaseUrl(UriInfo uriInfo) {
|
public static UriBuilder tokenServiceBaseUrl(UriInfo uriInfo) {
|
||||||
|
@ -117,7 +115,7 @@ public class OIDCLoginProtocolService {
|
||||||
*/
|
*/
|
||||||
@Path("auth")
|
@Path("auth")
|
||||||
public Object auth() {
|
public Object auth() {
|
||||||
AuthorizationEndpoint endpoint = new AuthorizationEndpoint(authManager, realm, event);
|
AuthorizationEndpoint endpoint = new AuthorizationEndpoint(realm, event);
|
||||||
ResteasyProviderFactory.getInstance().injectProperties(endpoint);
|
ResteasyProviderFactory.getInstance().injectProperties(endpoint);
|
||||||
return endpoint;
|
return endpoint;
|
||||||
}
|
}
|
||||||
|
@ -127,7 +125,7 @@ public class OIDCLoginProtocolService {
|
||||||
*/
|
*/
|
||||||
@Path("registrations")
|
@Path("registrations")
|
||||||
public Object registerPage() {
|
public Object registerPage() {
|
||||||
AuthorizationEndpoint endpoint = new AuthorizationEndpoint(authManager, realm, event);
|
AuthorizationEndpoint endpoint = new AuthorizationEndpoint(realm, event);
|
||||||
ResteasyProviderFactory.getInstance().injectProperties(endpoint);
|
ResteasyProviderFactory.getInstance().injectProperties(endpoint);
|
||||||
return endpoint.register();
|
return endpoint.register();
|
||||||
}
|
}
|
||||||
|
@ -137,7 +135,7 @@ public class OIDCLoginProtocolService {
|
||||||
*/
|
*/
|
||||||
@Path("forgot-credentials")
|
@Path("forgot-credentials")
|
||||||
public Object forgotCredentialsPage() {
|
public Object forgotCredentialsPage() {
|
||||||
AuthorizationEndpoint endpoint = new AuthorizationEndpoint(authManager, realm, event);
|
AuthorizationEndpoint endpoint = new AuthorizationEndpoint(realm, event);
|
||||||
ResteasyProviderFactory.getInstance().injectProperties(endpoint);
|
ResteasyProviderFactory.getInstance().injectProperties(endpoint);
|
||||||
return endpoint.forgotCredentials();
|
return endpoint.forgotCredentials();
|
||||||
}
|
}
|
||||||
|
@ -147,7 +145,7 @@ public class OIDCLoginProtocolService {
|
||||||
*/
|
*/
|
||||||
@Path("token")
|
@Path("token")
|
||||||
public Object token() {
|
public Object token() {
|
||||||
TokenEndpoint endpoint = new TokenEndpoint(tokenManager, authManager, realm, event);
|
TokenEndpoint endpoint = new TokenEndpoint(tokenManager, realm, event);
|
||||||
ResteasyProviderFactory.getInstance().injectProperties(endpoint);
|
ResteasyProviderFactory.getInstance().injectProperties(endpoint);
|
||||||
return endpoint;
|
return endpoint;
|
||||||
}
|
}
|
||||||
|
@ -155,7 +153,7 @@ public class OIDCLoginProtocolService {
|
||||||
@Path("login")
|
@Path("login")
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public Object loginPage() {
|
public Object loginPage() {
|
||||||
AuthorizationEndpoint endpoint = new AuthorizationEndpoint(authManager, realm, event);
|
AuthorizationEndpoint endpoint = new AuthorizationEndpoint(realm, event);
|
||||||
ResteasyProviderFactory.getInstance().injectProperties(endpoint);
|
ResteasyProviderFactory.getInstance().injectProperties(endpoint);
|
||||||
return endpoint.legacy(OIDCLoginProtocol.CODE_PARAM);
|
return endpoint.legacy(OIDCLoginProtocol.CODE_PARAM);
|
||||||
}
|
}
|
||||||
|
@ -170,7 +168,7 @@ public class OIDCLoginProtocolService {
|
||||||
@Path("grants/access")
|
@Path("grants/access")
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public Object grantAccessToken() {
|
public Object grantAccessToken() {
|
||||||
TokenEndpoint endpoint = new TokenEndpoint(tokenManager, authManager, realm, event);
|
TokenEndpoint endpoint = new TokenEndpoint(tokenManager, realm, event);
|
||||||
ResteasyProviderFactory.getInstance().injectProperties(endpoint);
|
ResteasyProviderFactory.getInstance().injectProperties(endpoint);
|
||||||
return endpoint.legacy(OAuth2Constants.PASSWORD);
|
return endpoint.legacy(OAuth2Constants.PASSWORD);
|
||||||
}
|
}
|
||||||
|
@ -178,7 +176,7 @@ public class OIDCLoginProtocolService {
|
||||||
@Path("refresh")
|
@Path("refresh")
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public Object refreshAccessToken() {
|
public Object refreshAccessToken() {
|
||||||
TokenEndpoint endpoint = new TokenEndpoint(tokenManager, authManager, realm, event);
|
TokenEndpoint endpoint = new TokenEndpoint(tokenManager, realm, event);
|
||||||
ResteasyProviderFactory.getInstance().injectProperties(endpoint);
|
ResteasyProviderFactory.getInstance().injectProperties(endpoint);
|
||||||
return endpoint.legacy(OAuth2Constants.REFRESH_TOKEN);
|
return endpoint.legacy(OAuth2Constants.REFRESH_TOKEN);
|
||||||
}
|
}
|
||||||
|
@ -186,7 +184,7 @@ public class OIDCLoginProtocolService {
|
||||||
@Path("access/codes")
|
@Path("access/codes")
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public Object accessCodeToToken() {
|
public Object accessCodeToToken() {
|
||||||
TokenEndpoint endpoint = new TokenEndpoint(tokenManager, authManager, realm, event);
|
TokenEndpoint endpoint = new TokenEndpoint(tokenManager, realm, event);
|
||||||
ResteasyProviderFactory.getInstance().injectProperties(endpoint);
|
ResteasyProviderFactory.getInstance().injectProperties(endpoint);
|
||||||
return endpoint.legacy(OAuth2Constants.AUTHORIZATION_CODE);
|
return endpoint.legacy(OAuth2Constants.AUTHORIZATION_CODE);
|
||||||
}
|
}
|
||||||
|
@ -225,7 +223,7 @@ public class OIDCLoginProtocolService {
|
||||||
|
|
||||||
@Path("logout")
|
@Path("logout")
|
||||||
public Object logout() {
|
public Object logout() {
|
||||||
LogoutEndpoint endpoint = new LogoutEndpoint(tokenManager, authManager, realm, event);
|
LogoutEndpoint endpoint = new LogoutEndpoint(tokenManager, realm, event);
|
||||||
ResteasyProviderFactory.getInstance().injectProperties(endpoint);
|
ResteasyProviderFactory.getInstance().injectProperties(endpoint);
|
||||||
return endpoint;
|
return endpoint;
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,8 +63,8 @@ public class AuthorizationEndpoint extends AuthorizationEndpointBase {
|
||||||
|
|
||||||
private String legacyResponseType;
|
private String legacyResponseType;
|
||||||
|
|
||||||
public AuthorizationEndpoint(AuthenticationManager authManager, RealmModel realm, EventBuilder event) {
|
public AuthorizationEndpoint(RealmModel realm, EventBuilder event) {
|
||||||
super(realm, event, authManager);
|
super(realm, event);
|
||||||
event.event(EventType.LOGIN);
|
event.event(EventType.LOGIN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -61,13 +61,11 @@ public class LogoutEndpoint {
|
||||||
private UriInfo uriInfo;
|
private UriInfo uriInfo;
|
||||||
|
|
||||||
private TokenManager tokenManager;
|
private TokenManager tokenManager;
|
||||||
private AuthenticationManager authManager;
|
|
||||||
private RealmModel realm;
|
private RealmModel realm;
|
||||||
private EventBuilder event;
|
private EventBuilder event;
|
||||||
|
|
||||||
public LogoutEndpoint(TokenManager tokenManager, AuthenticationManager authManager, RealmModel realm, EventBuilder event) {
|
public LogoutEndpoint(TokenManager tokenManager, RealmModel realm, EventBuilder event) {
|
||||||
this.tokenManager = tokenManager;
|
this.tokenManager = tokenManager;
|
||||||
this.authManager = authManager;
|
|
||||||
this.realm = realm;
|
this.realm = realm;
|
||||||
this.event = event;
|
this.event = event;
|
||||||
}
|
}
|
||||||
|
@ -117,7 +115,7 @@ public class LogoutEndpoint {
|
||||||
}
|
}
|
||||||
|
|
||||||
// authenticate identity cookie, but ignore an access token timeout as we're logging out anyways.
|
// authenticate identity cookie, but ignore an access token timeout as we're logging out anyways.
|
||||||
AuthenticationManager.AuthResult authResult = authManager.authenticateIdentityCookie(session, realm, false);
|
AuthenticationManager.AuthResult authResult = AuthenticationManager.authenticateIdentityCookie(session, realm, false);
|
||||||
if (authResult != null) {
|
if (authResult != null) {
|
||||||
userSession = userSession != null ? userSession : authResult.getSession();
|
userSession = userSession != null ? userSession : authResult.getSession();
|
||||||
if (redirect != null) userSession.setNote(OIDCLoginProtocol.LOGOUT_REDIRECT_URI, redirect);
|
if (redirect != null) userSession.setNote(OIDCLoginProtocol.LOGOUT_REDIRECT_URI, redirect);
|
||||||
|
@ -129,7 +127,7 @@ public class LogoutEndpoint {
|
||||||
return response;
|
return response;
|
||||||
} else if (userSession != null) { // non browser logout
|
} else if (userSession != null) { // non browser logout
|
||||||
event.event(EventType.LOGOUT);
|
event.event(EventType.LOGOUT);
|
||||||
authManager.backchannelLogout(session, realm, userSession, uriInfo, clientConnection, headers, true);
|
AuthenticationManager.backchannelLogout(session, realm, userSession, uriInfo, clientConnection, headers, true);
|
||||||
event.user(userSession.getUser()).session(userSession).success();
|
event.user(userSession.getUser()).session(userSession).success();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -185,7 +183,7 @@ public class LogoutEndpoint {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void logout(UserSessionModel userSession) {
|
private void logout(UserSessionModel userSession) {
|
||||||
authManager.backchannelLogout(session, realm, userSession, uriInfo, clientConnection, headers, true);
|
AuthenticationManager.backchannelLogout(session, realm, userSession, uriInfo, clientConnection, headers, true);
|
||||||
event.user(userSession.getUser()).session(userSession).success();
|
event.user(userSession.getUser()).session(userSession).success();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -76,7 +76,6 @@ public class TokenEndpoint {
|
||||||
private ClientConnection clientConnection;
|
private ClientConnection clientConnection;
|
||||||
|
|
||||||
private final TokenManager tokenManager;
|
private final TokenManager tokenManager;
|
||||||
private final AuthenticationManager authManager;
|
|
||||||
private final RealmModel realm;
|
private final RealmModel realm;
|
||||||
private final EventBuilder event;
|
private final EventBuilder event;
|
||||||
|
|
||||||
|
@ -86,9 +85,8 @@ public class TokenEndpoint {
|
||||||
|
|
||||||
private String legacyGrantType;
|
private String legacyGrantType;
|
||||||
|
|
||||||
public TokenEndpoint(TokenManager tokenManager, AuthenticationManager authManager, RealmModel realm, EventBuilder event) {
|
public TokenEndpoint(TokenManager tokenManager, RealmModel realm, EventBuilder event) {
|
||||||
this.tokenManager = tokenManager;
|
this.tokenManager = tokenManager;
|
||||||
this.authManager = authManager;
|
|
||||||
this.realm = realm;
|
this.realm = realm;
|
||||||
this.event = event;
|
this.event = event;
|
||||||
}
|
}
|
||||||
|
@ -372,7 +370,6 @@ public class TokenEndpoint {
|
||||||
.setFlowId(flowId)
|
.setFlowId(flowId)
|
||||||
.setConnection(clientConnection)
|
.setConnection(clientConnection)
|
||||||
.setEventBuilder(event)
|
.setEventBuilder(event)
|
||||||
.setProtector(authManager.getProtector())
|
|
||||||
.setRealm(realm)
|
.setRealm(realm)
|
||||||
.setSession(session)
|
.setSession(session)
|
||||||
.setUriInfo(uriInfo)
|
.setUriInfo(uriInfo)
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package org.keycloak.services.listeners;
|
package org.keycloak.services.listeners;
|
||||||
|
|
||||||
import org.keycloak.models.KeycloakSessionFactory;
|
import org.keycloak.models.KeycloakSessionFactory;
|
||||||
import org.keycloak.services.managers.BruteForceProtector;
|
|
||||||
|
|
||||||
import javax.servlet.ServletContextEvent;
|
import javax.servlet.ServletContextEvent;
|
||||||
import javax.servlet.ServletContextListener;
|
import javax.servlet.ServletContextListener;
|
||||||
|
@ -17,10 +16,6 @@ public class KeycloakSessionDestroyListener implements ServletContextListener {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void contextDestroyed(ServletContextEvent sce) {
|
public void contextDestroyed(ServletContextEvent sce) {
|
||||||
BruteForceProtector protector = (BruteForceProtector) sce.getServletContext().getAttribute(BruteForceProtector.class.getName());
|
|
||||||
if (protector != null) {
|
|
||||||
protector.shutdown();
|
|
||||||
}
|
|
||||||
KeycloakSessionFactory sessionFactory = (KeycloakSessionFactory) sce.getServletContext().getAttribute(KeycloakSessionFactory.class.getName());
|
KeycloakSessionFactory sessionFactory = (KeycloakSessionFactory) sce.getServletContext().getAttribute(KeycloakSessionFactory.class.getName());
|
||||||
if (sessionFactory != null) {
|
if (sessionFactory != null) {
|
||||||
sessionFactory.close();
|
sessionFactory.close();
|
||||||
|
|
|
@ -70,19 +70,6 @@ public class AuthenticationManager {
|
||||||
public static final String KEYCLOAK_LOGOUT_PROTOCOL = "KEYCLOAK_LOGOUT_PROTOCOL";
|
public static final String KEYCLOAK_LOGOUT_PROTOCOL = "KEYCLOAK_LOGOUT_PROTOCOL";
|
||||||
public static final String CURRENT_REQUIRED_ACTION = "CURRENT_REQUIRED_ACTION";
|
public static final String CURRENT_REQUIRED_ACTION = "CURRENT_REQUIRED_ACTION";
|
||||||
|
|
||||||
protected BruteForceProtector protector;
|
|
||||||
|
|
||||||
public AuthenticationManager() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public AuthenticationManager(BruteForceProtector protector) {
|
|
||||||
this.protector = protector;
|
|
||||||
}
|
|
||||||
|
|
||||||
public BruteForceProtector getProtector() {
|
|
||||||
return protector;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean isSessionValid(RealmModel realm, UserSessionModel userSession) {
|
public static boolean isSessionValid(RealmModel realm, UserSessionModel userSession) {
|
||||||
if (userSession == null) {
|
if (userSession == null) {
|
||||||
logger.debug("No user session");
|
logger.debug("No user session");
|
||||||
|
|
|
@ -20,8 +20,8 @@ import java.util.concurrent.TimeUnit;
|
||||||
* @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 BruteForceProtector implements Runnable {
|
public class DefaultBruteForceProtector implements Runnable, BruteForceProtector {
|
||||||
protected static Logger logger = Logger.getLogger(BruteForceProtector.class);
|
protected static Logger logger = Logger.getLogger(DefaultBruteForceProtector.class);
|
||||||
|
|
||||||
protected volatile boolean run = true;
|
protected volatile boolean run = true;
|
||||||
protected int maxDeltaTimeSeconds = 60 * 60 * 12; // 12 hours
|
protected int maxDeltaTimeSeconds = 60 * 60 * 12; // 12 hours
|
||||||
|
@ -67,7 +67,7 @@ public class BruteForceProtector implements Runnable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public BruteForceProtector(KeycloakSessionFactory factory) {
|
public DefaultBruteForceProtector(KeycloakSessionFactory factory) {
|
||||||
this.factory = factory;
|
this.factory = factory;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -204,6 +204,7 @@ public class BruteForceProtector implements Runnable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void failedLogin(RealmModel realm, String username, ClientConnection clientConnection) {
|
public void failedLogin(RealmModel realm, String username, ClientConnection clientConnection) {
|
||||||
try {
|
try {
|
||||||
FailedLogin event = new FailedLogin(realm.getId(), username, clientConnection.getRemoteAddr());
|
FailedLogin event = new FailedLogin(realm.getId(), username, clientConnection.getRemoteAddr());
|
||||||
|
@ -217,6 +218,7 @@ public class BruteForceProtector implements Runnable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean isTemporarilyDisabled(KeycloakSession session, RealmModel realm, String username) {
|
public boolean isTemporarilyDisabled(KeycloakSession session, RealmModel realm, String username) {
|
||||||
UsernameLoginFailureModel failure = session.sessions().getUserLoginFailure(realm, username.toLowerCase());
|
UsernameLoginFailureModel failure = session.sessions().getUserLoginFailure(realm, username.toLowerCase());
|
||||||
if (failure == null) {
|
if (failure == null) {
|
||||||
|
@ -231,4 +233,8 @@ public class BruteForceProtector implements Runnable {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() {
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
package org.keycloak.services.managers;
|
||||||
|
|
||||||
|
import org.keycloak.Config;
|
||||||
|
import org.keycloak.models.KeycloakSession;
|
||||||
|
import org.keycloak.models.KeycloakSessionFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
* @version $Revision: 1 $
|
||||||
|
*/
|
||||||
|
public class DefaultBruteForceProtectorFactory implements BruteForceProtectorFactory {
|
||||||
|
DefaultBruteForceProtector protector;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BruteForceProtector create(KeycloakSession session) {
|
||||||
|
return protector;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init(Config.Scope config) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void postInit(KeycloakSessionFactory factory) {
|
||||||
|
protector = new DefaultBruteForceProtector(factory);
|
||||||
|
protector.start();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() {
|
||||||
|
protector.shutdown();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getId() {
|
||||||
|
return "default-brute-force-detector";
|
||||||
|
}
|
||||||
|
}
|
|
@ -699,7 +699,6 @@ public class IdentityBrokerService implements IdentityProvider.AuthenticationCal
|
||||||
.setFlowId(flowId)
|
.setFlowId(flowId)
|
||||||
.setConnection(clientConnection)
|
.setConnection(clientConnection)
|
||||||
.setEventBuilder(event)
|
.setEventBuilder(event)
|
||||||
.setProtector(protector)
|
|
||||||
.setRealm(realmModel)
|
.setRealm(realmModel)
|
||||||
.setSession(session)
|
.setSession(session)
|
||||||
.setUriInfo(uriInfo)
|
.setUriInfo(uriInfo)
|
||||||
|
|
|
@ -17,7 +17,6 @@ import org.keycloak.representations.idm.UserRepresentation;
|
||||||
import org.keycloak.services.DefaultKeycloakSessionFactory;
|
import org.keycloak.services.DefaultKeycloakSessionFactory;
|
||||||
import org.keycloak.services.filters.KeycloakTransactionCommitter;
|
import org.keycloak.services.filters.KeycloakTransactionCommitter;
|
||||||
import org.keycloak.services.managers.ApplianceBootstrap;
|
import org.keycloak.services.managers.ApplianceBootstrap;
|
||||||
import org.keycloak.services.managers.BruteForceProtector;
|
|
||||||
import org.keycloak.services.managers.RealmManager;
|
import org.keycloak.services.managers.RealmManager;
|
||||||
import org.keycloak.services.managers.UsersSyncManager;
|
import org.keycloak.services.managers.UsersSyncManager;
|
||||||
import org.keycloak.services.resources.admin.AdminRoot;
|
import org.keycloak.services.resources.admin.AdminRoot;
|
||||||
|
@ -60,12 +59,7 @@ public class KeycloakApplication extends Application {
|
||||||
this.sessionFactory = createSessionFactory();
|
this.sessionFactory = createSessionFactory();
|
||||||
|
|
||||||
dispatcher.getDefaultContextObjects().put(KeycloakApplication.class, this);
|
dispatcher.getDefaultContextObjects().put(KeycloakApplication.class, this);
|
||||||
BruteForceProtector protector = new BruteForceProtector(sessionFactory);
|
|
||||||
dispatcher.getDefaultContextObjects().put(BruteForceProtector.class, protector);
|
|
||||||
ResteasyProviderFactory.pushContext(BruteForceProtector.class, protector); // for injection
|
|
||||||
ResteasyProviderFactory.pushContext(KeycloakApplication.class, this); // for injection
|
ResteasyProviderFactory.pushContext(KeycloakApplication.class, this); // for injection
|
||||||
protector.start();
|
|
||||||
context.setAttribute(BruteForceProtector.class.getName(), protector);
|
|
||||||
context.setAttribute(KeycloakSessionFactory.class.getName(), this.sessionFactory);
|
context.setAttribute(KeycloakSessionFactory.class.getName(), this.sessionFactory);
|
||||||
|
|
||||||
singletons.add(new ServerVersionResource());
|
singletons.add(new ServerVersionResource());
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
*/
|
*/
|
||||||
package org.keycloak.services.resources;
|
package org.keycloak.services.resources;
|
||||||
|
|
||||||
|
import org.apache.http.auth.AUTH;
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
import org.jboss.resteasy.spi.HttpRequest;
|
import org.jboss.resteasy.spi.HttpRequest;
|
||||||
import org.keycloak.authentication.authenticators.broker.AbstractIdpAuthenticator;
|
import org.keycloak.authentication.authenticators.broker.AbstractIdpAuthenticator;
|
||||||
|
@ -121,8 +122,6 @@ public class LoginActionsService {
|
||||||
@Context
|
@Context
|
||||||
protected KeycloakSession session;
|
protected KeycloakSession session;
|
||||||
|
|
||||||
private AuthenticationManager authManager;
|
|
||||||
|
|
||||||
private EventBuilder event;
|
private EventBuilder event;
|
||||||
|
|
||||||
public static UriBuilder loginActionsBaseUrl(UriInfo uriInfo) {
|
public static UriBuilder loginActionsBaseUrl(UriInfo uriInfo) {
|
||||||
|
@ -154,9 +153,8 @@ public class LoginActionsService {
|
||||||
return baseUriBuilder.path(RealmsResource.class).path(RealmsResource.class, "getLoginActionsService");
|
return baseUriBuilder.path(RealmsResource.class).path(RealmsResource.class, "getLoginActionsService");
|
||||||
}
|
}
|
||||||
|
|
||||||
public LoginActionsService(RealmModel realm, AuthenticationManager authManager, EventBuilder event) {
|
public LoginActionsService(RealmModel realm, EventBuilder event) {
|
||||||
this.realm = realm;
|
this.realm = realm;
|
||||||
this.authManager = authManager;
|
|
||||||
this.event = event;
|
this.event = event;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -293,7 +291,6 @@ public class LoginActionsService {
|
||||||
.setFlowId(flow.getId())
|
.setFlowId(flow.getId())
|
||||||
.setConnection(clientConnection)
|
.setConnection(clientConnection)
|
||||||
.setEventBuilder(event)
|
.setEventBuilder(event)
|
||||||
.setProtector(authManager.getProtector())
|
|
||||||
.setRealm(realm)
|
.setRealm(realm)
|
||||||
.setSession(session)
|
.setSession(session)
|
||||||
.setUriInfo(uriInfo)
|
.setUriInfo(uriInfo)
|
||||||
|
@ -454,7 +451,7 @@ public class LoginActionsService {
|
||||||
ClientSessionModel clientSession = clientSessionCode.getClientSession();
|
ClientSessionModel clientSession = clientSessionCode.getClientSession();
|
||||||
|
|
||||||
|
|
||||||
authManager.expireIdentityCookie(realm, uriInfo, clientConnection);
|
AuthenticationManager.expireIdentityCookie(realm, uriInfo, clientConnection);
|
||||||
|
|
||||||
return processRegistration(execution, clientSession, null);
|
return processRegistration(execution, clientSession, null);
|
||||||
}
|
}
|
||||||
|
@ -648,7 +645,7 @@ public class LoginActionsService {
|
||||||
event.detail(Details.CONSENT, Details.CONSENT_VALUE_CONSENT_GRANTED);
|
event.detail(Details.CONSENT, Details.CONSENT_VALUE_CONSENT_GRANTED);
|
||||||
event.success();
|
event.success();
|
||||||
|
|
||||||
return authManager.redirectAfterSuccessfulFlow(session, realm, userSession, clientSession, request, uriInfo, clientConnection, event);
|
return AuthenticationManager.redirectAfterSuccessfulFlow(session, realm, userSession, clientSession, request, uriInfo, clientConnection, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Path("email-verification")
|
@Path("email-verification")
|
||||||
|
|
|
@ -81,10 +81,9 @@ public class RealmsResource {
|
||||||
RealmModel realm = init(name);
|
RealmModel realm = init(name);
|
||||||
|
|
||||||
EventBuilder event = new EventBuilder(realm, session, clientConnection);
|
EventBuilder event = new EventBuilder(realm, session, clientConnection);
|
||||||
AuthenticationManager authManager = new AuthenticationManager(protector);
|
|
||||||
|
|
||||||
LoginProtocolFactory factory = (LoginProtocolFactory)session.getKeycloakSessionFactory().getProviderFactory(LoginProtocol.class, OIDCLoginProtocol.LOGIN_PROTOCOL);
|
LoginProtocolFactory factory = (LoginProtocolFactory)session.getKeycloakSessionFactory().getProviderFactory(LoginProtocol.class, OIDCLoginProtocol.LOGIN_PROTOCOL);
|
||||||
OIDCLoginProtocolService endpoint = (OIDCLoginProtocolService)factory.createProtocolEndpoint(realm, event, authManager);
|
OIDCLoginProtocolService endpoint = (OIDCLoginProtocolService)factory.createProtocolEndpoint(realm, event);
|
||||||
|
|
||||||
ResteasyProviderFactory.getInstance().injectProperties(endpoint);
|
ResteasyProviderFactory.getInstance().injectProperties(endpoint);
|
||||||
return endpoint.getLoginStatusIframe();
|
return endpoint.getLoginStatusIframe();
|
||||||
|
@ -97,10 +96,9 @@ public class RealmsResource {
|
||||||
RealmModel realm = init(name);
|
RealmModel realm = init(name);
|
||||||
|
|
||||||
EventBuilder event = new EventBuilder(realm, session, clientConnection);
|
EventBuilder event = new EventBuilder(realm, session, clientConnection);
|
||||||
AuthenticationManager authManager = new AuthenticationManager(protector);
|
|
||||||
|
|
||||||
LoginProtocolFactory factory = (LoginProtocolFactory)session.getKeycloakSessionFactory().getProviderFactory(LoginProtocol.class, protocol);
|
LoginProtocolFactory factory = (LoginProtocolFactory)session.getKeycloakSessionFactory().getProviderFactory(LoginProtocol.class, protocol);
|
||||||
Object endpoint = factory.createProtocolEndpoint(realm, event, authManager);
|
Object endpoint = factory.createProtocolEndpoint(realm, event);
|
||||||
|
|
||||||
ResteasyProviderFactory.getInstance().injectProperties(endpoint);
|
ResteasyProviderFactory.getInstance().injectProperties(endpoint);
|
||||||
return endpoint;
|
return endpoint;
|
||||||
|
@ -117,8 +115,7 @@ public class RealmsResource {
|
||||||
public LoginActionsService getLoginActionsService(final @PathParam("realm") String name) {
|
public LoginActionsService getLoginActionsService(final @PathParam("realm") String name) {
|
||||||
RealmModel realm = init(name);
|
RealmModel realm = init(name);
|
||||||
EventBuilder event = new EventBuilder(realm, session, clientConnection);
|
EventBuilder event = new EventBuilder(realm, session, clientConnection);
|
||||||
AuthenticationManager authManager = new AuthenticationManager(protector);
|
LoginActionsService service = new LoginActionsService(realm, event);
|
||||||
LoginActionsService service = new LoginActionsService(realm, authManager, event);
|
|
||||||
ResteasyProviderFactory.getInstance().injectProperties(service);
|
ResteasyProviderFactory.getInstance().injectProperties(service);
|
||||||
return service;
|
return service;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
org.keycloak.protocol.LoginProtocolSpi
|
|
||||||
org.keycloak.protocol.ProtocolMapperSpi
|
|
||||||
org.keycloak.exportimport.ClientDescriptionConverterSpi
|
org.keycloak.exportimport.ClientDescriptionConverterSpi
|
||||||
org.keycloak.wellknown.WellKnownSpi
|
org.keycloak.wellknown.WellKnownSpi
|
||||||
org.keycloak.messages.MessagesSpi
|
org.keycloak.messages.MessagesSpi
|
||||||
|
@ -9,4 +7,3 @@ org.keycloak.authentication.RequiredActionSpi
|
||||||
org.keycloak.authentication.FormAuthenticatorSpi
|
org.keycloak.authentication.FormAuthenticatorSpi
|
||||||
org.keycloak.authentication.FormActionSpi
|
org.keycloak.authentication.FormActionSpi
|
||||||
org.keycloak.services.clientregistration.ClientRegistrationSpi
|
org.keycloak.services.clientregistration.ClientRegistrationSpi
|
||||||
org.keycloak.protocol.ClientInstallationSpi
|
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
org.keycloak.services.managers.DefaultBruteForceProtectorFactory
|
Loading…
Reference in a new issue