Merge pull request #1143 from stianst/kc-context

Added KeycloakContext
This commit is contained in:
Stian Thorgersen 2015-04-15 14:02:14 +02:00
commit 5ef1ddb9f1
64 changed files with 479 additions and 434 deletions

View file

@ -34,7 +34,7 @@ import org.keycloak.models.FederatedIdentityModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.services.messages.Messages;
import org.keycloak.services.resources.flows.Flows;
import org.keycloak.services.ErrorPage;
import javax.ws.rs.GET;
import javax.ws.rs.QueryParam;
@ -217,7 +217,7 @@ public abstract class AbstractOAuth2IdentityProvider<C extends OAuth2IdentityPro
//logger.error("Failed " + getConfig().getAlias() + " broker login: " + error);
event.event(EventType.LOGIN);
event.error(error);
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.IDENTITY_PROVIDER_UNEXPECTED_ERROR);
return ErrorPage.error(session, Messages.IDENTITY_PROVIDER_UNEXPECTED_ERROR);
}
try {
@ -239,7 +239,7 @@ public abstract class AbstractOAuth2IdentityProvider<C extends OAuth2IdentityPro
}
event.event(EventType.LOGIN);
event.error(Errors.IDENTITY_PROVIDER_LOGIN_FAILURE);
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.IDENTITY_PROVIDER_UNEXPECTED_ERROR);
return ErrorPage.error(session, Messages.IDENTITY_PROVIDER_UNEXPECTED_ERROR);
}
public SimpleHttp generateTokenRequest(String authorizationCode) {

View file

@ -19,7 +19,6 @@ package org.keycloak.broker.oidc;
import org.codehaus.jackson.JsonNode;
import org.jboss.logging.Logger;
import org.keycloak.RSATokenVerifier;
import org.keycloak.broker.oidc.util.SimpleHttp;
import org.keycloak.broker.provider.AuthenticationRequest;
import org.keycloak.broker.provider.FederatedIdentity;
@ -37,7 +36,7 @@ import org.keycloak.services.managers.AuthenticationManager;
import org.keycloak.services.messages.Messages;
import org.keycloak.services.resources.IdentityBrokerService;
import org.keycloak.services.resources.RealmsResource;
import org.keycloak.services.resources.flows.Flows;
import org.keycloak.services.ErrorPage;
import org.keycloak.util.JsonSerialization;
import org.keycloak.util.PemUtils;
@ -116,14 +115,14 @@ public class OIDCIdentityProvider extends AbstractOAuth2IdentityProvider<OIDCIde
EventBuilder event = new EventBuilder(realm, session, clientConnection);
event.event(EventType.LOGOUT);
event.error(Errors.USER_SESSION_NOT_FOUND);
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.IDENTITY_PROVIDER_UNEXPECTED_ERROR);
return ErrorPage.error(session, Messages.IDENTITY_PROVIDER_UNEXPECTED_ERROR);
}
if (userSession.getState() != UserSessionModel.State.LOGGING_OUT) {
logger.error("usersession in different state");
EventBuilder event = new EventBuilder(realm, session, clientConnection);
event.event(EventType.LOGOUT);
event.error(Errors.USER_SESSION_NOT_FOUND);
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.SESSION_NOT_ACTIVE);
return ErrorPage.error(session, Messages.SESSION_NOT_ACTIVE);
}
return AuthenticationManager.finishBrowserLogout(session, realm, userSession, uriInfo, clientConnection, headers);
}

View file

@ -19,7 +19,7 @@ import org.keycloak.protocol.saml.SamlProtocol;
import org.keycloak.protocol.saml.SamlProtocolUtils;
import org.keycloak.services.managers.AuthenticationManager;
import org.keycloak.services.messages.Messages;
import org.keycloak.services.resources.flows.Flows;
import org.keycloak.services.ErrorPage;
import org.keycloak.saml.common.constants.GeneralConstants;
import org.keycloak.saml.common.constants.JBossSAMLConstants;
import org.keycloak.saml.common.constants.JBossSAMLURIConstants;
@ -130,18 +130,18 @@ public class SAMLEndpoint {
if (!checkSsl()) {
event.event(EventType.LOGIN);
event.error(Errors.SSL_REQUIRED);
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.HTTPS_REQUIRED);
return ErrorPage.error(session, Messages.HTTPS_REQUIRED);
}
if (!realm.isEnabled()) {
event.event(EventType.LOGIN_ERROR);
event.error(Errors.REALM_DISABLED);
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.REALM_NOT_ENABLED);
return ErrorPage.error(session, Messages.REALM_NOT_ENABLED);
}
if (samlRequest == null && samlResponse == null) {
event.event(EventType.LOGIN);
event.error(Errors.INVALID_REQUEST);
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.INVALID_REQUEST );
return ErrorPage.error(session, Messages.INVALID_REQUEST);
}
return null;
@ -177,7 +177,7 @@ public class SAMLEndpoint {
event.event(EventType.IDENTITY_PROVIDER_RESPONSE);
event.error(Errors.INVALID_SAML_RESPONSE);
event.detail(Details.REASON, "invalid_destination");
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.INVALID_REQUEST);
return ErrorPage.error(session, Messages.INVALID_REQUEST);
}
if (config.isValidateSignature()) {
try {
@ -186,7 +186,7 @@ public class SAMLEndpoint {
logger.error("validation failed", e);
event.event(EventType.IDENTITY_PROVIDER_RESPONSE);
event.error(Errors.INVALID_SIGNATURE);
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.INVALID_REQUESTER);
return ErrorPage.error(session, Messages.INVALID_REQUESTER);
}
}
@ -199,7 +199,7 @@ public class SAMLEndpoint {
} else {
event.event(EventType.LOGIN);
event.error(Errors.INVALID_TOKEN);
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.INVALID_REQUEST);
return ErrorPage.error(session, Messages.INVALID_REQUEST);
}
}
@ -327,7 +327,7 @@ public class SAMLEndpoint {
event.event(EventType.IDENTITY_PROVIDER_RESPONSE);
event.error(Errors.INVALID_SAML_RESPONSE);
event.detail(Details.REASON, "invalid_destination");
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.INVALID_FEDERATED_IDENTITY_ACTION);
return ErrorPage.error(session, Messages.INVALID_FEDERATED_IDENTITY_ACTION);
}
if (config.isValidateSignature()) {
try {
@ -336,7 +336,7 @@ public class SAMLEndpoint {
logger.error("validation failed", e);
event.event(EventType.IDENTITY_PROVIDER_RESPONSE);
event.error(Errors.INVALID_SIGNATURE);
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.INVALID_FEDERATED_IDENTITY_ACTION);
return ErrorPage.error(session, Messages.INVALID_FEDERATED_IDENTITY_ACTION);
}
}
if (statusResponse instanceof ResponseType) {
@ -355,20 +355,20 @@ public class SAMLEndpoint {
logger.error("no valid user session");
event.event(EventType.LOGOUT);
event.error(Errors.USER_SESSION_NOT_FOUND);
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.IDENTITY_PROVIDER_UNEXPECTED_ERROR);
return ErrorPage.error(session, Messages.IDENTITY_PROVIDER_UNEXPECTED_ERROR);
}
UserSessionModel userSession = session.sessions().getUserSession(realm, relayState);
if (userSession == null) {
logger.error("no valid user session");
event.event(EventType.LOGOUT);
event.error(Errors.USER_SESSION_NOT_FOUND);
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.IDENTITY_PROVIDER_UNEXPECTED_ERROR);
return ErrorPage.error(session, Messages.IDENTITY_PROVIDER_UNEXPECTED_ERROR);
}
if (userSession.getState() != UserSessionModel.State.LOGGING_OUT) {
logger.error("usersession in different state");
event.event(EventType.LOGOUT);
event.error(Errors.USER_SESSION_NOT_FOUND);
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.SESSION_NOT_ACTIVE);
return ErrorPage.error(session, Messages.SESSION_NOT_ACTIVE);
}
return AuthenticationManager.finishBrowserLogout(session, realm, userSession, uriInfo, clientConnection, headers);
}

View file

@ -12,6 +12,7 @@
<module name="org.keycloak.keycloak-events-api"/>
<module name="org.jboss.logging"/>
<module name="javax.api"/>
<module name="javax.ws.rs.api"/>
</dependencies>
</module>

View file

@ -36,6 +36,11 @@
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jaxrs</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>

View file

@ -3,23 +3,35 @@ package org.keycloak.events.log;
import org.jboss.logging.Logger;
import org.keycloak.events.Event;
import org.keycloak.events.EventListenerProvider;
import org.keycloak.models.KeycloakContext;
import org.keycloak.models.KeycloakSession;
import javax.ws.rs.core.Cookie;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.UriInfo;
import java.util.Map;
import java.util.logging.Level;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public class JBossLoggingEventListenerProvider implements EventListenerProvider {
private final KeycloakSession session;
private final Logger logger;
private final Logger.Level successLevel;
private final Logger.Level errorLevel;
public JBossLoggingEventListenerProvider(Logger logger) {
public JBossLoggingEventListenerProvider(KeycloakSession session, Logger logger, Logger.Level successLevel, Logger.Level errorLevel) {
this.session = session;
this.logger = logger;
this.successLevel = successLevel;
this.errorLevel = errorLevel;
}
@Override
public void onEvent(Event event) {
Logger.Level level = event.getError() != null ? Logger.Level.WARN : Logger.Level.INFO;
Logger.Level level = event.getError() != null ? errorLevel : successLevel;
if (logger.isEnabled(level)) {
StringBuilder sb = new StringBuilder();
@ -55,7 +67,31 @@ public class JBossLoggingEventListenerProvider implements EventListenerProvider
}
}
logger.log(level, sb.toString());
if (logger.isTraceEnabled()) {
KeycloakContext context = session.getContext();
UriInfo uriInfo = context.getUri();
HttpHeaders headers = context.getRequestHeaders();
if (uriInfo != null) {
sb.append(", requestUri=");
sb.append(uriInfo.getRequestUri().toString());
}
if (headers != null) {
sb.append(", cookies=[");
boolean f = true;
for (Map.Entry<String, Cookie> e : headers.getCookies().entrySet()) {
if (f) {
f = false;
} else {
sb.append(", ");
}
sb.append(e.getValue().toString());
}
sb.append("]");
}
}
logger.log(logger.isTraceEnabled() ? Logger.Level.TRACE : level, sb.toString());
}
}

View file

@ -6,6 +6,9 @@ import org.keycloak.events.EventListenerProvider;
import org.keycloak.events.EventListenerProviderFactory;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory;
import sun.rmi.runtime.Log;
import java.util.logging.Level;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
@ -16,13 +19,18 @@ public class JBossLoggingEventListenerProviderFactory implements EventListenerPr
private static final Logger logger = Logger.getLogger("org.keycloak.events");
private Logger.Level successLevel;
private Logger.Level errorLevel;
@Override
public EventListenerProvider create(KeycloakSession session) {
return new JBossLoggingEventListenerProvider(logger);
return new JBossLoggingEventListenerProvider(session, logger, successLevel, errorLevel);
}
@Override
public void init(Config.Scope config) {
successLevel = Logger.Level.valueOf(config.get("success-level", "debug").toUpperCase());
errorLevel = Logger.Level.valueOf(config.get("error-level", "warn").toUpperCase());
}
@Override

View file

@ -47,7 +47,7 @@ import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.UserSessionModel;
import org.keycloak.models.utils.FormMessage;
import org.keycloak.services.resources.flows.Urls;
import org.keycloak.services.Urls;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>

View file

@ -6,7 +6,7 @@ import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel;
import org.keycloak.services.resources.AccountService;
import org.keycloak.services.resources.flows.Urls;
import org.keycloak.services.Urls;
import javax.ws.rs.core.UriBuilder;
import java.net.URI;

View file

@ -2,7 +2,7 @@ package org.keycloak.account.freemarker.model;
import org.keycloak.freemarker.Theme;
import org.keycloak.models.RealmModel;
import org.keycloak.services.resources.flows.Urls;
import org.keycloak.services.Urls;
import java.net.URI;

View file

@ -21,12 +21,6 @@ import org.keycloak.provider.Provider;
*/
public interface LoginFormsProvider extends Provider {
public LoginFormsProvider setRealm(RealmModel realm);
public LoginFormsProvider setUriInfo(UriInfo uriInfo);
public LoginFormsProvider setHttpHeaders(HttpHeaders httpHeaders);
public Response createResponse(UserModel.RequiredAction action);
public Response createLogin();
@ -67,14 +61,8 @@ public interface LoginFormsProvider extends Provider {
public LoginFormsProvider setSuccess(String message, Object ... parameters);
public LoginFormsProvider setWarning(String message, Object ... parameters);
public LoginFormsProvider setUser(UserModel user);
public LoginFormsProvider setClient(ClientModel client);
public LoginFormsProvider setQueryParams(MultivaluedMap<String, String> queryParams);
public LoginFormsProvider setResponseHeader(String headerName, String headerValue);
public LoginFormsProvider setFormData(MultivaluedMap<String, String> formData);

View file

@ -37,9 +37,8 @@ import org.keycloak.models.RoleModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.utils.FormMessage;
import org.keycloak.services.messages.Messages;
import org.keycloak.services.resources.flows.Urls;
import org.keycloak.services.Urls;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
@ -79,39 +78,20 @@ import java.util.concurrent.TimeUnit;
private KeycloakSession session;
private FreeMarkerUtil freeMarker;
private RealmModel realm;
private UserModel user;
private ClientModel client;
private ClientSessionModel clientSession;
private UriInfo uriInfo;
private HttpHeaders httpHeaders;
public FreeMarkerLoginFormsProvider(KeycloakSession session, FreeMarkerUtil freeMarker) {
this.session = session;
this.freeMarker = freeMarker;
}
public LoginFormsProvider setRealm(RealmModel realm) {
this.realm = realm;
return this;
}
public LoginFormsProvider setUriInfo(UriInfo uriInfo) {
this.uriInfo = uriInfo;
return this;
}
@Override
public LoginFormsProvider setHttpHeaders(HttpHeaders httpHeaders) {
this.httpHeaders = httpHeaders;
return this;
}
public Response createResponse(UserModel.RequiredAction action) {
RealmModel realm = session.getContext().getRealm();
UriInfo uriInfo = session.getContext().getUri();
String actionMessage;
LoginFormsPages page;
@ -150,13 +130,17 @@ import java.util.concurrent.TimeUnit;
}
if (messages == null) {
setWarning(actionMessage);
setMessage(MessageType.WARNING, actionMessage);
}
return createResponse(page);
}
private Response createResponse(LoginFormsPages page) {
RealmModel realm = session.getContext().getRealm();
ClientModel client = session.getContext().getClient();
UriInfo uriInfo = session.getContext().getUri();
MultivaluedMap<String, String> queryParameterMap = queryParams != null ? queryParams : new MultivaluedMapImpl<String, String>();
String requestURI = uriInfo.getBaseUri().getPath();
@ -191,7 +175,7 @@ import java.util.concurrent.TimeUnit;
}
Properties messagesBundle;
Locale locale = LocaleHelper.getLocale(realm, user, uriInfo, httpHeaders);
Locale locale = LocaleHelper.getLocale(realm, user, uriInfo, session.getContext().getRequestHeaders());
try {
messagesBundle = theme.getMessages(locale);
attributes.put("msg", new MessageFormatterMethod(locale, messagesBundle));
@ -222,7 +206,7 @@ import java.util.concurrent.TimeUnit;
if (realm != null) {
attributes.put("realm", new RealmBean(realm));
attributes.put("social", new IdentityProviderBean(realm, baseUri, this.uriInfo));
attributes.put("social", new IdentityProviderBean(realm, baseUri, uriInfo));
attributes.put("url", new UrlBean(realm, theme, baseUri, this.actionUri));
if (realm.isInternationalizationEnabled()) {
@ -365,22 +349,11 @@ import java.util.concurrent.TimeUnit;
return this;
}
@Override
public FreeMarkerLoginFormsProvider setWarning(String message, Object ... parameters) {
setMessage(MessageType.WARNING, message, parameters);
return this;
}
public FreeMarkerLoginFormsProvider setUser(UserModel user) {
this.user = user;
return this;
}
public FreeMarkerLoginFormsProvider setClient(ClientModel client) {
this.client = client;
return this;
}
public FreeMarkerLoginFormsProvider setFormData(MultivaluedMap<String, String> formData) {
this.formData = formData;
return this;
@ -411,12 +384,6 @@ import java.util.concurrent.TimeUnit;
return this;
}
@Override
public LoginFormsProvider setQueryParams(MultivaluedMap<String, String> queryParams) {
this.queryParams = queryParams;
return this;
}
@Override
public LoginFormsProvider setActionUri(URI actionUri) {
this.actionUri = actionUri;

View file

@ -23,7 +23,7 @@ package org.keycloak.login.freemarker.model;
import org.keycloak.models.IdentityProviderModel;
import org.keycloak.models.RealmModel;
import org.keycloak.services.resources.flows.Urls;
import org.keycloak.services.Urls;
import javax.ws.rs.core.UriInfo;
import java.net.URI;

View file

@ -23,7 +23,7 @@ package org.keycloak.login.freemarker.model;
import org.keycloak.freemarker.Theme;
import org.keycloak.models.RealmModel;
import org.keycloak.services.resources.flows.Urls;
import org.keycloak.services.Urls;
import java.net.URI;

View file

@ -14,6 +14,11 @@
<description/>
<dependencies>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jaxrs</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>net.iharder</groupId>
<artifactId>base64</artifactId>

View file

@ -0,0 +1,23 @@
package org.keycloak.models;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.UriInfo;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public interface KeycloakContext {
UriInfo getUri();
HttpHeaders getRequestHeaders();
RealmModel getRealm();
void setRealm(RealmModel realm);
ClientModel getClient();
void setClient(ClientModel client);
}

View file

@ -10,6 +10,8 @@ import java.util.Set;
*/
public interface KeycloakSession {
KeycloakContext getContext();
KeycloakTransactionManager getTransaction();
<T extends Provider> T getProvider(Class<T> clazz);

View file

@ -64,7 +64,7 @@ public class RepresentationToModel {
if (rep.getFailureFactor() != null) newRealm.setFailureFactor(rep.getFailureFactor());
if (rep.isEventsEnabled() != null) newRealm.setEventsEnabled(rep.isEventsEnabled());
if (rep.getEventsExpiration() != null) newRealm.setEventsExpiration(rep.getEventsExpiration());
if (rep.getEventsListeners() != null) newRealm.setEventsListeners(new HashSet<String>(rep.getEventsListeners()));
if (rep.getEventsListeners() != null) newRealm.setEventsListeners(new HashSet<>(rep.getEventsListeners()));
if (rep.getNotBefore() != null) newRealm.setNotBefore(rep.getNotBefore());
@ -409,8 +409,8 @@ public class RepresentationToModel {
if (rep.getEmailTheme() != null) realm.setEmailTheme(rep.getEmailTheme());
if (rep.isEventsEnabled() != null) realm.setEventsEnabled(rep.isEventsEnabled());
if (rep.getEventsExpiration() != null) realm.setEventsExpiration(rep.getEventsExpiration());
if (rep.getEventsListeners() != null) realm.setEventsListeners(new HashSet<String>(rep.getEventsListeners()));
if (rep.getEnabledEventTypes() != null) realm.setEnabledEventTypes(new HashSet<String>(rep.getEnabledEventTypes()));
if (rep.getEventsListeners() != null) realm.setEventsListeners(new HashSet<>(rep.getEventsListeners()));
if (rep.getEnabledEventTypes() != null) realm.setEnabledEventTypes(new HashSet<>(rep.getEnabledEventTypes()));
if (rep.getPasswordPolicy() != null) realm.setPasswordPolicy(new PasswordPolicy(rep.getPasswordPolicy()));

View file

@ -30,7 +30,7 @@ import org.keycloak.services.managers.ResourceAdminManager;
import org.keycloak.services.messages.Messages;
import org.keycloak.services.resources.RealmsResource;
import org.keycloak.services.resources.admin.ClientAttributeCertificateResource;
import org.keycloak.services.resources.flows.Flows;
import org.keycloak.services.ErrorPage;
import org.w3c.dom.Document;
import javax.ws.rs.core.HttpHeaders;
@ -152,7 +152,7 @@ public class SamlProtocol implements LoginProtocol {
return builder.redirectBinding().response();
}
} catch (Exception e) {
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.FAILED_TO_PROCESS_RESPONSE );
return ErrorPage.error(session, Messages.FAILED_TO_PROCESS_RESPONSE);
}
}
@ -309,7 +309,7 @@ public class SamlProtocol implements LoginProtocol {
samlDocument = builder.buildDocument(samlModel);
} catch (Exception e) {
logger.error("failed", e);
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo,headers, Messages.FAILED_TO_PROCESS_RESPONSE);
return ErrorPage.error(session, Messages.FAILED_TO_PROCESS_RESPONSE);
}
SAML2BindingBuilder2 bindingBuilder = new SAML2BindingBuilder2();
@ -331,7 +331,7 @@ public class SamlProtocol implements LoginProtocol {
publicKey = SamlProtocolUtils.getEncryptionValidationKey(client);
} catch (Exception e) {
logger.error("failed", e);
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.FAILED_TO_PROCESS_RESPONSE);
return ErrorPage.error(session, Messages.FAILED_TO_PROCESS_RESPONSE);
}
bindingBuilder.encrypt(publicKey);
}
@ -343,7 +343,7 @@ public class SamlProtocol implements LoginProtocol {
}
} catch (Exception e) {
logger.error("failed", e);
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.FAILED_TO_PROCESS_RESPONSE );
return ErrorPage.error(session, Messages.FAILED_TO_PROCESS_RESPONSE);
}
}

View file

@ -23,7 +23,7 @@ import org.keycloak.services.managers.ClientSessionCode;
import org.keycloak.services.managers.HttpAuthenticationManager;
import org.keycloak.services.messages.Messages;
import org.keycloak.services.resources.RealmsResource;
import org.keycloak.services.resources.flows.Flows;
import org.keycloak.services.ErrorPage;
import org.keycloak.util.StreamUtil;
import org.keycloak.saml.common.constants.GeneralConstants;
import org.keycloak.saml.common.constants.JBossSAMLURIConstants;
@ -102,18 +102,18 @@ public class SamlService {
if (!checkSsl()) {
event.event(EventType.LOGIN);
event.error(Errors.SSL_REQUIRED);
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.HTTPS_REQUIRED );
return ErrorPage.error(session, Messages.HTTPS_REQUIRED);
}
if (!realm.isEnabled()) {
event.event(EventType.LOGIN_ERROR);
event.error(Errors.REALM_DISABLED);
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.REALM_NOT_ENABLED);
return ErrorPage.error(session, Messages.REALM_NOT_ENABLED);
}
if (samlRequest == null && samlResponse == null) {
event.event(EventType.LOGIN);
event.error(Errors.INVALID_TOKEN);
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.INVALID_REQUEST );
return ErrorPage.error(session, Messages.INVALID_REQUEST);
}
return null;
@ -127,7 +127,7 @@ public class SamlService {
if (!uriInfo.getAbsolutePath().toString().equals(statusResponse.getDestination())) {
event.error(Errors.INVALID_SAML_LOGOUT_RESPONSE);
event.detail(Details.REASON, "invalid_destination");
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.INVALID_REQUEST);
return ErrorPage.error(session, Messages.INVALID_REQUEST);
}
AuthenticationManager.AuthResult authResult = authManager.authenticateIdentityCookie(session, realm, uriInfo, clientConnection, headers, false);
@ -135,7 +135,7 @@ public class SamlService {
logger.warn("Unknown saml response.");
event.event(EventType.LOGOUT);
event.error(Errors.INVALID_TOKEN);
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.INVALID_REQUEST);
return ErrorPage.error(session, Messages.INVALID_REQUEST);
}
// assume this is a logout response
UserSessionModel userSession = authResult.getSession();
@ -144,7 +144,7 @@ public class SamlService {
logger.warn("UserSession is not tagged as logging out.");
event.event(EventType.LOGOUT);
event.error(Errors.INVALID_SAML_LOGOUT_RESPONSE);
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.INVALID_REQUEST);
return ErrorPage.error(session, Messages.INVALID_REQUEST);
}
logger.debug("logout response");
Response response = authManager.browserLogout(session, realm, userSession, uriInfo, clientConnection, headers);
@ -157,7 +157,7 @@ public class SamlService {
if (documentHolder == null) {
event.event(EventType.LOGIN);
event.error(Errors.INVALID_TOKEN);
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.INVALID_REQUEST);
return ErrorPage.error(session, Messages.INVALID_REQUEST);
}
SAML2Object samlObject = documentHolder.getSamlObject();
@ -169,32 +169,34 @@ public class SamlService {
if (client == null) {
event.event(EventType.LOGIN);
event.error(Errors.CLIENT_NOT_FOUND);
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.UNKNOWN_LOGIN_REQUESTER);
return ErrorPage.error(session, Messages.UNKNOWN_LOGIN_REQUESTER);
}
if (!client.isEnabled()) {
event.event(EventType.LOGIN);
event.error(Errors.CLIENT_DISABLED);
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.LOGIN_REQUESTER_NOT_ENABLED);
return ErrorPage.error(session, Messages.LOGIN_REQUESTER_NOT_ENABLED);
}
if ((client instanceof ClientModel) && ((ClientModel)client).isBearerOnly()) {
event.event(EventType.LOGIN);
event.error(Errors.NOT_ALLOWED);
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.BEARER_ONLY);
return ErrorPage.error(session, Messages.BEARER_ONLY);
}
if (client.isDirectGrantsOnly()) {
event.event(EventType.LOGIN);
event.error(Errors.NOT_ALLOWED);
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.DIRECT_GRANTS_ONLY );
return ErrorPage.error(session, Messages.DIRECT_GRANTS_ONLY);
}
session.getContext().setClient(client);
try {
verifySignature(documentHolder, client);
} catch (VerificationException e) {
SamlService.logger.error("request validation failed", e);
event.event(EventType.LOGIN);
event.error(Errors.INVALID_SIGNATURE);
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.INVALID_REQUESTER);
return ErrorPage.error(session, Messages.INVALID_REQUESTER);
}
logger.debug("verified request");
if (samlObject instanceof AuthnRequestType) {
@ -212,7 +214,7 @@ public class SamlService {
} else {
event.event(EventType.LOGIN);
event.error(Errors.INVALID_TOKEN);
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.INVALID_REQUEST);
return ErrorPage.error(session, Messages.INVALID_REQUEST);
}
}
@ -226,7 +228,7 @@ public class SamlService {
if (!uriInfo.getAbsolutePath().equals(requestAbstractType.getDestination())) {
event.error(Errors.INVALID_SAML_AUTHN_REQUEST);
event.detail(Details.REASON, "invalid_destination");
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.INVALID_REQUEST);
return ErrorPage.error(session, Messages.INVALID_REQUEST);
}
String bindingType = getBindingType(requestAbstractType);
if ("true".equals(client.getAttribute(SamlProtocol.SAML_FORCE_POST_BINDING))) bindingType = SamlProtocol.SAML_POST_BINDING;
@ -248,7 +250,7 @@ public class SamlService {
if (redirect == null) {
event.error(Errors.INVALID_REDIRECT_URI);
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.INVALID_REDIRECT_URI );
return ErrorPage.error(session, Messages.INVALID_REDIRECT_URI);
}
@ -271,7 +273,7 @@ public class SamlService {
} else {
event.error(Errors.INVALID_SAML_AUTHN_REQUEST);
event.detail(Details.REASON, "unsupported_nameid_format");
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.UNSUPPORTED_NAME_ID_FORMAT);
return ErrorPage.error(session, Messages.UNSUPPORTED_NAME_ID_FORMAT);
}
}
@ -283,7 +285,7 @@ public class SamlService {
HttpAuthenticationManager.HttpAuthOutput httpAuthOutput = httpAuthManager.spnegoAuthenticate(headers);
if (httpAuthOutput.getResponse() != null) return httpAuthOutput.getResponse();
LoginFormsProvider forms = Flows.forms(session, realm, clientSession.getClient(), uriInfo, headers)
LoginFormsProvider forms = session.getProvider(LoginFormsProvider.class)
.setClientSessionCode(new ClientSessionCode(realm, clientSession).getCode());
// Attach state from SPNEGO authentication
@ -335,7 +337,7 @@ public class SamlService {
if (!uriInfo.getAbsolutePath().equals(logoutRequest.getDestination())) {
event.error(Errors.INVALID_SAML_LOGOUT_REQUEST);
event.detail(Details.REASON, "invalid_destination");
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.INVALID_REQUEST);
return ErrorPage.error(session, Messages.INVALID_REQUEST);
}
// authenticate identity cookie, but ignore an access token timeout as we're logging out anyways.
@ -374,7 +376,7 @@ public class SamlService {
if (redirectUri != null) {
redirectUri = RedirectUtils.verifyRedirectUri(uriInfo, redirectUri, realm, client);
if (redirectUri == null) {
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.INVALID_REDIRECT_URI );
return ErrorPage.error(session, Messages.INVALID_REDIRECT_URI);
}
}
if (redirectUri != null) {

View file

@ -14,6 +14,13 @@
}
},
"eventsListener": {
"jboss-logging" : {
"success-level": "debug",
"error-level": "warn"
}
},
"realm": {
"provider": "jpa"
},

View file

@ -18,7 +18,6 @@ import org.keycloak.protocol.oidc.endpoints.ValidateTokenEndpoint;
import org.keycloak.protocol.oidc.representations.JSONWebKeySet;
import org.keycloak.services.managers.AuthenticationManager;
import org.keycloak.services.resources.RealmsResource;
import org.keycloak.services.resources.flows.Flows;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
@ -204,7 +203,7 @@ public class OIDCLoginProtocolService {
@Path("oauth/oob")
@GET
public Response installedAppUrnCallback(final @QueryParam("code") String code, final @QueryParam("error") String error, final @QueryParam("error_description") String errorDescription) {
LoginFormsProvider forms = Flows.forms(session, realm, null, uriInfo, headers);
LoginFormsProvider forms = session.getProvider(LoginFormsProvider.class);
if (code != null) {
return forms.setClientSessionCode(code).createCode();
} else {

View file

@ -1,18 +1,17 @@
package org.keycloak.protocol.oidc;
import org.keycloak.OAuth2Constants;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.protocol.oidc.representations.OIDCConfigurationRepresentation;
import org.keycloak.services.resources.RealmsResource;
import org.keycloak.services.resources.flows.Urls;
import org.keycloak.services.Urls;
import org.keycloak.wellknown.WellKnownProvider;
import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriInfo;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
@ -29,8 +28,17 @@ public class OIDCWellKnownProvider implements WellKnownProvider {
public static final List<String> DEFAULT_RESPONSE_MODES_SUPPORTED = list("query");
private KeycloakSession session;
public OIDCWellKnownProvider(KeycloakSession session) {
this.session = session;
}
@Override
public Object getConfig(RealmModel realm, UriInfo uriInfo) {
public Object getConfig() {
UriInfo uriInfo = session.getContext().getUri();
RealmModel realm = session.getContext().getRealm();
UriBuilder uriBuilder = RealmsResource.protocolUrl(uriInfo);
OIDCConfigurationRepresentation config = new OIDCConfigurationRepresentation();

View file

@ -11,16 +11,13 @@ import org.keycloak.wellknown.WellKnownProviderFactory;
*/
public class OIDCWellKnownProviderFactory implements WellKnownProviderFactory {
private WellKnownProvider provider;
@Override
public WellKnownProvider create(KeycloakSession session) {
return provider;
return new OIDCWellKnownProvider(session);
}
@Override
public void init(Config.Scope config) {
provider = new OIDCWellKnownProvider();
}
@Override
@ -29,7 +26,6 @@ public class OIDCWellKnownProviderFactory implements WellKnownProviderFactory {
@Override
public void close() {
provider = null;
}
@Override

View file

@ -25,8 +25,7 @@ import org.keycloak.services.managers.AuthenticationManager;
import org.keycloak.services.managers.ClientSessionCode;
import org.keycloak.services.managers.HttpAuthenticationManager;
import org.keycloak.services.messages.Messages;
import org.keycloak.services.resources.flows.Flows;
import org.keycloak.services.resources.flows.Urls;
import org.keycloak.services.Urls;
import javax.ws.rs.GET;
import javax.ws.rs.core.Context;
@ -116,7 +115,7 @@ public class AuthorizationEndpoint {
action = Action.REGISTER;
if (!realm.isRegistrationAllowed()) {
throw new ErrorPageException(session, realm, uriInfo, headers, Messages.REGISTRATION_NOT_ALLOWED);
throw new ErrorPageException(session, Messages.REGISTRATION_NOT_ALLOWED);
}
return this;
@ -148,21 +147,21 @@ public class AuthorizationEndpoint {
private void checkSsl() {
if (!uriInfo.getBaseUri().getScheme().equals("https") && realm.getSslRequired().isRequired(clientConnection)) {
event.error(Errors.SSL_REQUIRED);
throw new ErrorPageException(session, realm, uriInfo, headers, Messages.HTTPS_REQUIRED);
throw new ErrorPageException(session, Messages.HTTPS_REQUIRED);
}
}
private void checkRealm() {
if (!realm.isEnabled()) {
event.error(Errors.REALM_DISABLED);
throw new ErrorPageException(session, realm, uriInfo, headers, Messages.REALM_NOT_ENABLED);
throw new ErrorPageException(session, Messages.REALM_NOT_ENABLED);
}
}
private void checkClient() {
if (clientId == null) {
event.error(Errors.INVALID_REQUEST);
throw new ErrorPageException(session, realm, uriInfo, headers, Messages.MISSING_PARAMETER, OIDCLoginProtocol.CLIENT_ID_PARAM );
throw new ErrorPageException(session, Messages.MISSING_PARAMETER, OIDCLoginProtocol.CLIENT_ID_PARAM );
}
event.client(clientId);
@ -170,18 +169,20 @@ public class AuthorizationEndpoint {
client = realm.getClientByClientId(clientId);
if (client == null) {
event.error(Errors.CLIENT_NOT_FOUND);
throw new ErrorPageException(session, realm, uriInfo, headers, Messages.CLIENT_NOT_FOUND );
throw new ErrorPageException(session, Messages.CLIENT_NOT_FOUND );
}
if ((client instanceof ClientModel) && ((ClientModel) client).isBearerOnly()) {
event.error(Errors.NOT_ALLOWED);
throw new ErrorPageException(session, realm, uriInfo, headers, Messages.BEARER_ONLY );
throw new ErrorPageException(session, Messages.BEARER_ONLY );
}
if (client.isDirectGrantsOnly()) {
event.error(Errors.NOT_ALLOWED);
throw new ErrorPageException(session, realm, uriInfo, headers, Messages.DIRECT_GRANTS_ONLY);
throw new ErrorPageException(session, Messages.DIRECT_GRANTS_ONLY);
}
session.getContext().setClient(client);
}
private void checkResponseType() {
@ -190,7 +191,7 @@ public class AuthorizationEndpoint {
responseType = legacyResponseType;
} else {
event.error(Errors.INVALID_REQUEST);
throw new ErrorPageException(session, realm, uriInfo, headers, Messages.MISSING_PARAMETER, OIDCLoginProtocol.RESPONSE_TYPE_PARAM );
throw new ErrorPageException(session, Messages.MISSING_PARAMETER, OIDCLoginProtocol.RESPONSE_TYPE_PARAM );
}
}
@ -200,7 +201,7 @@ public class AuthorizationEndpoint {
action = Action.CODE;
} else {
event.error(Errors.INVALID_REQUEST);
throw new ErrorPageException(session, realm, uriInfo, headers, Messages.INVALID_PARAMETER, OIDCLoginProtocol.RESPONSE_TYPE_PARAM );
throw new ErrorPageException(session, Messages.INVALID_PARAMETER, OIDCLoginProtocol.RESPONSE_TYPE_PARAM );
}
}
@ -210,7 +211,7 @@ public class AuthorizationEndpoint {
redirectUri = RedirectUtils.verifyRedirectUri(uriInfo, redirectUriParam, realm, client);
if (redirectUri == null) {
event.error(Errors.INVALID_REDIRECT_URI);
throw new ErrorPageException(session, realm, uriInfo, headers, Messages.INVALID_PARAMETER, OIDCLoginProtocol.REDIRECT_URI_PARAM);
throw new ErrorPageException(session, Messages.INVALID_PARAMETER, OIDCLoginProtocol.REDIRECT_URI_PARAM);
}
}
@ -238,7 +239,7 @@ public class AuthorizationEndpoint {
IdentityProviderModel identityProviderModel = realm.getIdentityProviderByAlias(idpHint);
if (identityProviderModel == null) {
return Flows.forms(session, realm, null, uriInfo, headers)
return session.getProvider(LoginFormsProvider.class)
.setError(Messages.IDENTITY_PROVIDER_NOT_FOUND, idpHint)
.createErrorPage();
}
@ -272,14 +273,13 @@ public class AuthorizationEndpoint {
return buildRedirectToIdentityProvider(identityProviders.get(0).getAlias(), accessCode);
}
return Flows.forms(session, realm, null, uriInfo, headers).setError(Messages.IDENTITY_PROVIDER_NOT_UNIQUE, realm.getName()).createErrorPage();
return session.getProvider(LoginFormsProvider.class).setError(Messages.IDENTITY_PROVIDER_NOT_UNIQUE, realm.getName()).createErrorPage();
}
return Flows.forms(session, realm, null, uriInfo, headers).setError(Messages.REALM_SUPPORTS_NO_CREDENTIALS, realm.getName()).createErrorPage();
return session.getProvider(LoginFormsProvider.class).setError(Messages.REALM_SUPPORTS_NO_CREDENTIALS, realm.getName()).createErrorPage();
}
LoginFormsProvider forms = Flows.forms(session, realm, clientSession.getClient(), uriInfo, headers)
.setClientSessionCode(accessCode);
LoginFormsProvider forms = session.getProvider(LoginFormsProvider.class).setClientSessionCode(accessCode);
// Attach state from SPNEGO authentication
if (httpAuthOutput.getChallenge() != null) {
@ -307,7 +307,7 @@ public class AuthorizationEndpoint {
private Response buildRegister() {
authManager.expireIdentityCookie(realm, uriInfo, clientConnection);
return Flows.forms(session, realm, client, uriInfo, headers)
return session.getProvider(LoginFormsProvider.class)
.setClientSessionCode(new ClientSessionCode(realm, clientSession).getCode())
.createRegistration();
}

View file

@ -24,7 +24,7 @@ import org.keycloak.services.ErrorResponseException;
import org.keycloak.services.managers.AuthenticationManager;
import org.keycloak.services.messages.Messages;
import org.keycloak.services.resources.Cors;
import org.keycloak.services.resources.flows.Flows;
import org.keycloak.services.ErrorPage;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
@ -92,7 +92,7 @@ public class LogoutEndpoint {
event.event(EventType.LOGOUT);
event.detail(Details.REDIRECT_URI, redirect);
event.error(Errors.INVALID_REDIRECT_URI);
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.INVALID_REDIRECT_URI);
return ErrorPage.error(session, Messages.INVALID_REDIRECT_URI);
}
redirect = validatedUri;
}
@ -112,7 +112,7 @@ public class LogoutEndpoint {
if (error) {
event.event(EventType.LOGOUT);
event.error(Errors.INVALID_TOKEN);
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.SESSION_NOT_ACTIVE);
return ErrorPage.error(session, Messages.SESSION_NOT_ACTIVE);
}
}

View file

@ -27,7 +27,7 @@ import org.keycloak.services.ErrorResponseException;
import org.keycloak.services.managers.AuthenticationManager;
import org.keycloak.services.managers.ClientSessionCode;
import org.keycloak.services.resources.Cors;
import org.keycloak.services.resources.flows.Urls;
import org.keycloak.services.Urls;
import javax.ws.rs.OPTIONS;
import javax.ws.rs.POST;

View file

@ -36,7 +36,7 @@ import org.keycloak.representations.AccessToken;
import org.keycloak.services.ErrorResponseException;
import org.keycloak.services.managers.AppAuthManager;
import org.keycloak.services.resources.Cors;
import org.keycloak.services.resources.flows.Urls;
import org.keycloak.services.Urls;
import javax.ws.rs.Consumes;
import javax.ws.rs.FormParam;

View file

@ -15,10 +15,9 @@ import org.keycloak.models.RealmModel;
import org.keycloak.protocol.oidc.TokenManager;
import org.keycloak.representations.AccessToken;
import org.keycloak.services.ErrorResponseException;
import org.keycloak.services.resources.flows.Urls;
import org.keycloak.services.Urls;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.*;

View file

@ -4,7 +4,7 @@ import org.jboss.logging.Logger;
import org.keycloak.models.ClientModel;
import org.keycloak.models.Constants;
import org.keycloak.models.RealmModel;
import org.keycloak.services.resources.flows.Urls;
import org.keycloak.services.Urls;
import javax.ws.rs.core.UriInfo;
import java.net.URI;

View file

@ -0,0 +1,50 @@
package org.keycloak.services;
import org.jboss.resteasy.spi.ResteasyProviderFactory;
import org.keycloak.models.ClientModel;
import org.keycloak.models.KeycloakContext;
import org.keycloak.models.RealmModel;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.UriInfo;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public class DefaultKeycloakContext implements KeycloakContext {
private RealmModel realm;
private ClientModel client;
@Override
public UriInfo getUri() {
return ResteasyProviderFactory.getContextData(UriInfo.class);
}
@Override
public HttpHeaders getRequestHeaders() {
return ResteasyProviderFactory.getContextData(HttpHeaders.class);
}
@Override
public RealmModel getRealm() {
return realm;
}
@Override
public void setRealm(RealmModel realm) {
this.realm = realm;
}
@Override
public ClientModel getClient() {
return client;
}
@Override
public void setClient(ClientModel client) {
this.client = client;
}
}

View file

@ -1,5 +1,8 @@
package org.keycloak.services;
import org.jboss.resteasy.spi.HttpRequest;
import org.jboss.resteasy.spi.ResteasyProviderFactory;
import org.keycloak.models.KeycloakContext;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.models.KeycloakTransactionManager;
@ -12,6 +15,7 @@ import org.keycloak.models.cache.CacheUserProvider;
import org.keycloak.provider.Provider;
import org.keycloak.provider.ProviderFactory;
import javax.ws.rs.core.UriInfo;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
@ -32,11 +36,18 @@ public class DefaultKeycloakSession implements KeycloakSession {
private UserProvider userModel;
private UserSessionProvider sessionProvider;
private UserFederationManager federationManager;
private KeycloakContext context;
public DefaultKeycloakSession(DefaultKeycloakSessionFactory factory) {
this.factory = factory;
this.transactionManager = new DefaultKeycloakTransactionManager();
federationManager = new UserFederationManager(this);
context = new DefaultKeycloakContext();
}
@Override
public KeycloakContext getContext() {
return context;
}
private RealmProvider getRealmProvider() {

View file

@ -19,35 +19,20 @@
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.keycloak.services.resources.flows;
package org.keycloak.services;
import org.keycloak.login.LoginFormsProvider;
import org.keycloak.models.ClientModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public class Flows {
public class ErrorPage {
private Flows() {
}
public static LoginFormsProvider forms(KeycloakSession session, RealmModel realm, ClientModel client, UriInfo uriInfo, HttpHeaders headers) {
return session.getProvider(LoginFormsProvider.class).setRealm(realm).setUriInfo(uriInfo).setClient(client).setHttpHeaders(headers);
}
public static ErrorFlows errors() {
return new ErrorFlows();
}
public static Response forwardToSecurityFailurePage(KeycloakSession session, RealmModel realm, UriInfo uriInfo, HttpHeaders headers, String message, Object ... parameters) {
return Flows.forms(session, realm, null, uriInfo, headers).setError(message,parameters).createErrorPage();
public static Response error(KeycloakSession session, String message, Object... parameters) {
return session.getProvider(LoginFormsProvider.class).setError(message, parameters).createErrorPage();
}

View file

@ -1,13 +1,9 @@
package org.keycloak.services;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.services.resources.flows.Flows;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
@ -15,24 +11,18 @@ import javax.ws.rs.core.UriInfo;
public class ErrorPageException extends WebApplicationException {
private final KeycloakSession session;
private final RealmModel realm;
private final UriInfo uriInfo;
private final HttpHeaders httpHeaders;
private final String errorMessage;
private final Object[] parameters;
public ErrorPageException(KeycloakSession session, RealmModel realm, UriInfo uriInfo, HttpHeaders headers, String errorMessage, Object ... parameters) {
public ErrorPageException(KeycloakSession session, String errorMessage, Object... parameters) {
this.session = session;
this.realm = realm;
this.uriInfo = uriInfo;
this.httpHeaders = headers;
this.errorMessage = errorMessage;
this.parameters = parameters;
}
@Override
public Response getResponse() {
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, httpHeaders, errorMessage, parameters);
return ErrorPage.error(session, errorMessage, parameters);
}
}

View file

@ -1,4 +1,4 @@
package org.keycloak.services.resources.flows;
package org.keycloak.services;
import org.keycloak.representations.idm.ErrorRepresentation;
@ -8,20 +8,18 @@ import javax.ws.rs.core.Response;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public class ErrorFlows {
public class ErrorResponse {
public Response exists(String message) {
public static Response exists(String message) {
ErrorRepresentation error = new ErrorRepresentation();
error.setErrorMessage(message);
return Response.status(Response.Status.CONFLICT).entity(error).type(MediaType.APPLICATION_JSON).build();
}
public Response error(String message, Response.Status status) {
public static Response error(String message, Response.Status status) {
ErrorRepresentation error = new ErrorRepresentation();
error.setErrorMessage(message);
return Response.status(status).entity(error).type(MediaType.APPLICATION_JSON).build();
}
}

View file

@ -1,14 +1,10 @@
package org.keycloak.services;
import org.keycloak.OAuth2Constants;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.services.resources.flows.Flows;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import java.util.HashMap;
import java.util.Map;

View file

@ -19,7 +19,7 @@
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.keycloak.services.resources.flows;
package org.keycloak.services;
import org.keycloak.OAuth2Constants;
import org.keycloak.Version;

View file

@ -30,8 +30,7 @@ import org.keycloak.representations.idm.CredentialRepresentation;
import org.keycloak.services.resources.IdentityBrokerService;
import org.keycloak.services.resources.LoginActionsService;
import org.keycloak.services.resources.RealmsResource;
import org.keycloak.services.resources.flows.Flows;
import org.keycloak.services.resources.flows.Urls;
import org.keycloak.services.Urls;
import org.keycloak.services.util.CookieHelper;
import org.keycloak.services.validation.Validation;
import org.keycloak.util.Time;
@ -401,7 +400,7 @@ public class AuthenticationManager {
if (action != null) {
accessCode.setRequiredAction(action);
LoginFormsProvider loginFormsProvider = Flows.forms(session, realm, client, uriInfo, request.getHttpHeaders()).setClientSessionCode(accessCode.getCode())
LoginFormsProvider loginFormsProvider = session.getProvider(LoginFormsProvider.class).setClientSessionCode(accessCode.getCode())
.setUser(user);
if (action.equals(UserModel.RequiredAction.VERIFY_EMAIL)) {
event.clone().event(EventType.SEND_VERIFY_EMAIL).detail(Details.EMAIL, user.getEmail()).success();
@ -425,10 +424,9 @@ public class AuthenticationManager {
}
}
return Flows.forms(session, realm, client, uriInfo, request.getHttpHeaders())
return session.getProvider(LoginFormsProvider.class)
.setClientSessionCode(accessCode.getCode())
.setAccessRequest(realmRoles, resourceRoles)
.setClient(client)
.createOAuthGrant(clientSession);
}

View file

@ -25,7 +25,7 @@ import org.keycloak.constants.KerberosConstants;
import org.keycloak.protocol.oidc.TokenManager;
import org.keycloak.representations.idm.CredentialRepresentation;
import org.keycloak.services.messages.Messages;
import org.keycloak.services.resources.flows.Flows;
import org.keycloak.services.ErrorPage;
/**
* Handle HTTP authentication types requiring complex handshakes with multiple HTTP request/responses
@ -114,7 +114,7 @@ public class HttpAuthenticationManager {
Response response;
if (!user.isEnabled()) {
event.error(Errors.USER_DISABLED);
response = Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.ACCOUNT_DISABLED);
response = ErrorPage.error(session, Messages.ACCOUNT_DISABLED);
} else {
UserSessionModel userSession = session.sessions().createUserSession(realm, user, user.getUsername(), clientConnection.getRemoteAddr(), authMethod, false, null, null);

View file

@ -132,6 +132,8 @@ public class RealmManager {
realm.setMaxDeltaTimeSeconds(60 * 60 * 12); // 12 hours
realm.setFailureFactor(30);
realm.setSslRequired(SslRequired.EXTERNAL);
realm.setEventsListeners(Collections.singleton("jboss-logging"));
}
public boolean removeRealm(RealmModel realm) {

View file

@ -24,7 +24,9 @@ package org.keycloak.services.resources;
import org.jboss.logging.Logger;
import org.jboss.resteasy.spi.BadRequestException;
import org.jboss.resteasy.spi.HttpRequest;
import org.keycloak.AbstractOAuthClient;
import org.keycloak.ClientConnection;
import org.keycloak.OAuth2Constants;
import org.keycloak.account.AccountPages;
import org.keycloak.account.AccountProvider;
import org.keycloak.events.Details;
@ -32,6 +34,7 @@ import org.keycloak.events.Event;
import org.keycloak.events.EventBuilder;
import org.keycloak.events.EventStoreProvider;
import org.keycloak.events.EventType;
import org.keycloak.login.LoginFormsProvider;
import org.keycloak.models.*;
import org.keycloak.models.utils.FormMessage;
import org.keycloak.models.utils.ModelToRepresentation;
@ -47,9 +50,7 @@ import org.keycloak.services.managers.Auth;
import org.keycloak.services.managers.AuthenticationManager;
import org.keycloak.services.managers.ClientSessionCode;
import org.keycloak.services.messages.Messages;
import org.keycloak.services.resources.flows.Flows;
import org.keycloak.services.resources.flows.OAuthRedirect;
import org.keycloak.services.resources.flows.Urls;
import org.keycloak.services.Urls;
import org.keycloak.services.util.CookieHelper;
import org.keycloak.services.util.ResolveRelative;
import org.keycloak.services.validation.Validation;
@ -66,6 +67,7 @@ import javax.ws.rs.core.Cookie;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.NewCookie;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriInfo;
@ -230,7 +232,7 @@ public class AccountService {
try {
require(AccountRoles.MANAGE_ACCOUNT);
} catch (ForbiddenException e) {
return Flows.forms(session, realm, null, uriInfo, headers).setError(Messages.NO_ACCESS).createErrorPage();
return session.getProvider(LoginFormsProvider.class).setError(Messages.NO_ACCESS).createErrorPage();
}
setReferrerOnPage();
@ -873,4 +875,42 @@ public class AccountService {
}
}
class OAuthRedirect extends AbstractOAuthClient {
/**
* closes client
*/
public void stop() {
}
public Response redirect(UriInfo uriInfo, String redirectUri) {
String state = getStateCode();
UriBuilder uriBuilder = UriBuilder.fromUri(authUrl)
.queryParam(OAuth2Constants.CLIENT_ID, clientId)
.queryParam(OAuth2Constants.REDIRECT_URI, redirectUri)
.queryParam(OAuth2Constants.STATE, state)
.queryParam(OAuth2Constants.RESPONSE_TYPE, OAuth2Constants.CODE);
if (scope != null) {
uriBuilder.queryParam(OAuth2Constants.SCOPE, scope);
}
URI url = uriBuilder.build();
// todo httpOnly!
NewCookie cookie = new NewCookie(getStateCookieName(), state, getStateCookiePath(uriInfo), null, null, -1, isSecure);
logger.debug("NewCookie: " + cookie.toString());
logger.debug("Oauth Redirect to: " + url);
return Response.status(302)
.location(url)
.cookie(cookie).build();
}
private String getStateCookiePath(UriInfo uriInfo) {
if (stateCookiePath != null) return stateCookiePath;
return uriInfo.getBaseUri().getRawPath();
}
}
}

View file

@ -30,6 +30,7 @@ import org.keycloak.events.Details;
import org.keycloak.events.Errors;
import org.keycloak.events.EventBuilder;
import org.keycloak.events.EventType;
import org.keycloak.login.LoginFormsProvider;
import org.keycloak.models.ClientModel;
import org.keycloak.models.ClientSessionModel;
import org.keycloak.models.FederatedIdentityModel;
@ -45,8 +46,9 @@ import org.keycloak.services.managers.AuthenticationManager;
import org.keycloak.services.managers.AuthenticationManager.AuthResult;
import org.keycloak.services.managers.ClientSessionCode;
import org.keycloak.services.messages.Messages;
import org.keycloak.services.resources.flows.Flows;
import org.keycloak.services.resources.flows.Urls;
import org.keycloak.services.ErrorResponse;
import org.keycloak.services.ErrorPage;
import org.keycloak.services.Urls;
import org.keycloak.services.validation.Validation;
import org.keycloak.social.SocialIdentityProvider;
import org.keycloak.util.ObjectUtil;
@ -185,15 +187,16 @@ public class IdentityBrokerService implements IdentityProvider.AuthenticationCal
return badRequest("Invalid client.");
}
session.getContext().setClient(clientModel);
if (!clientModel.isAllowedRetrieveTokenFromIdentityProvider(providerId)) {
return corsResponse(badRequest("Client [" + audience + "] not authorized to retrieve tokens from identity provider [" + providerId + "]."), clientModel);
}
if (clientModel.isConsentRequired()) {
return corsResponse(Flows.forms(this.session, this.realmModel, clientModel, this.uriInfo, headers)
return corsResponse(session.getProvider(LoginFormsProvider.class)
.setClientSessionCode(authManager.extractAuthorizationHeaderToken(this.request.getHttpHeaders()))
.setAccessRequest("Your information from " + providerId + " identity provider.")
.setClient(clientModel)
.setActionUri(this.uriInfo.getRequestUri())
.createOAuthGrant(null), clientModel);
}
@ -411,7 +414,7 @@ public class IdentityBrokerService implements IdentityProvider.AuthenticationCal
}
fireErrorEvent(message, throwable);
return Flows.forwardToSecurityFailurePage(this.session, this.realmModel, this.uriInfo, headers, message, parameters);
return ErrorPage.error(this.session, message, parameters);
}
private Response redirectToLoginPage(Throwable t, ClientSessionCode clientCode) {
@ -422,7 +425,7 @@ public class IdentityBrokerService implements IdentityProvider.AuthenticationCal
}
fireErrorEvent(message);
return Flows.forms(this.session, this.realmModel, clientCode.getClientSession().getClient(), this.uriInfo, headers)
return session.getProvider(LoginFormsProvider.class)
.setClientSessionCode(clientCode.getCode())
.setError(message)
.createLogin();
@ -430,7 +433,7 @@ public class IdentityBrokerService implements IdentityProvider.AuthenticationCal
private Response badRequest(String message) {
fireErrorEvent(message);
return Flows.errors().error(message, Status.BAD_REQUEST);
return ErrorResponse.error(message, Status.BAD_REQUEST);
}
public static IdentityProvider getIdentityProvider(KeycloakSession session, RealmModel realm, String alias) {

View file

@ -53,8 +53,8 @@ import org.keycloak.representations.idm.CredentialRepresentation;
import org.keycloak.services.managers.AuthenticationManager;
import org.keycloak.services.managers.ClientSessionCode;
import org.keycloak.services.messages.Messages;
import org.keycloak.services.resources.flows.Flows;
import org.keycloak.services.resources.flows.Urls;
import org.keycloak.services.ErrorPage;
import org.keycloak.services.Urls;
import org.keycloak.services.util.CookieHelper;
import org.keycloak.services.validation.Validation;
@ -162,7 +162,7 @@ public class LoginActionsService {
return false;
} else if (!clientCode.isValid(requiredAction)) {
event.error(Errors.INVALID_CODE);
response = Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.INVALID_CODE);
response = ErrorPage.error(session, Messages.INVALID_CODE);
return false;
} else {
return true;
@ -174,7 +174,7 @@ public class LoginActionsService {
return false;
} else if (!(clientCode.isValid(requiredAction) || clientCode.isValid(alternativeRequiredAction))) {
event.error(Errors.INVALID_CODE);
response = Flows.forwardToSecurityFailurePage(session, realm, uriInfo,headers, Messages.INVALID_CODE);
response = ErrorPage.error(session, Messages.INVALID_CODE);
return false;
} else {
return true;
@ -184,20 +184,21 @@ public class LoginActionsService {
public boolean check(String code) {
if (!checkSsl()) {
event.error(Errors.SSL_REQUIRED);
response = Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.HTTPS_REQUIRED);
response = ErrorPage.error(session, Messages.HTTPS_REQUIRED);
return false;
}
if (!realm.isEnabled()) {
event.error(Errors.REALM_DISABLED);
response = Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.REALM_NOT_ENABLED);
response = ErrorPage.error(session, Messages.REALM_NOT_ENABLED);
return false;
}
clientCode = ClientSessionCode.parse(code, session, realm);
if (clientCode == null) {
event.error(Errors.INVALID_CODE);
response = Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.UNKNOWN_CODE);
response = ErrorPage.error(session, Messages.UNKNOWN_CODE);
return false;
}
session.getContext().setClient(clientCode.getClientSession().getClient());
return true;
}
}
@ -226,10 +227,9 @@ public class LoginActionsService {
clientSession.setAction(ClientSessionModel.Action.AUTHENTICATE);
}
LoginFormsProvider forms = Flows.forms(session, realm, clientSession.getClient(), uriInfo, headers)
.setClientSessionCode(clientSessionCode.getCode());
return forms.createLogin();
return session.getProvider(LoginFormsProvider.class)
.setClientSessionCode(clientSessionCode.getCode())
.createLogin();
}
/**
@ -244,7 +244,7 @@ public class LoginActionsService {
event.event(EventType.REGISTER);
if (!realm.isRegistrationAllowed()) {
event.error(Errors.REGISTRATION_DISABLED);
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.REGISTRATION_NOT_ALLOWED);
return ErrorPage.error(session, Messages.REGISTRATION_NOT_ALLOWED);
}
Checks checks = new Checks();
@ -258,7 +258,7 @@ public class LoginActionsService {
authManager.expireIdentityCookie(realm, uriInfo, clientConnection);
return Flows.forms(session, realm, clientSession.getClient(), uriInfo, headers)
return session.getProvider(LoginFormsProvider.class)
.setClientSessionCode(clientSessionCode.getCode())
.createRegistration();
}
@ -278,17 +278,17 @@ public class LoginActionsService {
event.event(EventType.LOGIN);
if (!checkSsl()) {
event.error(Errors.SSL_REQUIRED);
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.HTTPS_REQUIRED);
return ErrorPage.error(session, Messages.HTTPS_REQUIRED);
}
if (!realm.isEnabled()) {
event.error(Errors.REALM_DISABLED);
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.REALM_NOT_ENABLED);
return ErrorPage.error(session, Messages.REALM_NOT_ENABLED);
}
ClientSessionCode clientCode = ClientSessionCode.parse(code, session, realm);
if (clientCode == null) {
event.error(Errors.INVALID_CODE);
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.UNKNOWN_CODE);
return ErrorPage.error(session, Messages.UNKNOWN_CODE);
}
ClientSessionModel clientSession = clientCode.getClientSession();
@ -297,7 +297,8 @@ public class LoginActionsService {
if (!clientCode.isValid(ClientSessionModel.Action.AUTHENTICATE) || clientSession.getUserSession() != null) {
clientCode.setAction(ClientSessionModel.Action.AUTHENTICATE);
event.client(clientSession.getClient()).error(Errors.EXPIRED_CODE);
return Flows.forms(this.session, realm, clientSession.getClient(), uriInfo, headers).setError(Messages.EXPIRED_CODE)
return session.getProvider(LoginFormsProvider.class)
.setError(Messages.EXPIRED_CODE)
.setClientSessionCode(clientCode.getCode())
.createLogin();
}
@ -320,13 +321,15 @@ public class LoginActionsService {
ClientModel client = clientSession.getClient();
if (client == null) {
event.error(Errors.CLIENT_NOT_FOUND);
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.UNKNOWN_LOGIN_REQUESTER);
return ErrorPage.error(session, Messages.UNKNOWN_LOGIN_REQUESTER);
}
if (!client.isEnabled()) {
event.error(Errors.CLIENT_NOT_FOUND);
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.LOGIN_REQUESTER_NOT_ENABLED);
return ErrorPage.error(session, Messages.LOGIN_REQUESTER_NOT_ENABLED);
}
session.getContext().setClient(clientSession.getClient());
if (formData.containsKey("cancel")) {
event.error(Errors.REJECTED_BY_USER);
LoginProtocol protocol = session.getProvider(LoginProtocol.class, clientSession.getAuthMethod());
@ -358,14 +361,14 @@ public class LoginActionsService {
return authManager.nextActionAfterAuthentication(session, userSession, clientSession, clientConnection, request, uriInfo, event);
case ACCOUNT_TEMPORARILY_DISABLED:
event.error(Errors.USER_TEMPORARILY_DISABLED);
return Flows.forms(this.session, realm, client, uriInfo, headers)
return session.getProvider(LoginFormsProvider.class)
.setError(Messages.ACCOUNT_TEMPORARILY_DISABLED)
.setFormData(formData)
.setClientSessionCode(clientCode.getCode())
.createLogin();
case ACCOUNT_DISABLED:
event.error(Errors.USER_DISABLED);
return Flows.forms(this.session, realm, client, uriInfo, headers)
return session.getProvider(LoginFormsProvider.class)
.setError(Messages.ACCOUNT_DISABLED)
.setClientSessionCode(clientCode.getCode())
.setFormData(formData).createLogin();
@ -375,19 +378,21 @@ public class LoginActionsService {
String passwordToken = new JWSBuilder().jsonContent(new PasswordToken(realm.getName(), user.getId())).rsa256(realm.getPrivateKey());
formData.add(CredentialRepresentation.PASSWORD_TOKEN, passwordToken);
return Flows.forms(this.session, realm, client, uriInfo, headers)
return session.getProvider(LoginFormsProvider.class)
.setFormData(formData)
.setClientSessionCode(clientCode.getCode())
.createLoginTotp();
case INVALID_USER:
event.error(Errors.USER_NOT_FOUND);
return Flows.forms(this.session, realm, client, uriInfo, headers).setError(Messages.INVALID_USER)
return session.getProvider(LoginFormsProvider.class)
.setError(Messages.INVALID_USER)
.setFormData(formData)
.setClientSessionCode(clientCode.getCode())
.createLogin();
default:
event.error(Errors.INVALID_USER_CREDENTIALS);
return Flows.forms(this.session, realm, client, uriInfo, headers).setError(Messages.INVALID_USER)
return session.getProvider(LoginFormsProvider.class)
.setError(Messages.INVALID_USER)
.setFormData(formData)
.setClientSessionCode(clientCode.getCode())
.createLogin();
@ -409,25 +414,25 @@ public class LoginActionsService {
event.event(EventType.REGISTER);
if (!checkSsl()) {
event.error(Errors.SSL_REQUIRED);
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.HTTPS_REQUIRED);
return ErrorPage.error(session, Messages.HTTPS_REQUIRED);
}
if (!realm.isEnabled()) {
event.error(Errors.REALM_DISABLED);
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.REALM_NOT_ENABLED);
return ErrorPage.error(session, Messages.REALM_NOT_ENABLED);
}
if (!realm.isRegistrationAllowed()) {
event.error(Errors.REGISTRATION_DISABLED);
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.REGISTRATION_NOT_ALLOWED);
return ErrorPage.error(session, Messages.REGISTRATION_NOT_ALLOWED);
}
ClientSessionCode clientCode = ClientSessionCode.parse(code, session, realm);
if (clientCode == null) {
event.error(Errors.INVALID_CODE);
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.UNKNOWN_CODE);
return ErrorPage.error(session, Messages.UNKNOWN_CODE);
}
if (!clientCode.isValid(ClientSessionModel.Action.AUTHENTICATE)) {
event.error(Errors.INVALID_CODE);
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.INVALID_CODE);
return ErrorPage.error(session, Messages.INVALID_CODE);
}
String username = formData.getFirst(Validation.FIELD_USERNAME);
@ -446,19 +451,20 @@ public class LoginActionsService {
if (!realm.isEnabled()) {
event.error(Errors.REALM_DISABLED);
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.REALM_NOT_ENABLED);
return ErrorPage.error(session, Messages.REALM_NOT_ENABLED);
}
ClientModel client = clientSession.getClient();
if (client == null) {
event.error(Errors.CLIENT_NOT_FOUND);
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.UNKNOWN_LOGIN_REQUESTER);
return ErrorPage.error(session, Messages.UNKNOWN_LOGIN_REQUESTER);
}
if (!client.isEnabled()) {
event.error(Errors.CLIENT_DISABLED);
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.LOGIN_REQUESTER_NOT_ENABLED);
return ErrorPage.error(session, Messages.LOGIN_REQUESTER_NOT_ENABLED);
}
session.getContext().setClient(client);
List<String> requiredCredentialTypes = new LinkedList<String>();
for (RequiredCredentialModel m : realm.getRequiredCredentials()) {
@ -470,7 +476,7 @@ public class LoginActionsService {
if (errors != null && !errors.isEmpty()) {
event.error(Errors.INVALID_REGISTRATION);
return Flows.forms(session, realm, client, uriInfo, headers)
return session.getProvider(LoginFormsProvider.class)
.setErrors(errors)
.setFormData(formData)
.setClientSessionCode(clientCode.getCode())
@ -480,7 +486,7 @@ public class LoginActionsService {
// Validate that user with this username doesn't exist in realm or any federation provider
if (session.users().getUserByUsername(username, realm) != null) {
event.error(Errors.USERNAME_IN_USE);
return Flows.forms(session, realm, client, uriInfo, headers)
return session.getProvider(LoginFormsProvider.class)
.setError(Messages.USERNAME_EXISTS)
.setFormData(formData)
.setClientSessionCode(clientCode.getCode())
@ -490,7 +496,7 @@ public class LoginActionsService {
// Validate that user with this email doesn't exist in realm or any federation provider
if (email != null && session.users().getUserByEmail(email, realm) != null) {
event.error(Errors.EMAIL_IN_USE);
return Flows.forms(session, realm, client, uriInfo, headers)
return session.getProvider(LoginFormsProvider.class)
.setError(Messages.EMAIL_EXISTS)
.setFormData(formData)
.setClientSessionCode(clientCode.getCode())
@ -527,7 +533,7 @@ public class LoginActionsService {
// User already registered, but force him to update password
if (!passwordUpdateSuccessful) {
user.addRequiredAction(UserModel.RequiredAction.UPDATE_PASSWORD);
return Flows.forms(session, realm, client, uriInfo, headers)
return session.getProvider(LoginFormsProvider.class)
.setError(passwordUpdateError, passwordUpdateErrorParameters)
.setClientSessionCode(clientCode.getCode())
.createResponse(UserModel.RequiredAction.UPDATE_PASSWORD);
@ -556,7 +562,7 @@ public class LoginActionsService {
if (!checkSsl()) {
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.HTTPS_REQUIRED);
return ErrorPage.error(session, Messages.HTTPS_REQUIRED);
}
String code = formData.getFirst("code");
@ -564,7 +570,7 @@ public class LoginActionsService {
ClientSessionCode accessCode = ClientSessionCode.parse(code, session, realm);
if (accessCode == null || !accessCode.isValid(ClientSessionModel.Action.OAUTH_GRANT)) {
event.error(Errors.INVALID_CODE);
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.INVALID_ACCESS_CODE);
return ErrorPage.error(session, Messages.INVALID_ACCESS_CODE);
}
ClientSessionModel clientSession = accessCode.getClientSession();
event.detail(Details.CODE_ID, clientSession.getId());
@ -588,7 +594,7 @@ public class LoginActionsService {
if (!AuthenticationManager.isSessionValid(realm, userSession)) {
AuthenticationManager.backchannelLogout(session, realm, userSession, uriInfo, clientConnection, headers);
event.error(Errors.INVALID_CODE);
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.SESSION_NOT_ACTIVE);
return ErrorPage.error(session, Messages.SESSION_NOT_ACTIVE);
}
event.session(userSession);
@ -625,8 +631,10 @@ public class LoginActionsService {
List<FormMessage> errors = Validation.validateUpdateProfileForm(formData);
if (errors != null && !errors.isEmpty()) {
return Flows.forms(session, realm, null, uriInfo, headers).setUser(user).setErrors(errors)
return session.getProvider(LoginFormsProvider.class)
.setClientSessionCode(accessCode.getCode())
.setUser(user)
.setErrors(errors)
.createResponse(RequiredAction.UPDATE_PROFILE);
}
@ -643,7 +651,9 @@ public class LoginActionsService {
// check for duplicated email
if (userByEmail != null && !userByEmail.getId().equals(user.getId())) {
return Flows.forms(session, realm, null, uriInfo, headers).setUser(user).setError(Messages.EMAIL_EXISTS)
return session.getProvider(LoginFormsProvider.class)
.setUser(user)
.setError(Messages.EMAIL_EXISTS)
.setClientSessionCode(accessCode.getCode())
.createResponse(RequiredAction.UPDATE_PROFILE);
}
@ -682,7 +692,7 @@ public class LoginActionsService {
String totp = formData.getFirst("totp");
String totpSecret = formData.getFirst("totpSecret");
LoginFormsProvider loginForms = Flows.forms(session, realm, null, uriInfo, headers).setUser(user);
LoginFormsProvider loginForms = session.getProvider(LoginFormsProvider.class).setUser(user);
if (Validation.isEmpty(totp)) {
return loginForms.setError(Messages.MISSING_TOTP)
.setClientSessionCode(accessCode.getCode())
@ -727,7 +737,8 @@ public class LoginActionsService {
String passwordNew = formData.getFirst("password-new");
String passwordConfirm = formData.getFirst("password-confirm");
LoginFormsProvider loginForms = Flows.forms(session, realm, null, uriInfo, headers).setUser(user);
LoginFormsProvider loginForms = session.getProvider(LoginFormsProvider.class)
.setUser(user);
if (Validation.isEmpty(passwordNew)) {
return loginForms.setError(Messages.MISSING_PASSWORD)
.setClientSessionCode(accessCode.getCode())
@ -757,7 +768,9 @@ public class LoginActionsService {
if (clientSession.getAction().equals(ClientSessionModel.Action.RECOVER_PASSWORD)) {
String actionCookieValue = getActionCookie();
if (actionCookieValue == null || !actionCookieValue.equals(userSession.getId())) {
return Flows.forms(session, realm, clientSession.getClient(), uriInfo, headers).setSuccess(Messages.ACCOUNT_PASSWORD_UPDATED).createInfoPage();
return session.getProvider(LoginFormsProvider.class)
.setSuccess(Messages.ACCOUNT_PASSWORD_UPDATED)
.createInfoPage();
}
}
@ -789,7 +802,9 @@ public class LoginActionsService {
String actionCookieValue = getActionCookie();
if (actionCookieValue == null || !actionCookieValue.equals(userSession.getId())) {
return Flows.forms(session, realm, clientSession.getClient(), uriInfo, headers).setSuccess(Messages.EMAIL_VERIFIED).createInfoPage();
return session.getProvider(LoginFormsProvider.class)
.setSuccess(Messages.EMAIL_VERIFIED)
.createInfoPage();
}
event = event.clone().removeDetail(Details.EMAIL).event(EventType.LOGIN);
@ -807,7 +822,7 @@ public class LoginActionsService {
createActionCookie(realm, uriInfo, clientConnection, userSession.getId());
return Flows.forms(session, realm, null, uriInfo, headers)
return session.getProvider(LoginFormsProvider.class)
.setClientSessionCode(accessCode.getCode())
.setUser(userSession.getUser())
.createResponse(RequiredAction.VERIFY_EMAIL);
@ -824,11 +839,11 @@ public class LoginActionsService {
return checks.response;
}
ClientSessionCode accessCode = checks.clientCode;
return Flows.forms(session, realm, null, uriInfo, headers)
return session.getProvider(LoginFormsProvider.class)
.setClientSessionCode(accessCode.getCode())
.createResponse(RequiredAction.UPDATE_PASSWORD);
} else {
return Flows.forms(session, realm, null, uriInfo, headers)
return session.getProvider(LoginFormsProvider.class)
.setClientSessionCode(code)
.createPasswordReset();
}
@ -841,16 +856,16 @@ public class LoginActionsService {
final MultivaluedMap<String, String> formData) {
event.event(EventType.SEND_RESET_PASSWORD);
if (!checkSsl()) {
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.HTTPS_REQUIRED);
return ErrorPage.error(session, Messages.HTTPS_REQUIRED);
}
if (!realm.isEnabled()) {
event.error(Errors.REALM_DISABLED);
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.REALM_NOT_ENABLED);
return ErrorPage.error(session, Messages.REALM_NOT_ENABLED);
}
ClientSessionCode accessCode = ClientSessionCode.parse(code, session, realm);
if (accessCode == null) {
event.error(Errors.INVALID_CODE);
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.UNKNOWN_CODE);
return ErrorPage.error(session, Messages.UNKNOWN_CODE);
}
ClientSessionModel clientSession = accessCode.getClientSession();
@ -858,12 +873,14 @@ public class LoginActionsService {
ClientModel client = clientSession.getClient();
if (client == null) {
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.UNKNOWN_LOGIN_REQUESTER);
return ErrorPage.error(session, Messages.UNKNOWN_LOGIN_REQUESTER);
}
if (!client.isEnabled()) {
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.LOGIN_REQUESTER_NOT_ENABLED);
return ErrorPage.error(session, Messages.LOGIN_REQUESTER_NOT_ENABLED);
}
session.getContext().setClient(client);
event.client(client.getClientId())
.detail(Details.REDIRECT_URI, clientSession.getRedirectUri())
.detail(Details.RESPONSE_TYPE, "code")
@ -904,7 +921,8 @@ public class LoginActionsService {
} catch (EmailException e) {
event.error(Errors.EMAIL_SEND_FAILED);
logger.error("Failed to send password reset email", e);
return Flows.forms(this.session, realm, client, uriInfo, headers).setError(Messages.EMAIL_SENT_ERROR)
return session.getProvider(LoginFormsProvider.class)
.setError(Messages.EMAIL_SENT_ERROR)
.setClientSessionCode(accessCode.getCode())
.createErrorPage();
}
@ -912,7 +930,10 @@ public class LoginActionsService {
createActionCookie(realm, uriInfo, clientConnection, userSession.getId());
}
return Flows.forms(session, realm, client, uriInfo, headers).setSuccess(Messages.EMAIL_SENT).setClientSessionCode(accessCode.getCode()).createPasswordReset();
return session.getProvider(LoginFormsProvider.class)
.setSuccess(Messages.EMAIL_SENT)
.setClientSessionCode(accessCode.getCode())
.createPasswordReset();
}
private String getActionCookie() {

View file

@ -24,7 +24,6 @@ import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriBuilder;
@ -38,17 +37,6 @@ import javax.ws.rs.core.UriInfo;
public class RealmsResource {
protected static Logger logger = Logger.getLogger(RealmsResource.class);
@Context
protected UriInfo uriInfo;
@Context
protected HttpHeaders headers;
/*
@Context
protected ResourceContext resourceContext;
*/
@Context
protected KeycloakSession session;
@ -62,18 +50,10 @@ public class RealmsResource {
return uriInfo.getBaseUriBuilder().path(RealmsResource.class).path(RealmsResource.class, "getRealmResource");
}
public static UriBuilder realmBaseUrl(UriBuilder base) {
return base.path(RealmsResource.class).path(RealmsResource.class, "getRealmResource");
}
public static UriBuilder accountUrl(UriBuilder base) {
return base.path(RealmsResource.class).path(RealmsResource.class, "getAccountService");
}
public static UriBuilder protocolUrl(UriBuilder base) {
return base.path(RealmsResource.class).path(RealmsResource.class, "getProtocol");
}
public static UriBuilder protocolUrl(UriInfo uriInfo) {
return uriInfo.getBaseUriBuilder().path(RealmsResource.class).path(RealmsResource.class, "getProtocol");
}
@ -87,9 +67,8 @@ public class RealmsResource {
public Object getLoginStatusIframe(final @PathParam("realm") String name,
@QueryParam("client_id") String client_id,
@QueryParam("origin") String origin) {
// backward compatibility
RealmManager realmManager = new RealmManager(session);
RealmModel realm = locateRealm(name, realmManager);
RealmModel realm = init(name);
EventBuilder event = new EventBuilder(realm, session, clientConnection);
AuthenticationManager authManager = new AuthenticationManager(protector);
@ -104,8 +83,8 @@ public class RealmsResource {
@Path("{realm}/protocol/{protocol}")
public Object getProtocol(final @PathParam("realm") String name,
final @PathParam("protocol") String protocol) {
RealmManager realmManager = new RealmManager(session);
RealmModel realm = locateRealm(name, realmManager);
RealmModel realm = init(name);
EventBuilder event = new EventBuilder(realm, session, clientConnection);
AuthenticationManager authManager = new AuthenticationManager(protector);
@ -125,8 +104,7 @@ public class RealmsResource {
@Path("{realm}/login-actions")
public LoginActionsService getLoginActionsService(final @PathParam("realm") String name) {
RealmManager realmManager = new RealmManager(session);
RealmModel realm = locateRealm(name, realmManager);
RealmModel realm = init(name);
EventBuilder event = new EventBuilder(realm, session, clientConnection);
AuthenticationManager authManager = new AuthenticationManager(protector);
LoginActionsService service = new LoginActionsService(realm, authManager, event);
@ -136,26 +114,26 @@ public class RealmsResource {
@Path("{realm}/clients-managements")
public ClientsManagementService getClientsManagementService(final @PathParam("realm") String name) {
RealmManager realmManager = new RealmManager(session);
RealmModel realm = locateRealm(name, realmManager);
RealmModel realm = init(name);
EventBuilder event = new EventBuilder(realm, session, clientConnection);
ClientsManagementService service = new ClientsManagementService(realm, event);
ResteasyProviderFactory.getInstance().injectProperties(service);
return service;
}
protected RealmModel locateRealm(String name, RealmManager realmManager) {
RealmModel realm = realmManager.getRealmByName(name);
private RealmModel init(String realmName) {
RealmManager realmManager = new RealmManager(session);
RealmModel realm = realmManager.getRealmByName(realmName);
if (realm == null) {
throw new NotFoundException("Realm does not exist");
}
session.getContext().setRealm(realm);
return realm;
}
@Path("{realm}/account")
public AccountService getAccountService(final @PathParam("realm") String name) {
RealmManager realmManager = new RealmManager(session);
RealmModel realm = locateRealm(name, realmManager);
RealmModel realm = init(name);
ClientModel client = realm.getClientNameMap().get(Constants.ACCOUNT_MANAGEMENT_CLIENT_ID);
if (client == null || !client.isEnabled()) {
@ -172,8 +150,7 @@ public class RealmsResource {
@Path("{realm}")
public PublicRealmResource getRealmResource(final @PathParam("realm") String name) {
RealmManager realmManager = new RealmManager(session);
RealmModel realm = locateRealm(name, realmManager);
RealmModel realm = init(name);
PublicRealmResource realmResource = new PublicRealmResource(realm);
ResteasyProviderFactory.getInstance().injectProperties(realmResource);
return realmResource;
@ -181,8 +158,7 @@ public class RealmsResource {
@Path("{realm}/broker")
public IdentityBrokerService getBrokerService(final @PathParam("realm") String name) {
RealmManager realmManager = new RealmManager(session);
RealmModel realm = locateRealm(name, realmManager);
RealmModel realm = init(name);
IdentityBrokerService brokerService = new IdentityBrokerService(realm);
ResteasyProviderFactory.getInstance().injectProperties(brokerService);
@ -195,12 +171,12 @@ public class RealmsResource {
@GET
@Path("{realm}/.well-known/{provider}")
@Produces(MediaType.APPLICATION_JSON)
public Response getWellKnown(final @PathParam("realm") String realmName,
public Response getWellKnown(final @PathParam("realm") String name,
final @PathParam("provider") String providerName) {
RealmManager realmManager = new RealmManager(session);
RealmModel realm = locateRealm(realmName, realmManager);
init(name);
WellKnownProvider wellKnown = session.getProvider(WellKnownProvider.class, providerName);
return Response.ok(wellKnown.getConfig(realm, uriInfo)).build();
return Response.ok(wellKnown.getConfig()).build();
}
}

View file

@ -26,7 +26,7 @@ import org.keycloak.services.managers.ClientManager;
import org.keycloak.services.managers.AuthenticationManager;
import org.keycloak.services.managers.RealmManager;
import org.keycloak.services.resources.KeycloakApplication;
import org.keycloak.services.resources.flows.Urls;
import org.keycloak.services.Urls;
import javax.ws.rs.GET;
import javax.ws.rs.Path;

View file

@ -23,7 +23,7 @@ import org.keycloak.services.managers.ClientManager;
import org.keycloak.services.managers.RealmManager;
import org.keycloak.services.managers.ResourceAdminManager;
import org.keycloak.services.resources.KeycloakApplication;
import org.keycloak.services.resources.flows.Flows;
import org.keycloak.services.ErrorResponse;
import org.keycloak.util.JsonSerialization;
import org.keycloak.util.Time;
@ -100,7 +100,7 @@ public class ClientResource {
RepresentationToModel.updateClient(rep, client);
return Response.noContent().build();
} catch (ModelDuplicateException e) {
return Flows.errors().exists("Client " + rep.getClientId() + " already exists");
return ErrorResponse.exists("Client " + rep.getClientId() + " already exists");
}
}

View file

@ -11,7 +11,7 @@ import org.keycloak.models.RealmModel;
import org.keycloak.models.utils.ModelToRepresentation;
import org.keycloak.models.utils.RepresentationToModel;
import org.keycloak.representations.idm.ClientRepresentation;
import org.keycloak.services.resources.flows.Flows;
import org.keycloak.services.ErrorResponse;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
@ -91,7 +91,7 @@ public class ClientsResource {
ClientModel clientModel = RepresentationToModel.createClient(session, realm, rep, true);
return Response.created(uriInfo.getAbsolutePathBuilder().path(getClientPath(clientModel)).build()).build();
} catch (ModelDuplicateException e) {
return Flows.errors().exists("Client " + rep.getClientId() + " already exists");
return ErrorResponse.exists("Client " + rep.getClientId() + " already exists");
}
}

View file

@ -16,7 +16,7 @@ import org.keycloak.models.utils.ModelToRepresentation;
import org.keycloak.models.utils.RepresentationToModel;
import org.keycloak.provider.ProviderFactory;
import org.keycloak.representations.idm.IdentityProviderRepresentation;
import org.keycloak.services.resources.flows.Flows;
import org.keycloak.services.ErrorResponse;
import org.keycloak.social.SocialIdentityProvider;
import javax.ws.rs.Consumes;
@ -96,7 +96,7 @@ public class IdentityProviderResource {
return Response.noContent().build();
} catch (ModelDuplicateException e) {
return Flows.errors().exists("Identity Provider " + providerRep.getAlias() + " already exists");
return ErrorResponse.exists("Identity Provider " + providerRep.getAlias() + " already exists");
}
}
@ -169,7 +169,7 @@ public class IdentityProviderResource {
IdentityProviderFactory factory = getIdentityProviderFactory();
return factory.create(identityProviderModel).export(uriInfo, realm, format);
} catch (Exception e) {
return Flows.errors().error("Could not export public broker configuration for identity provider [" + identityProviderModel.getProviderId() + "].", Response.Status.NOT_FOUND);
return ErrorResponse.error("Could not export public broker configuration for identity provider [" + identityProviderModel.getProviderId() + "].", Response.Status.NOT_FOUND);
}
}

View file

@ -17,7 +17,7 @@ import org.keycloak.models.utils.RepresentationToModel;
import org.keycloak.provider.ProviderFactory;
import org.keycloak.representations.idm.IdentityProviderRepresentation;
import org.keycloak.services.managers.ResourceAdminManager;
import org.keycloak.services.resources.flows.Flows;
import org.keycloak.services.ErrorResponse;
import org.keycloak.social.SocialIdentityProvider;
import javax.ws.rs.Consumes;
@ -132,7 +132,7 @@ public class IdentityProvidersResource {
return Response.created(uriInfo.getAbsolutePathBuilder().path(representation.getProviderId()).build()).build();
} catch (ModelDuplicateException e) {
return Flows.errors().exists("Identity Provider " + representation.getAlias() + " already exists");
return ErrorResponse.exists("Identity Provider " + representation.getAlias() + " already exists");
}
}

View file

@ -29,7 +29,7 @@ import org.keycloak.services.managers.LDAPConnectionTestManager;
import org.keycloak.services.managers.RealmManager;
import org.keycloak.services.managers.ResourceAdminManager;
import org.keycloak.services.managers.UsersSyncManager;
import org.keycloak.services.resources.flows.Flows;
import org.keycloak.services.ErrorResponse;
import org.keycloak.timer.TimerProvider;
import javax.ws.rs.Consumes;
@ -191,11 +191,11 @@ public class RealmAdminResource {
return Response.noContent().build();
} catch (PatternSyntaxException e) {
return Flows.errors().exists("Specified regex pattern(s) is invalid.");
return ErrorResponse.exists("Specified regex pattern(s) is invalid.");
} catch (ModelDuplicateException e) {
return Flows.errors().exists("Realm " + rep.getRealm() + " already exists.");
return ErrorResponse.exists("Realm " + rep.getRealm() + " already exists.");
} catch (Exception e) {
return Flows.errors().exists("Failed to update " + rep.getRealm() + " Realm.");
return ErrorResponse.exists("Failed to update " + rep.getRealm() + " Realm.");
}
}
@ -442,7 +442,7 @@ public class RealmAdminResource {
auth.init(RealmAuth.Resource.REALM).requireManage();
boolean result = new LDAPConnectionTestManager().testLDAP(action, connectionUrl, bindDn, bindCredential);
return result ? Response.noContent().build() : Flows.errors().error("LDAP test error", Response.Status.BAD_REQUEST);
return result ? Response.noContent().build() : ErrorResponse.error("LDAP test error", Response.Status.BAD_REQUEST);
}
@Path("identity-provider")

View file

@ -18,7 +18,7 @@ import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.services.ForbiddenException;
import org.keycloak.services.managers.RealmManager;
import org.keycloak.services.resources.KeycloakApplication;
import org.keycloak.services.resources.flows.Flows;
import org.keycloak.services.ErrorResponse;
import org.keycloak.util.JsonSerialization;
import javax.ws.rs.Consumes;
@ -131,7 +131,7 @@ public class RealmsAdminResource {
return Response.created(location).build();
} catch (ModelDuplicateException e) {
return Flows.errors().exists("Realm " + rep.getRealm() + " already exists");
return ErrorResponse.exists("Realm " + rep.getRealm() + " already exists");
}
}
@ -166,7 +166,7 @@ public class RealmsAdminResource {
try {
realm = realmManager.importRealm(rep);
} catch (ModelDuplicateException e) {
return Flows.errors().exists("Realm " + rep.getRealm() + " already exists");
return ErrorResponse.exists("Realm " + rep.getRealm() + " already exists");
}
grantPermissionsToRealmCreator(realm);

View file

@ -9,7 +9,7 @@ import org.keycloak.models.RoleContainerModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.utils.ModelToRepresentation;
import org.keycloak.representations.idm.RoleRepresentation;
import org.keycloak.services.resources.flows.Flows;
import org.keycloak.services.ErrorResponse;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
@ -79,7 +79,7 @@ public class RoleContainerResource extends RoleResource {
role.setDescription(rep.getDescription());
return Response.created(uriInfo.getAbsolutePathBuilder().path(role.getName()).build()).build();
} catch (ModelDuplicateException e) {
return Flows.errors().exists("Role with name " + rep.getName() + " already exists");
return ErrorResponse.exists("Role with name " + rep.getName() + " already exists");
}
}
@ -144,7 +144,7 @@ public class RoleContainerResource extends RoleResource {
updateRole(rep, role);
return Response.noContent().build();
} catch (ModelDuplicateException e) {
return Flows.errors().exists("Role with name " + rep.getName() + " already exists");
return ErrorResponse.exists("Role with name " + rep.getName() + " already exists");
}
}

View file

@ -36,8 +36,8 @@ import org.keycloak.services.managers.AuthenticationManager;
import org.keycloak.services.managers.ClientSessionCode;
import org.keycloak.services.managers.RealmManager;
import org.keycloak.services.managers.UserManager;
import org.keycloak.services.resources.flows.Flows;
import org.keycloak.services.resources.flows.Urls;
import org.keycloak.services.ErrorResponse;
import org.keycloak.services.Urls;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
@ -123,9 +123,9 @@ public class UsersResource {
return Response.noContent().build();
} catch (ModelDuplicateException e) {
return Flows.errors().exists("User exists with same username or email");
return ErrorResponse.exists("User exists with same username or email");
} catch (ModelReadOnlyException re) {
return Flows.errors().exists("User is read only!");
return ErrorResponse.exists("User is read only!");
}
}
@ -143,10 +143,10 @@ public class UsersResource {
// Double-check duplicated username and email here due to federation
if (session.users().getUserByUsername(rep.getUsername(), realm) != null) {
return Flows.errors().exists("User exists with same username");
return ErrorResponse.exists("User exists with same username");
}
if (rep.getEmail() != null && session.users().getUserByEmail(rep.getEmail(), realm) != null) {
return Flows.errors().exists("User exists with same email");
return ErrorResponse.exists("User exists with same email");
}
try {
@ -162,7 +162,7 @@ public class UsersResource {
if (session.getTransaction().isActive()) {
session.getTransaction().setRollbackOnly();
}
return Flows.errors().exists("User exists with same username or email");
return ErrorResponse.exists("User exists with same username or email");
}
}
@ -287,7 +287,7 @@ public class UsersResource {
throw new NotFoundException("User not found");
}
if (session.users().getFederatedIdentity(user, provider, realm) != null) {
return Flows.errors().exists("User is already linked with provider");
return ErrorResponse.exists("User is already linked with provider");
}
FederatedIdentityModel socialLink = new FederatedIdentityModel(provider, rep.getUserId(), rep.getUserName());
@ -352,7 +352,7 @@ public class UsersResource {
if (removed) {
return Response.noContent().build();
} else {
return Flows.errors().error("User couldn't be deleted", Response.Status.BAD_REQUEST);
return ErrorResponse.error("User couldn't be deleted", Response.Status.BAD_REQUEST);
}
}
@ -702,19 +702,19 @@ public class UsersResource {
UserModel user = session.users().getUserByUsername(username, realm);
if (user == null) {
return Flows.errors().error("User not found", Response.Status.NOT_FOUND);
return ErrorResponse.error("User not found", Response.Status.NOT_FOUND);
}
if (!user.isEnabled()) {
return Flows.errors().error("User is disabled", Response.Status.BAD_REQUEST);
return ErrorResponse.error("User is disabled", Response.Status.BAD_REQUEST);
}
if (user.getEmail() == null) {
return Flows.errors().error("User email missing", Response.Status.BAD_REQUEST);
return ErrorResponse.error("User email missing", Response.Status.BAD_REQUEST);
}
if(redirectUri != null && clientId == null){
return Flows.errors().error("Client id missing", Response.Status.BAD_REQUEST);
return ErrorResponse.error("Client id missing", Response.Status.BAD_REQUEST);
}
if(clientId == null){
@ -723,14 +723,14 @@ public class UsersResource {
ClientModel client = realm.getClientByClientId(clientId);
if (client == null || !client.isEnabled()) {
return Flows.errors().error(clientId + " not enabled", Response.Status.INTERNAL_SERVER_ERROR);
return ErrorResponse.error(clientId + " not enabled", Response.Status.INTERNAL_SERVER_ERROR);
}
String redirect;
if(redirectUri != null){
redirect = RedirectUtils.verifyRedirectUri(uriInfo, redirectUri, realm, client);
if(redirect == null){
return Flows.errors().error("Invalid redirect uri.", Response.Status.BAD_REQUEST);
return ErrorResponse.error("Invalid redirect uri.", Response.Status.BAD_REQUEST);
}
}else{
redirect = Urls.accountBase(uriInfo.getBaseUri()).path("/").build(realm.getName()).toString();
@ -760,7 +760,7 @@ public class UsersResource {
return Response.ok().build();
} catch (EmailException e) {
logger.error("Failed to send password reset email", e);
return Flows.errors().error("Failed to send email", Response.Status.INTERNAL_SERVER_ERROR);
return ErrorResponse.error("Failed to send email", Response.Status.INTERNAL_SERVER_ERROR);
}
}

View file

@ -1,76 +0,0 @@
package org.keycloak.services.resources.flows;
import org.jboss.logging.Logger;
import org.jboss.resteasy.spi.BadRequestException;
import org.keycloak.AbstractOAuthClient;
import org.keycloak.OAuth2Constants;
import javax.ws.rs.core.Cookie;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.NewCookie;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriInfo;
import java.net.URI;
/**
* Helper code to obtain oauth access tokens via browser redirects
*
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class OAuthRedirect extends AbstractOAuthClient {
protected static final Logger logger = Logger.getLogger(OAuthRedirect.class);
/**
* closes client
*/
public void stop() {
}
public Response redirect(UriInfo uriInfo, String redirectUri) {
String state = getStateCode();
UriBuilder uriBuilder = UriBuilder.fromUri(authUrl)
.queryParam(OAuth2Constants.CLIENT_ID, clientId)
.queryParam(OAuth2Constants.REDIRECT_URI, redirectUri)
.queryParam(OAuth2Constants.STATE, state)
.queryParam(OAuth2Constants.RESPONSE_TYPE, OAuth2Constants.CODE);
if (scope != null) {
uriBuilder.queryParam(OAuth2Constants.SCOPE, scope);
}
URI url = uriBuilder.build();
// todo httpOnly!
NewCookie cookie = new NewCookie(getStateCookieName(), state, getStateCookiePath(uriInfo), null, null, -1, isSecure);
logger.debug("NewCookie: " + cookie.toString());
logger.debug("Oauth Redirect to: " + url);
return Response.status(302)
.location(url)
.cookie(cookie).build();
}
public String getStateCookiePath(UriInfo uriInfo) {
if (stateCookiePath != null) return stateCookiePath;
return uriInfo.getBaseUri().getRawPath();
}
public String getError(UriInfo uriInfo) {
return uriInfo.getQueryParameters().getFirst(OAuth2Constants.ERROR);
}
public String getAccessCode(UriInfo uriInfo) {
return uriInfo.getQueryParameters().getFirst(OAuth2Constants.CODE);
}
public void checkStateCookie(UriInfo uriInfo, HttpHeaders headers) {
Cookie stateCookie = headers.getCookies().get(stateCookieName);
if (stateCookie == null) throw new BadRequestException("state cookie not set");
String state = uriInfo.getQueryParameters().getFirst(OAuth2Constants.STATE);
if (state == null) throw new BadRequestException("state parameter was null");
if (!state.equals(stateCookie.getValue())) {
throw new BadRequestException("state parameter invalid");
}
}
}

View file

@ -1,16 +1,12 @@
package org.keycloak.wellknown;
import org.keycloak.models.RealmModel;
import org.keycloak.provider.Provider;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public interface WellKnownProvider extends Provider {
Object getConfig(RealmModel realm, UriInfo uriInfo);
Object getConfig();
}

View file

@ -37,7 +37,7 @@ import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.services.managers.ClientSessionCode;
import org.keycloak.services.messages.Messages;
import org.keycloak.services.resources.flows.Flows;
import org.keycloak.services.ErrorPage;
import org.keycloak.social.SocialIdentityProvider;
import twitter4j.Twitter;
import twitter4j.TwitterFactory;
@ -158,7 +158,7 @@ public class TwitterIdentityProvider extends AbstractIdentityProvider<OAuth2Iden
EventBuilder event = new EventBuilder(realm, session, clientConnection);
event.event(EventType.LOGIN);
event.error("twitter_login_failed");
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.UNEXPECTED_ERROR_HANDLING_RESPONSE);
return ErrorPage.error(session, Messages.UNEXPECTED_ERROR_HANDLING_RESPONSE);
}
private ClientSessionCode parseClientSessionCode(String code) {

View file

@ -43,6 +43,11 @@
<artifactId>keycloak-admin-client</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>event-listener-sysout-example</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>

View file

@ -7,6 +7,13 @@
"provider": "${keycloak.eventStore.provider:jpa}"
},
"eventsListener": {
"jboss-logging" : {
"success-level": "debug",
"error-level": "warn"
}
},
"realm": {
"provider": "${keycloak.realm.provider:jpa}"
},

View file

@ -6,6 +6,9 @@ log4j.appender.stdout.layout.ConversionPattern=%d{HH:mm:ss,SSS} %-5p [%c] %m%n
log4j.logger.org.keycloak=info
# Enable to view events
# log4j.logger.org.keycloak.events=debug
# Enable to view loaded SPI and Providers
# log4j.logger.org.keycloak.services.DefaultKeycloakSessionFactory=debug
# log4j.logger.org.keycloak.provider.ProviderManager=debug

View file

@ -38,7 +38,7 @@ import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.UserModel.RequiredAction;
import org.keycloak.representations.IDToken;
import org.keycloak.services.resources.flows.Urls;
import org.keycloak.services.Urls;
import org.keycloak.testsuite.OAuthClient;
import org.keycloak.testsuite.OAuthClient.AccessTokenResponse;
import org.keycloak.testsuite.broker.util.UserSessionStatusServlet.UserSessionStatus;

View file

@ -2,7 +2,7 @@ package org.keycloak.testsuite.pages;
import javax.ws.rs.core.UriBuilder;
import org.keycloak.services.resources.flows.Urls;
import org.keycloak.services.Urls;
import org.keycloak.testsuite.Constants;
import org.openqa.selenium.By;

View file

@ -21,7 +21,7 @@
*/
package org.keycloak.testsuite.pages;
import org.keycloak.services.resources.flows.Urls;
import org.keycloak.services.Urls;
import org.keycloak.testsuite.Constants;
import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;

View file

@ -21,7 +21,7 @@
*/
package org.keycloak.testsuite.pages;
import org.keycloak.services.resources.flows.Urls;
import org.keycloak.services.Urls;
import org.keycloak.testsuite.Constants;
import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;

View file

@ -103,11 +103,6 @@ public class LoginPage extends AbstractPage {
return loginErrorMessage != null ? loginErrorMessage.getText() : null;
}
public String getWarning() {
return loginWarningMessage != null ? loginWarningMessage.getText() : null;
}
public boolean isCurrent() {
return driver.getTitle().equals("Log in to test") || driver.getTitle().equals("Anmeldung bei test");
}