From 007e9530ecd638f9aa23d43ae81110ae818bced3 Mon Sep 17 00:00:00 2001 From: Bill Burke Date: Fri, 15 Jan 2016 19:25:28 -0500 Subject: [PATCH] brute force refactr, mv protocol --- .../protocol/saml/SamlProtocolFactory.java | 4 +- .../keycloak/protocol/saml/SamlService.java | 6 +-- .../profile/ecp/SamlEcpProfileService.java | 4 +- .../AbstractLoginProtocolFactory.java | 0 .../protocol/ClientInstallationProvider.java | 0 .../protocol/ClientInstallationSpi.java | 0 .../org/keycloak/protocol/LoginProtocol.java | 0 .../protocol/LoginProtocolFactory.java | 2 +- .../keycloak/protocol/LoginProtocolSpi.java | 0 .../org/keycloak/protocol/ProtocolMapper.java | 0 .../keycloak/protocol/ProtocolMapperSpi.java | 0 .../managers/BruteForceProtector.java | 16 ++++++++ .../managers/BruteForceProtectorFactory.java | 10 +++++ .../managers/BruteForceProtectorSpi.java | 34 +++++++++++++++ .../services/managers/ClientSessionCode.java | 0 .../services/org.keycloak.provider.Spi | 5 +++ .../AuthenticationProcessor.java | 15 +++---- .../protocol/AuthorizationEndpointBase.java | 4 +- .../oidc/OIDCLoginProtocolFactory.java | 4 +- .../oidc/OIDCLoginProtocolService.java | 22 +++++----- .../oidc/endpoints/AuthorizationEndpoint.java | 4 +- .../oidc/endpoints/LogoutEndpoint.java | 10 ++--- .../oidc/endpoints/TokenEndpoint.java | 5 +-- .../KeycloakSessionDestroyListener.java | 5 --- .../managers/AuthenticationManager.java | 13 ------ ...r.java => DefaultBruteForceProtector.java} | 12 ++++-- .../DefaultBruteForceProtectorFactory.java | 41 +++++++++++++++++++ .../resources/IdentityBrokerService.java | 1 - .../resources/KeycloakApplication.java | 6 --- .../resources/LoginActionsService.java | 11 ++--- .../services/resources/RealmsResource.java | 9 ++-- .../services/org.keycloak.provider.Spi | 3 -- ...rvices.managers.BruteForceProtectorFactory | 1 + 33 files changed, 159 insertions(+), 88 deletions(-) rename {services => server-spi}/src/main/java/org/keycloak/protocol/AbstractLoginProtocolFactory.java (100%) rename {services => server-spi}/src/main/java/org/keycloak/protocol/ClientInstallationProvider.java (100%) rename {services => server-spi}/src/main/java/org/keycloak/protocol/ClientInstallationSpi.java (100%) rename {services => server-spi}/src/main/java/org/keycloak/protocol/LoginProtocol.java (100%) rename {services => server-spi}/src/main/java/org/keycloak/protocol/LoginProtocolFactory.java (97%) rename {services => server-spi}/src/main/java/org/keycloak/protocol/LoginProtocolSpi.java (100%) rename {services => server-spi}/src/main/java/org/keycloak/protocol/ProtocolMapper.java (100%) rename {services => server-spi}/src/main/java/org/keycloak/protocol/ProtocolMapperSpi.java (100%) create mode 100755 server-spi/src/main/java/org/keycloak/services/managers/BruteForceProtector.java create mode 100755 server-spi/src/main/java/org/keycloak/services/managers/BruteForceProtectorFactory.java create mode 100755 server-spi/src/main/java/org/keycloak/services/managers/BruteForceProtectorSpi.java rename {services => server-spi}/src/main/java/org/keycloak/services/managers/ClientSessionCode.java (100%) rename services/src/main/java/org/keycloak/services/managers/{BruteForceProtector.java => DefaultBruteForceProtector.java} (96%) create mode 100755 services/src/main/java/org/keycloak/services/managers/DefaultBruteForceProtectorFactory.java create mode 100755 services/src/main/resources/META-INF/services/org.keycloak.services.managers.BruteForceProtectorFactory diff --git a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlProtocolFactory.java b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlProtocolFactory.java index 1de9f456aa..db84f1dddb 100755 --- a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlProtocolFactory.java +++ b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlProtocolFactory.java @@ -32,8 +32,8 @@ import java.util.List; public class SamlProtocolFactory extends AbstractLoginProtocolFactory { @Override - public Object createProtocolEndpoint(RealmModel realm, EventBuilder event, AuthenticationManager authManager) { - return new SamlService(realm, event, authManager); + public Object createProtocolEndpoint(RealmModel realm, EventBuilder event) { + return new SamlService(realm, event); } @Override diff --git a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlService.java b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlService.java index 1f9073577e..df3bb4e0ac 100755 --- a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlService.java +++ b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlService.java @@ -61,8 +61,8 @@ public class SamlService extends AuthorizationEndpointBase { protected static final Logger logger = Logger.getLogger(SamlService.class); - public SamlService(RealmModel realm, EventBuilder event, AuthenticationManager authManager) { - super(realm, event, authManager); + public SamlService(RealmModel realm, EventBuilder event) { + super(realm, event); } public abstract class BindingProtocol { @@ -556,7 +556,7 @@ public class SamlService extends AuthorizationEndpointBase { @POST @Consumes("application/soap+xml") public Response soapBinding(InputStream inputStream) { - SamlEcpProfileService bindingService = new SamlEcpProfileService(realm, event, authManager); + SamlEcpProfileService bindingService = new SamlEcpProfileService(realm, event); ResteasyProviderFactory.getInstance().injectProperties(bindingService); diff --git a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/profile/ecp/SamlEcpProfileService.java b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/profile/ecp/SamlEcpProfileService.java index f2623464b9..24c8bf2d1c 100755 --- a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/profile/ecp/SamlEcpProfileService.java +++ b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/profile/ecp/SamlEcpProfileService.java @@ -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_ASSERTION = "saml"; - public SamlEcpProfileService(RealmModel realm, EventBuilder event, AuthenticationManager authManager) { - super(realm, event, authManager); + public SamlEcpProfileService(RealmModel realm, EventBuilder event) { + super(realm, event); } public Response authenticate(InputStream inputStream) { diff --git a/services/src/main/java/org/keycloak/protocol/AbstractLoginProtocolFactory.java b/server-spi/src/main/java/org/keycloak/protocol/AbstractLoginProtocolFactory.java similarity index 100% rename from services/src/main/java/org/keycloak/protocol/AbstractLoginProtocolFactory.java rename to server-spi/src/main/java/org/keycloak/protocol/AbstractLoginProtocolFactory.java diff --git a/services/src/main/java/org/keycloak/protocol/ClientInstallationProvider.java b/server-spi/src/main/java/org/keycloak/protocol/ClientInstallationProvider.java similarity index 100% rename from services/src/main/java/org/keycloak/protocol/ClientInstallationProvider.java rename to server-spi/src/main/java/org/keycloak/protocol/ClientInstallationProvider.java diff --git a/services/src/main/java/org/keycloak/protocol/ClientInstallationSpi.java b/server-spi/src/main/java/org/keycloak/protocol/ClientInstallationSpi.java similarity index 100% rename from services/src/main/java/org/keycloak/protocol/ClientInstallationSpi.java rename to server-spi/src/main/java/org/keycloak/protocol/ClientInstallationSpi.java diff --git a/services/src/main/java/org/keycloak/protocol/LoginProtocol.java b/server-spi/src/main/java/org/keycloak/protocol/LoginProtocol.java similarity index 100% rename from services/src/main/java/org/keycloak/protocol/LoginProtocol.java rename to server-spi/src/main/java/org/keycloak/protocol/LoginProtocol.java diff --git a/services/src/main/java/org/keycloak/protocol/LoginProtocolFactory.java b/server-spi/src/main/java/org/keycloak/protocol/LoginProtocolFactory.java similarity index 97% rename from services/src/main/java/org/keycloak/protocol/LoginProtocolFactory.java rename to server-spi/src/main/java/org/keycloak/protocol/LoginProtocolFactory.java index 2238e6f21f..2419d4676e 100755 --- a/services/src/main/java/org/keycloak/protocol/LoginProtocolFactory.java +++ b/server-spi/src/main/java/org/keycloak/protocol/LoginProtocolFactory.java @@ -30,7 +30,7 @@ public interface LoginProtocolFactory extends ProviderFactory { */ List 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 diff --git a/services/src/main/java/org/keycloak/protocol/LoginProtocolSpi.java b/server-spi/src/main/java/org/keycloak/protocol/LoginProtocolSpi.java similarity index 100% rename from services/src/main/java/org/keycloak/protocol/LoginProtocolSpi.java rename to server-spi/src/main/java/org/keycloak/protocol/LoginProtocolSpi.java diff --git a/services/src/main/java/org/keycloak/protocol/ProtocolMapper.java b/server-spi/src/main/java/org/keycloak/protocol/ProtocolMapper.java similarity index 100% rename from services/src/main/java/org/keycloak/protocol/ProtocolMapper.java rename to server-spi/src/main/java/org/keycloak/protocol/ProtocolMapper.java diff --git a/services/src/main/java/org/keycloak/protocol/ProtocolMapperSpi.java b/server-spi/src/main/java/org/keycloak/protocol/ProtocolMapperSpi.java similarity index 100% rename from services/src/main/java/org/keycloak/protocol/ProtocolMapperSpi.java rename to server-spi/src/main/java/org/keycloak/protocol/ProtocolMapperSpi.java diff --git a/server-spi/src/main/java/org/keycloak/services/managers/BruteForceProtector.java b/server-spi/src/main/java/org/keycloak/services/managers/BruteForceProtector.java new file mode 100755 index 0000000000..7ce6f6a959 --- /dev/null +++ b/server-spi/src/main/java/org/keycloak/services/managers/BruteForceProtector.java @@ -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 Bill Burke + * @version $Revision: 1 $ + */ +public interface BruteForceProtector extends Provider { + void failedLogin(RealmModel realm, String username, ClientConnection clientConnection); + + boolean isTemporarilyDisabled(KeycloakSession session, RealmModel realm, String username); +} diff --git a/server-spi/src/main/java/org/keycloak/services/managers/BruteForceProtectorFactory.java b/server-spi/src/main/java/org/keycloak/services/managers/BruteForceProtectorFactory.java new file mode 100755 index 0000000000..555ff53b59 --- /dev/null +++ b/server-spi/src/main/java/org/keycloak/services/managers/BruteForceProtectorFactory.java @@ -0,0 +1,10 @@ +package org.keycloak.services.managers; + +import org.keycloak.provider.ProviderFactory; + +/** + * @author Bill Burke + * @version $Revision: 1 $ + */ +public interface BruteForceProtectorFactory extends ProviderFactory { +} diff --git a/server-spi/src/main/java/org/keycloak/services/managers/BruteForceProtectorSpi.java b/server-spi/src/main/java/org/keycloak/services/managers/BruteForceProtectorSpi.java new file mode 100755 index 0000000000..1196af8bdc --- /dev/null +++ b/server-spi/src/main/java/org/keycloak/services/managers/BruteForceProtectorSpi.java @@ -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 Stian Thorgersen + */ +public class BruteForceProtectorSpi implements Spi { + + @Override + public boolean isInternal() { + return true; + } + + @Override + public String getName() { + return "bruteForceProtector"; + } + + @Override + public Class getProviderClass() { + return BruteForceProtector.class; + } + + @Override + public Class getProviderFactoryClass() { + return BruteForceProtectorFactory.class; + } + +} diff --git a/services/src/main/java/org/keycloak/services/managers/ClientSessionCode.java b/server-spi/src/main/java/org/keycloak/services/managers/ClientSessionCode.java similarity index 100% rename from services/src/main/java/org/keycloak/services/managers/ClientSessionCode.java rename to server-spi/src/main/java/org/keycloak/services/managers/ClientSessionCode.java diff --git a/server-spi/src/main/resources/META-INF/services/org.keycloak.provider.Spi b/server-spi/src/main/resources/META-INF/services/org.keycloak.provider.Spi index cbea53ae75..907917f967 100755 --- a/server-spi/src/main/resources/META-INF/services/org.keycloak.provider.Spi +++ b/server-spi/src/main/resources/META-INF/services/org.keycloak.provider.Spi @@ -11,3 +11,8 @@ org.keycloak.events.EventStoreSpi org.keycloak.exportimport.ExportSpi org.keycloak.exportimport.ImportSpi org.keycloak.timer.TimerSpi +org.keycloak.services.managers.BruteForceProtectorSpi +org.keycloak.protocol.ClientInstallationSpi +org.keycloak.protocol.LoginProtocolSpi +org.keycloak.protocol.ProtocolMapperSpi + diff --git a/services/src/main/java/org/keycloak/authentication/AuthenticationProcessor.java b/services/src/main/java/org/keycloak/authentication/AuthenticationProcessor.java index b3123cb042..65f3c5cde1 100755 --- a/services/src/main/java/org/keycloak/authentication/AuthenticationProcessor.java +++ b/services/src/main/java/org/keycloak/authentication/AuthenticationProcessor.java @@ -84,6 +84,13 @@ public class AuthenticationProcessor { return this; } + public BruteForceProtector getBruteForceProtector() { + if (protector == null) { + protector = session.getProvider(BruteForceProtector.class); + } + return protector; + } + public RealmModel getRealm() { return realm; } @@ -149,11 +156,6 @@ public class AuthenticationProcessor { return this; } - public AuthenticationProcessor setProtector(BruteForceProtector protector) { - this.protector = protector; - return this; - } - public AuthenticationProcessor setEventBuilder(EventBuilder eventBuilder) { this.event = eventBuilder; return this; @@ -405,7 +407,7 @@ public class AuthenticationProcessor { @Override public BruteForceProtector getProtector() { - return AuthenticationProcessor.this.protector; + return AuthenticationProcessor.this.getBruteForceProtector(); } @Override @@ -571,7 +573,6 @@ public class AuthenticationProcessor { .setForwardedSuccessMessage(reset.getSuccessMessage()) .setConnection(connection) .setEventBuilder(event) - .setProtector(protector) .setRealm(realm) .setSession(session) .setUriInfo(uriInfo) diff --git a/services/src/main/java/org/keycloak/protocol/AuthorizationEndpointBase.java b/services/src/main/java/org/keycloak/protocol/AuthorizationEndpointBase.java index 9b11535301..4ac200aec2 100755 --- a/services/src/main/java/org/keycloak/protocol/AuthorizationEndpointBase.java +++ b/services/src/main/java/org/keycloak/protocol/AuthorizationEndpointBase.java @@ -48,10 +48,9 @@ public abstract class AuthorizationEndpointBase { @Context protected ClientConnection clientConnection; - public AuthorizationEndpointBase(RealmModel realm, EventBuilder event, AuthenticationManager authManager) { + public AuthorizationEndpointBase(RealmModel realm, EventBuilder event) { this.realm = realm; this.event = event; - this.authManager = authManager; } protected AuthenticationProcessor createProcessor(ClientSessionModel clientSession, String flowId, String flowPath) { @@ -62,7 +61,6 @@ public abstract class AuthorizationEndpointBase { .setBrowserFlow(true) .setConnection(clientConnection) .setEventBuilder(event) - .setProtector(authManager.getProtector()) .setRealm(realm) .setSession(session) .setUriInfo(uriInfo) diff --git a/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocolFactory.java b/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocolFactory.java index ee710cec48..a215e4cc06 100755 --- a/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocolFactory.java +++ b/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocolFactory.java @@ -160,8 +160,8 @@ public class OIDCLoginProtocolFactory extends AbstractLoginProtocolFactory { } @Override - public Object createProtocolEndpoint(RealmModel realm, EventBuilder event, AuthenticationManager authManager) { - return new OIDCLoginProtocolService(realm, event, authManager); + public Object createProtocolEndpoint(RealmModel realm, EventBuilder event) { + return new OIDCLoginProtocolService(realm, event); } @Override diff --git a/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocolService.java b/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocolService.java index 456a1287c8..613b048900 100755 --- a/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocolService.java +++ b/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocolService.java @@ -45,7 +45,6 @@ public class OIDCLoginProtocolService { private RealmModel realm; private TokenManager tokenManager; private EventBuilder event; - private AuthenticationManager authManager; @Context private UriInfo uriInfo; @@ -56,11 +55,10 @@ public class OIDCLoginProtocolService { @Context private HttpHeaders headers; - public OIDCLoginProtocolService(RealmModel realm, EventBuilder event, AuthenticationManager authManager) { + public OIDCLoginProtocolService(RealmModel realm, EventBuilder event) { this.realm = realm; this.tokenManager = new TokenManager(); this.event = event; - this.authManager = authManager; } public static UriBuilder tokenServiceBaseUrl(UriInfo uriInfo) { @@ -117,7 +115,7 @@ public class OIDCLoginProtocolService { */ @Path("auth") public Object auth() { - AuthorizationEndpoint endpoint = new AuthorizationEndpoint(authManager, realm, event); + AuthorizationEndpoint endpoint = new AuthorizationEndpoint(realm, event); ResteasyProviderFactory.getInstance().injectProperties(endpoint); return endpoint; } @@ -127,7 +125,7 @@ public class OIDCLoginProtocolService { */ @Path("registrations") public Object registerPage() { - AuthorizationEndpoint endpoint = new AuthorizationEndpoint(authManager, realm, event); + AuthorizationEndpoint endpoint = new AuthorizationEndpoint(realm, event); ResteasyProviderFactory.getInstance().injectProperties(endpoint); return endpoint.register(); } @@ -137,7 +135,7 @@ public class OIDCLoginProtocolService { */ @Path("forgot-credentials") public Object forgotCredentialsPage() { - AuthorizationEndpoint endpoint = new AuthorizationEndpoint(authManager, realm, event); + AuthorizationEndpoint endpoint = new AuthorizationEndpoint(realm, event); ResteasyProviderFactory.getInstance().injectProperties(endpoint); return endpoint.forgotCredentials(); } @@ -147,7 +145,7 @@ public class OIDCLoginProtocolService { */ @Path("token") public Object token() { - TokenEndpoint endpoint = new TokenEndpoint(tokenManager, authManager, realm, event); + TokenEndpoint endpoint = new TokenEndpoint(tokenManager, realm, event); ResteasyProviderFactory.getInstance().injectProperties(endpoint); return endpoint; } @@ -155,7 +153,7 @@ public class OIDCLoginProtocolService { @Path("login") @Deprecated public Object loginPage() { - AuthorizationEndpoint endpoint = new AuthorizationEndpoint(authManager, realm, event); + AuthorizationEndpoint endpoint = new AuthorizationEndpoint(realm, event); ResteasyProviderFactory.getInstance().injectProperties(endpoint); return endpoint.legacy(OIDCLoginProtocol.CODE_PARAM); } @@ -170,7 +168,7 @@ public class OIDCLoginProtocolService { @Path("grants/access") @Deprecated public Object grantAccessToken() { - TokenEndpoint endpoint = new TokenEndpoint(tokenManager, authManager, realm, event); + TokenEndpoint endpoint = new TokenEndpoint(tokenManager, realm, event); ResteasyProviderFactory.getInstance().injectProperties(endpoint); return endpoint.legacy(OAuth2Constants.PASSWORD); } @@ -178,7 +176,7 @@ public class OIDCLoginProtocolService { @Path("refresh") @Deprecated public Object refreshAccessToken() { - TokenEndpoint endpoint = new TokenEndpoint(tokenManager, authManager, realm, event); + TokenEndpoint endpoint = new TokenEndpoint(tokenManager, realm, event); ResteasyProviderFactory.getInstance().injectProperties(endpoint); return endpoint.legacy(OAuth2Constants.REFRESH_TOKEN); } @@ -186,7 +184,7 @@ public class OIDCLoginProtocolService { @Path("access/codes") @Deprecated public Object accessCodeToToken() { - TokenEndpoint endpoint = new TokenEndpoint(tokenManager, authManager, realm, event); + TokenEndpoint endpoint = new TokenEndpoint(tokenManager, realm, event); ResteasyProviderFactory.getInstance().injectProperties(endpoint); return endpoint.legacy(OAuth2Constants.AUTHORIZATION_CODE); } @@ -225,7 +223,7 @@ public class OIDCLoginProtocolService { @Path("logout") public Object logout() { - LogoutEndpoint endpoint = new LogoutEndpoint(tokenManager, authManager, realm, event); + LogoutEndpoint endpoint = new LogoutEndpoint(tokenManager, realm, event); ResteasyProviderFactory.getInstance().injectProperties(endpoint); return endpoint; } diff --git a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/AuthorizationEndpoint.java b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/AuthorizationEndpoint.java index 9ed45de00c..7e69581a66 100755 --- a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/AuthorizationEndpoint.java +++ b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/AuthorizationEndpoint.java @@ -63,8 +63,8 @@ public class AuthorizationEndpoint extends AuthorizationEndpointBase { private String legacyResponseType; - public AuthorizationEndpoint(AuthenticationManager authManager, RealmModel realm, EventBuilder event) { - super(realm, event, authManager); + public AuthorizationEndpoint(RealmModel realm, EventBuilder event) { + super(realm, event); event.event(EventType.LOGIN); } diff --git a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/LogoutEndpoint.java b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/LogoutEndpoint.java index 2250dd076f..8453daaa0d 100755 --- a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/LogoutEndpoint.java +++ b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/LogoutEndpoint.java @@ -61,13 +61,11 @@ public class LogoutEndpoint { private UriInfo uriInfo; private TokenManager tokenManager; - private AuthenticationManager authManager; private RealmModel realm; 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.authManager = authManager; this.realm = realm; 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. - AuthenticationManager.AuthResult authResult = authManager.authenticateIdentityCookie(session, realm, false); + AuthenticationManager.AuthResult authResult = AuthenticationManager.authenticateIdentityCookie(session, realm, false); if (authResult != null) { userSession = userSession != null ? userSession : authResult.getSession(); if (redirect != null) userSession.setNote(OIDCLoginProtocol.LOGOUT_REDIRECT_URI, redirect); @@ -129,7 +127,7 @@ public class LogoutEndpoint { return response; } else if (userSession != null) { // non browser 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(); } @@ -185,7 +183,7 @@ public class LogoutEndpoint { } 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(); } diff --git a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/TokenEndpoint.java b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/TokenEndpoint.java index d937ff985e..8f875e1113 100755 --- a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/TokenEndpoint.java +++ b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/TokenEndpoint.java @@ -76,7 +76,6 @@ public class TokenEndpoint { private ClientConnection clientConnection; private final TokenManager tokenManager; - private final AuthenticationManager authManager; private final RealmModel realm; private final EventBuilder event; @@ -86,9 +85,8 @@ public class TokenEndpoint { 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.authManager = authManager; this.realm = realm; this.event = event; } @@ -372,7 +370,6 @@ public class TokenEndpoint { .setFlowId(flowId) .setConnection(clientConnection) .setEventBuilder(event) - .setProtector(authManager.getProtector()) .setRealm(realm) .setSession(session) .setUriInfo(uriInfo) diff --git a/services/src/main/java/org/keycloak/services/listeners/KeycloakSessionDestroyListener.java b/services/src/main/java/org/keycloak/services/listeners/KeycloakSessionDestroyListener.java index e87a0a8c0b..5413004af0 100755 --- a/services/src/main/java/org/keycloak/services/listeners/KeycloakSessionDestroyListener.java +++ b/services/src/main/java/org/keycloak/services/listeners/KeycloakSessionDestroyListener.java @@ -1,7 +1,6 @@ package org.keycloak.services.listeners; import org.keycloak.models.KeycloakSessionFactory; -import org.keycloak.services.managers.BruteForceProtector; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; @@ -17,10 +16,6 @@ public class KeycloakSessionDestroyListener implements ServletContextListener { @Override 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()); if (sessionFactory != null) { sessionFactory.close(); diff --git a/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java b/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java index 4943d24c4d..2e63e57ea7 100755 --- a/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java +++ b/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java @@ -70,19 +70,6 @@ public class AuthenticationManager { public static final String KEYCLOAK_LOGOUT_PROTOCOL = "KEYCLOAK_LOGOUT_PROTOCOL"; 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) { if (userSession == null) { logger.debug("No user session"); diff --git a/services/src/main/java/org/keycloak/services/managers/BruteForceProtector.java b/services/src/main/java/org/keycloak/services/managers/DefaultBruteForceProtector.java similarity index 96% rename from services/src/main/java/org/keycloak/services/managers/BruteForceProtector.java rename to services/src/main/java/org/keycloak/services/managers/DefaultBruteForceProtector.java index 191f7fa986..0164c2c58f 100755 --- a/services/src/main/java/org/keycloak/services/managers/BruteForceProtector.java +++ b/services/src/main/java/org/keycloak/services/managers/DefaultBruteForceProtector.java @@ -20,8 +20,8 @@ import java.util.concurrent.TimeUnit; * @author Bill Burke * @version $Revision: 1 $ */ -public class BruteForceProtector implements Runnable { - protected static Logger logger = Logger.getLogger(BruteForceProtector.class); +public class DefaultBruteForceProtector implements Runnable, BruteForceProtector { + protected static Logger logger = Logger.getLogger(DefaultBruteForceProtector.class); protected volatile boolean run = true; 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; } @@ -204,6 +204,7 @@ public class BruteForceProtector implements Runnable { } } + @Override public void failedLogin(RealmModel realm, String username, ClientConnection clientConnection) { try { 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) { UsernameLoginFailureModel failure = session.sessions().getUserLoginFailure(realm, username.toLowerCase()); if (failure == null) { @@ -231,4 +233,8 @@ public class BruteForceProtector implements Runnable { return false; } + @Override + public void close() { + + } } diff --git a/services/src/main/java/org/keycloak/services/managers/DefaultBruteForceProtectorFactory.java b/services/src/main/java/org/keycloak/services/managers/DefaultBruteForceProtectorFactory.java new file mode 100755 index 0000000000..d706475890 --- /dev/null +++ b/services/src/main/java/org/keycloak/services/managers/DefaultBruteForceProtectorFactory.java @@ -0,0 +1,41 @@ +package org.keycloak.services.managers; + +import org.keycloak.Config; +import org.keycloak.models.KeycloakSession; +import org.keycloak.models.KeycloakSessionFactory; + +/** + * @author Bill Burke + * @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"; + } +} diff --git a/services/src/main/java/org/keycloak/services/resources/IdentityBrokerService.java b/services/src/main/java/org/keycloak/services/resources/IdentityBrokerService.java index aa6d3feded..84521b3f33 100755 --- a/services/src/main/java/org/keycloak/services/resources/IdentityBrokerService.java +++ b/services/src/main/java/org/keycloak/services/resources/IdentityBrokerService.java @@ -699,7 +699,6 @@ public class IdentityBrokerService implements IdentityProvider.AuthenticationCal .setFlowId(flowId) .setConnection(clientConnection) .setEventBuilder(event) - .setProtector(protector) .setRealm(realmModel) .setSession(session) .setUriInfo(uriInfo) diff --git a/services/src/main/java/org/keycloak/services/resources/KeycloakApplication.java b/services/src/main/java/org/keycloak/services/resources/KeycloakApplication.java index 7b261f24ae..c0842eecfd 100755 --- a/services/src/main/java/org/keycloak/services/resources/KeycloakApplication.java +++ b/services/src/main/java/org/keycloak/services/resources/KeycloakApplication.java @@ -17,7 +17,6 @@ import org.keycloak.representations.idm.UserRepresentation; import org.keycloak.services.DefaultKeycloakSessionFactory; import org.keycloak.services.filters.KeycloakTransactionCommitter; import org.keycloak.services.managers.ApplianceBootstrap; -import org.keycloak.services.managers.BruteForceProtector; import org.keycloak.services.managers.RealmManager; import org.keycloak.services.managers.UsersSyncManager; import org.keycloak.services.resources.admin.AdminRoot; @@ -60,12 +59,7 @@ public class KeycloakApplication extends Application { this.sessionFactory = createSessionFactory(); 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 - protector.start(); - context.setAttribute(BruteForceProtector.class.getName(), protector); context.setAttribute(KeycloakSessionFactory.class.getName(), this.sessionFactory); singletons.add(new ServerVersionResource()); diff --git a/services/src/main/java/org/keycloak/services/resources/LoginActionsService.java b/services/src/main/java/org/keycloak/services/resources/LoginActionsService.java index d015224f24..cf9e8e212d 100755 --- a/services/src/main/java/org/keycloak/services/resources/LoginActionsService.java +++ b/services/src/main/java/org/keycloak/services/resources/LoginActionsService.java @@ -21,6 +21,7 @@ */ package org.keycloak.services.resources; +import org.apache.http.auth.AUTH; import org.jboss.logging.Logger; import org.jboss.resteasy.spi.HttpRequest; import org.keycloak.authentication.authenticators.broker.AbstractIdpAuthenticator; @@ -121,8 +122,6 @@ public class LoginActionsService { @Context protected KeycloakSession session; - private AuthenticationManager authManager; - private EventBuilder event; public static UriBuilder loginActionsBaseUrl(UriInfo uriInfo) { @@ -154,9 +153,8 @@ public class LoginActionsService { 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.authManager = authManager; this.event = event; } @@ -293,7 +291,6 @@ public class LoginActionsService { .setFlowId(flow.getId()) .setConnection(clientConnection) .setEventBuilder(event) - .setProtector(authManager.getProtector()) .setRealm(realm) .setSession(session) .setUriInfo(uriInfo) @@ -454,7 +451,7 @@ public class LoginActionsService { ClientSessionModel clientSession = clientSessionCode.getClientSession(); - authManager.expireIdentityCookie(realm, uriInfo, clientConnection); + AuthenticationManager.expireIdentityCookie(realm, uriInfo, clientConnection); return processRegistration(execution, clientSession, null); } @@ -648,7 +645,7 @@ public class LoginActionsService { event.detail(Details.CONSENT, Details.CONSENT_VALUE_CONSENT_GRANTED); 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") diff --git a/services/src/main/java/org/keycloak/services/resources/RealmsResource.java b/services/src/main/java/org/keycloak/services/resources/RealmsResource.java index f84b181ea5..73c89b9c0f 100755 --- a/services/src/main/java/org/keycloak/services/resources/RealmsResource.java +++ b/services/src/main/java/org/keycloak/services/resources/RealmsResource.java @@ -81,10 +81,9 @@ public class RealmsResource { RealmModel realm = init(name); EventBuilder event = new EventBuilder(realm, session, clientConnection); - AuthenticationManager authManager = new AuthenticationManager(protector); 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); return endpoint.getLoginStatusIframe(); @@ -97,10 +96,9 @@ public class RealmsResource { RealmModel realm = init(name); EventBuilder event = new EventBuilder(realm, session, clientConnection); - AuthenticationManager authManager = new AuthenticationManager(protector); 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); return endpoint; @@ -117,8 +115,7 @@ public class RealmsResource { public LoginActionsService getLoginActionsService(final @PathParam("realm") String name) { RealmModel realm = init(name); EventBuilder event = new EventBuilder(realm, session, clientConnection); - AuthenticationManager authManager = new AuthenticationManager(protector); - LoginActionsService service = new LoginActionsService(realm, authManager, event); + LoginActionsService service = new LoginActionsService(realm, event); ResteasyProviderFactory.getInstance().injectProperties(service); return service; } diff --git a/services/src/main/resources/META-INF/services/org.keycloak.provider.Spi b/services/src/main/resources/META-INF/services/org.keycloak.provider.Spi index a657c78891..312a57203a 100755 --- a/services/src/main/resources/META-INF/services/org.keycloak.provider.Spi +++ b/services/src/main/resources/META-INF/services/org.keycloak.provider.Spi @@ -1,5 +1,3 @@ -org.keycloak.protocol.LoginProtocolSpi -org.keycloak.protocol.ProtocolMapperSpi org.keycloak.exportimport.ClientDescriptionConverterSpi org.keycloak.wellknown.WellKnownSpi org.keycloak.messages.MessagesSpi @@ -9,4 +7,3 @@ org.keycloak.authentication.RequiredActionSpi org.keycloak.authentication.FormAuthenticatorSpi org.keycloak.authentication.FormActionSpi org.keycloak.services.clientregistration.ClientRegistrationSpi -org.keycloak.protocol.ClientInstallationSpi diff --git a/services/src/main/resources/META-INF/services/org.keycloak.services.managers.BruteForceProtectorFactory b/services/src/main/resources/META-INF/services/org.keycloak.services.managers.BruteForceProtectorFactory new file mode 100755 index 0000000000..caa9ee0cce --- /dev/null +++ b/services/src/main/resources/META-INF/services/org.keycloak.services.managers.BruteForceProtectorFactory @@ -0,0 +1 @@ +org.keycloak.services.managers.DefaultBruteForceProtectorFactory \ No newline at end of file