diff --git a/services/src/main/java/org/keycloak/protocol/oidc/OpenIDConnectService.java b/services/src/main/java/org/keycloak/protocol/oidc/OpenIDConnectService.java
index 674f594..71d7b19 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/OpenIDConnectService.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/OpenIDConnectService.java
@@ -631,7 +631,6 @@ public class OpenIDConnectService {
*
*/
private class FrontPageInitializer {
- protected String code;
protected String clientId;
protected String redirect;
protected String state;
@@ -642,11 +641,7 @@ public class OpenIDConnectService {
protected ClientSessionModel clientSession;
public Response processInput() {
- if (code != null) {
- event.detail(Details.CODE_ID, code);
- } else {
- event.client(clientId).detail(Details.REDIRECT_URI, redirect).detail(Details.RESPONSE_TYPE, "code");
- }
+ event.client(clientId).detail(Details.REDIRECT_URI, redirect).detail(Details.RESPONSE_TYPE, "code");
if (!checkSsl()) {
event.error(Errors.SSL_REQUIRED);
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, "HTTPS required");
@@ -657,65 +652,43 @@ public class OpenIDConnectService {
}
clientSession = null;
- if (code != null) {
- ClientSessionCode clientCode = ClientSessionCode.parse(code, session, realm);
- if (clientCode == null) {
- event.error(Errors.INVALID_CODE);
- return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, "Unknown code, please login again through your application.");
- }
- if (!clientCode.isValid(ClientSessionModel.Action.AUTHENTICATE)) {
- event.error(Errors.INVALID_CODE);
- return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, "Invalid code, please login again through your application.");
- }
- clientSession = clientCode.getClientSession();
- if (!clientSession.getAuthMethod().equals(OpenIDConnect.LOGIN_PROTOCOL)) {
- event.error(Errors.INVALID_CODE);
- return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, "Invalid protocol, please login again through your application.");
- }
- state = clientSession.getNote(OpenIDConnect.STATE_PARAM);
- scopeParam = clientSession.getNote(OpenIDConnect.SCOPE_PARAM);
- responseType = clientSession.getNote(OpenIDConnect.RESPONSE_TYPE_PARAM);
- loginHint = clientSession.getNote(OpenIDConnect.LOGIN_HINT_PARAM);
- prompt = clientSession.getNote(OpenIDConnect.PROMPT_PARAM);
- } else {
- if (state == null) {
- event.error(Errors.STATE_PARAM_NOT_FOUND);
- return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, "Invalid state param.");
+ if (state == null) {
+ event.error(Errors.STATE_PARAM_NOT_FOUND);
+ return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, "Invalid state param.");
- }
- ClientModel client = realm.findClient(clientId);
- if (client == null) {
- event.error(Errors.CLIENT_NOT_FOUND);
- return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, "Unknown login requester.");
- }
+ }
+ ClientModel client = realm.findClient(clientId);
+ if (client == null) {
+ event.error(Errors.CLIENT_NOT_FOUND);
+ return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, "Unknown login requester.");
+ }
- if (!client.isEnabled()) {
- event.error(Errors.CLIENT_DISABLED);
- return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, "Login requester not enabled.");
- }
- if ((client instanceof ApplicationModel) && ((ApplicationModel)client).isBearerOnly()) {
- event.error(Errors.NOT_ALLOWED);
- return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, "Bearer-only applications are not allowed to initiate browser login");
- }
- if (client.isDirectGrantsOnly()) {
- event.error(Errors.NOT_ALLOWED);
- return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, "direct-grants-only clients are not allowed to initiate browser login");
- }
- redirect = verifyRedirectUri(uriInfo, redirect, realm, client);
- if (redirect == null) {
- event.error(Errors.INVALID_REDIRECT_URI);
- return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, "Invalid redirect_uri.");
- }
- clientSession = session.sessions().createClientSession(realm, client);
- clientSession.setAuthMethod(OpenIDConnect.LOGIN_PROTOCOL);
- clientSession.setRedirectUri(redirect);
- clientSession.setAction(ClientSessionModel.Action.AUTHENTICATE);
- clientSession.setNote(OpenIDConnect.STATE_PARAM, state);
- if (scopeParam != null) clientSession.setNote(OpenIDConnect.SCOPE_PARAM, scopeParam);
- if (responseType != null) clientSession.setNote(OpenIDConnect.RESPONSE_TYPE_PARAM, responseType);
- if (loginHint != null) clientSession.setNote(OpenIDConnect.LOGIN_HINT_PARAM, loginHint);
- if (prompt != null) clientSession.setNote(OpenIDConnect.PROMPT_PARAM, prompt);
+ if (!client.isEnabled()) {
+ event.error(Errors.CLIENT_DISABLED);
+ return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, "Login requester not enabled.");
+ }
+ if ((client instanceof ApplicationModel) && ((ApplicationModel)client).isBearerOnly()) {
+ event.error(Errors.NOT_ALLOWED);
+ return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, "Bearer-only applications are not allowed to initiate browser login");
+ }
+ if (client.isDirectGrantsOnly()) {
+ event.error(Errors.NOT_ALLOWED);
+ return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, "direct-grants-only clients are not allowed to initiate browser login");
+ }
+ redirect = verifyRedirectUri(uriInfo, redirect, realm, client);
+ if (redirect == null) {
+ event.error(Errors.INVALID_REDIRECT_URI);
+ return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, "Invalid redirect_uri.");
}
+ clientSession = session.sessions().createClientSession(realm, client);
+ clientSession.setAuthMethod(OpenIDConnect.LOGIN_PROTOCOL);
+ clientSession.setRedirectUri(redirect);
+ clientSession.setAction(ClientSessionModel.Action.AUTHENTICATE);
+ clientSession.setNote(OpenIDConnect.STATE_PARAM, state);
+ if (scopeParam != null) clientSession.setNote(OpenIDConnect.SCOPE_PARAM, scopeParam);
+ if (responseType != null) clientSession.setNote(OpenIDConnect.RESPONSE_TYPE_PARAM, responseType);
+ if (loginHint != null) clientSession.setNote(OpenIDConnect.LOGIN_HINT_PARAM, loginHint);
+ if (prompt != null) clientSession.setNote(OpenIDConnect.PROMPT_PARAM, prompt);
return null;
}
}
@@ -726,7 +699,6 @@ public class OpenIDConnectService {
* @See <a href="http://tools.ietf.org/html/rfc6749#section-4.1">http://tools.ietf.org/html/rfc6749#section-4.1</a>
*
*
- * @param code
* @param responseType
* @param redirect
* @param clientId
@@ -737,8 +709,7 @@ public class OpenIDConnectService {
*/
@Path("login")
@GET
- public Response loginPage(@QueryParam("code") String code,
- @QueryParam(OpenIDConnect.RESPONSE_TYPE_PARAM) String responseType,
+ public Response loginPage(@QueryParam(OpenIDConnect.RESPONSE_TYPE_PARAM) String responseType,
@QueryParam(OpenIDConnect.REDIRECT_URI_PARAM) String redirect,
@QueryParam(OpenIDConnect.CLIENT_ID_PARAM) String clientId,
@QueryParam(OpenIDConnect.SCOPE_PARAM) String scopeParam,
@@ -747,7 +718,6 @@ public class OpenIDConnectService {
@QueryParam(OpenIDConnect.LOGIN_HINT_PARAM) String loginHint) {
event.event(EventType.LOGIN);
FrontPageInitializer pageInitializer = new FrontPageInitializer();
- pageInitializer.code = code;
pageInitializer.responseType = responseType;
pageInitializer.redirect = redirect;
pageInitializer.clientId = clientId;
@@ -758,14 +728,6 @@ public class OpenIDConnectService {
Response response = pageInitializer.processInput();
if (response != null) return response;
ClientSessionModel clientSession = pageInitializer.clientSession;
- code = pageInitializer.code;
- responseType = pageInitializer.responseType;
- redirect = pageInitializer.redirect;
- clientId = pageInitializer.clientId ;
- scopeParam = pageInitializer.scopeParam;
- state = pageInitializer.state;
- prompt = pageInitializer.prompt;
- loginHint = pageInitializer.loginHint;
@@ -822,8 +784,7 @@ public class OpenIDConnectService {
*/
@Path("registrations")
@GET
- public Response registerPage(@QueryParam("code") String code,
- @QueryParam(OpenIDConnect.RESPONSE_TYPE_PARAM) String responseType,
+ public Response registerPage(@QueryParam(OpenIDConnect.RESPONSE_TYPE_PARAM) String responseType,
@QueryParam(OpenIDConnect.REDIRECT_URI_PARAM) String redirect,
@QueryParam(OpenIDConnect.CLIENT_ID_PARAM) String clientId,
@QueryParam(OpenIDConnect.SCOPE_PARAM) String scopeParam,
@@ -835,7 +796,6 @@ public class OpenIDConnectService {
}
FrontPageInitializer pageInitializer = new FrontPageInitializer();
- pageInitializer.code = code;
pageInitializer.responseType = responseType;
pageInitializer.redirect = redirect;
pageInitializer.clientId = clientId;
diff --git a/services/src/main/java/org/keycloak/services/resources/flows/Urls.java b/services/src/main/java/org/keycloak/services/resources/flows/Urls.java
index af0efa4..2e4148e 100755
--- a/services/src/main/java/org/keycloak/services/resources/flows/Urls.java
+++ b/services/src/main/java/org/keycloak/services/resources/flows/Urls.java
@@ -138,10 +138,10 @@ public class Urls {
}
public static URI realmLoginPage(URI baseUri, String realmId) {
- return tokenBase(baseUri).path(OpenIDConnectService.class, "loginPage").build(realmId);
+ return requiredActionsBase(baseUri).path(LoginActionsService.class, "loginPage").build(realmId);
}
- public static UriBuilder realmLogout(URI baseUri) {
+ private static UriBuilder realmLogout(URI baseUri) {
return tokenBase(baseUri).path(OpenIDConnectService.class, "logout");
}
@@ -150,7 +150,7 @@ public class Urls {
}
public static URI realmRegisterPage(URI baseUri, String realmId) {
- return tokenBase(baseUri).path(OpenIDConnectService.class, "registerPage").build(realmId);
+ return requiredActionsBase(baseUri).path(LoginActionsService.class, "registerPage").build(realmId);
}
public static URI realmInstalledAppUrnCallback(URI baseUri, String realmId) {
@@ -161,10 +161,6 @@ public class Urls {
return requiredActionsBase(baseUri).path(LoginActionsService.class, "processConsent").build(realmId);
}
- public static URI realmCode(URI baseUri, String realmId) {
- return tokenBase(baseUri).path(OpenIDConnectService.class, "accessCodeToToken").build(realmId);
- }
-
public static UriBuilder socialBase(URI baseUri) {
return UriBuilder.fromUri(baseUri).path(SocialResource.class);
}
diff --git a/services/src/main/java/org/keycloak/services/resources/LoginActionsService.java b/services/src/main/java/org/keycloak/services/resources/LoginActionsService.java
index 3a0e6d6..c6bcc8c 100755
--- a/services/src/main/java/org/keycloak/services/resources/LoginActionsService.java
+++ b/services/src/main/java/org/keycloak/services/resources/LoginActionsService.java
@@ -22,6 +22,7 @@
package org.keycloak.services.resources;
import org.jboss.logging.Logger;
+import org.jboss.resteasy.specimpl.MultivaluedMapImpl;
import org.jboss.resteasy.spi.HttpRequest;
import org.keycloak.ClientConnection;
import org.keycloak.email.EmailException;
@@ -44,6 +45,7 @@ import org.keycloak.models.UserSessionModel;
import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.models.utils.TimeBasedOTP;
import org.keycloak.protocol.LoginProtocol;
+import org.keycloak.protocol.oidc.OpenIDConnect;
import org.keycloak.protocol.oidc.OpenIDConnectService;
import org.keycloak.protocol.oidc.TokenManager;
import org.keycloak.representations.PasswordToken;
@@ -61,6 +63,7 @@ import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
+import javax.ws.rs.core.Cookie;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
@@ -153,6 +156,15 @@ public class LoginActionsService {
Response response;
boolean check(String code, ClientSessionModel.Action requiredAction) {
+ if (!check(code)) return false;
+ if (!clientCode.isValid(requiredAction)) {
+ event.error(Errors.INVALID_CODE);
+ response = Flows.forwardToSecurityFailurePage(session, realm, uriInfo, "Invalid code, please login again through your application.");
+ }
+ return true;
+ }
+
+ public boolean check(String code) {
if (!checkSsl()) {
event.error(Errors.SSL_REQUIRED);
response = Flows.forwardToSecurityFailurePage(session, realm, uriInfo, "HTTPS required");
@@ -169,15 +181,69 @@ public class LoginActionsService {
response = Flows.forwardToSecurityFailurePage(session, realm, uriInfo, "Unknown code, please login again through your application.");
return false;
}
- if (!clientCode.isValid(requiredAction)) {
- event.error(Errors.INVALID_CODE);
- response = Flows.forwardToSecurityFailurePage(session, realm, uriInfo, "Invalid code, please login again through your application.");
- }
return true;
}
}
/**
+ * protocol independent login page entry point
+ *
+ *
+ * @param code
+ * @return
+ */
+ @Path("login")
+ @GET
+ public Response loginPage(@QueryParam("code") String code) {
+ event.event(EventType.LOGIN);
+ Checks checks = new Checks();
+ if (!checks.check(code)) {
+ return checks.response;
+ }
+ event.detail(Details.CODE_ID, code);
+ ClientSessionCode clientSessionCode = checks.clientCode;
+ ClientSessionModel clientSession = clientSessionCode.getClientSession();
+
+
+
+ LoginFormsProvider forms = Flows.forms(session, realm, clientSession.getClient(), uriInfo)
+ .setClientSessionCode(clientSessionCode.getCode());
+
+ return forms.createLogin();
+ }
+
+ /**
+ * protocol independent registration page entry point
+ *
+ * @param code
+ * @return
+ */
+ @Path("registration")
+ @GET
+ public Response registerPage(@QueryParam("code") String code) {
+ event.event(EventType.REGISTER);
+ if (!realm.isRegistrationAllowed()) {
+ event.error(Errors.REGISTRATION_DISABLED);
+ return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, "Registration not allowed");
+ }
+
+ Checks checks = new Checks();
+ if (!checks.check(code)) {
+ return checks.response;
+ }
+ event.detail(Details.CODE_ID, code);
+ ClientSessionCode clientSessionCode = checks.clientCode;
+ ClientSessionModel clientSession = clientSessionCode.getClientSession();
+
+
+ authManager.expireIdentityCookie(realm, uriInfo, clientConnection);
+
+ return Flows.forms(session, realm, clientSession.getClient(), uriInfo)
+ .setClientSessionCode(clientSessionCode.getCode())
+ .createRegistration();
+ }
+
+ /**
* URL called after login page. YOU SHOULD NEVER INVOKE THIS DIRECTLY!
*
* @param code