add localization support to realm
(cherry picked from commit b00764b) add localization support to realm (cherry picked from commit b00764b) add localization support to realm (cherry picked from commit b00764b) admin gui for localization support (cherry picked from commit c157cc3) added locale support to ClassLoaderTheme and FolderTheme (cherry picked from commit 764960a) rename localizatin to internationalization (cherry picked from commit 74a0658) fallback if no message can be found (cherry picked from commit 2d54e6f) fallback if no message can be found (cherry picked from commit 2d54e6f) add HttpHeaders (cherry picked from commit be921c8) add HttpHeaders (cherry picked from commit be921c8) NPE fix (cherry picked from commit 148158b) improve locale helper (cherry picked from commit 57a805a) write cookie fix npe (cherry picked from commit 33398b3) dropdown to choose language (cherry picked from commit 9e2eb60) added dropdown to choose locale to the account page. fixed the path of the cookie. (cherry picked from commit 871469a) remove debug info (cherry picked from commit c3ea6b1) added dropdown to change locale for user. (cherry picked from commit 1575bea) add i18n for emails (cherry picked from commit b6280e9) i18n for emails (cherry picked from commit 6118c51) set default locale to english (cherry picked from commit 386447b) change locale type form String to Locale (cherry picked from commit 8dcc595) change file encoding (cherry picked from commit 2cce96d) added parameters to setSuccess, setWarning, setError (cherry picked from commit 64ea438) i18n for error messages (cherry picked from commit e75d5ef) i18n for error message in login (cherry picked from commit 8b60c96) add i18n for messages in account pages (cherry picked from commit 9849d94) fix unit test (cherry picked from commit a70a1c7) fix unit test (cherry picked from commit 008744b) locale localization :) (cherry picked from commit f3a2144) locale localization :) (cherry picked from commit 21f6384) messages refactoring (cherry picked from commit 08f1ae7) messages refactoring (cherry picked from commit 3b4b53a) messages refactoring (cherry picked from commit 69146d4) messages refactoring (cherry picked from commit cd3db1d) messages refactoring (cherry picked from commit 715583f) fix unit tests after message refactoring (cherry picked from commit a82c9ff) fix unit tests after message refactoring (cherry picked from commit 5662d83) fix unit tests after message refactoring (cherry picked from commit 1188de6) fix unit tests after message refactoring (cherry picked from commit 90ded07) German translations (cherry picked from commit 9822b99) removed newliines (cherry picked from commit 34ca1d8) removed java 8 dependency (cherry picked from commit 3a23f4f) typo (cherry picked from commit a818122) typo (cherry picked from commit a818122) forgotten properties unit test fixes unit test fixes fixes after rebase add localization support to realm (cherry picked from commit b00764b) add localization support to realm (cherry picked from commit b00764b) add localization support to realm (cherry picked from commit b00764b) admin gui for localization support (cherry picked from commit c157cc3) added locale support to ClassLoaderTheme and FolderTheme (cherry picked from commit 764960a) rename localizatin to internationalization (cherry picked from commit 74a0658) fallback if no message can be found (cherry picked from commit 2d54e6f) fallback if no message can be found (cherry picked from commit 2d54e6f) add HttpHeaders (cherry picked from commit be921c8) add HttpHeaders (cherry picked from commit be921c8) NPE fix (cherry picked from commit 148158b) improve locale helper (cherry picked from commit 57a805a) write cookie fix npe (cherry picked from commit 33398b3) dropdown to choose language (cherry picked from commit 9e2eb60) added dropdown to choose locale to the account page. fixed the path of the cookie. (cherry picked from commit 871469a) remove debug info (cherry picked from commit c3ea6b1) added dropdown to change locale for user. (cherry picked from commit 1575bea) add i18n for emails (cherry picked from commit b6280e9) i18n for emails (cherry picked from commit 6118c51) set default locale to english (cherry picked from commit 386447b) change locale type form String to Locale (cherry picked from commit 8dcc595) change file encoding (cherry picked from commit 2cce96d) added parameters to setSuccess, setWarning, setError (cherry picked from commit 64ea438) i18n for error messages (cherry picked from commit e75d5ef) i18n for error message in login (cherry picked from commit 8b60c96) add i18n for messages in account pages (cherry picked from commit 9849d94) fix unit test (cherry picked from commit a70a1c7) fix unit test (cherry picked from commit 008744b) locale localization :) (cherry picked from commit f3a2144) locale localization :) (cherry picked from commit 21f6384) messages refactoring (cherry picked from commit 08f1ae7) messages refactoring (cherry picked from commit 3b4b53a) messages refactoring (cherry picked from commit 69146d4) messages refactoring (cherry picked from commit cd3db1d) messages refactoring (cherry picked from commit 715583f) fix unit tests after message refactoring (cherry picked from commit a82c9ff) fix unit tests after message refactoring (cherry picked from commit 5662d83) fix unit tests after message refactoring (cherry picked from commit 1188de6) fix unit tests after message refactoring (cherry picked from commit 90ded07) German translations (cherry picked from commit 9822b99) removed newliines (cherry picked from commit 34ca1d8) removed java 8 dependency (cherry picked from commit 3a23f4f) typo (cherry picked from commit a818122) typo (cherry picked from commit a818122) forgotten properties unit test fixes unit test fixes fixes after rebase fixes after rebase fixes after rebase fixes after rebase
This commit is contained in:
1 parent
7f879fcf62
commit
144ee2c56d
95 files changed
+1680
-601
No files matched your search
@@ -7,6 +7,7 @@ import org.keycloak.models.UserSessionModel;
|
||||
import org.keycloak.provider.Provider;
|
||||
import org.keycloak.services.managers.ClientSessionCode;
|
||||
|
||||
import javax.ws.rs.core.HttpHeaders;
|
||||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.core.UriInfo;
|
||||
|
||||
@@ -21,6 +22,8 @@ public interface LoginProtocol extends Provider {
|
||||
|
||||
LoginProtocol setUriInfo(UriInfo uriInfo);
|
||||
|
||||
LoginProtocol setHttpHeaders(HttpHeaders headers);
|
||||
|
||||
Response cancelLogin(ClientSessionModel clientSession);
|
||||
Response invalidSessionError(ClientSessionModel clientSession);
|
||||
Response authenticated(UserSessionModel userSession, ClientSessionCode accessCode);
|
||||
|
||||
@@ -33,6 +33,7 @@ import org.keycloak.protocol.LoginProtocol;
|
||||
import org.keycloak.services.managers.ClientSessionCode;
|
||||
import org.keycloak.services.managers.ResourceAdminManager;
|
||||
|
||||
import javax.ws.rs.core.HttpHeaders;
|
||||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.core.UriBuilder;
|
||||
import javax.ws.rs.core.UriInfo;
|
||||
@@ -63,13 +64,17 @@ public class OIDCLoginProtocol implements LoginProtocol {
|
||||
|
||||
protected UriInfo uriInfo;
|
||||
|
||||
public OIDCLoginProtocol(KeycloakSession session, RealmModel realm, UriInfo uriInfo) {
|
||||
protected HttpHeaders headers;
|
||||
|
||||
public OIDCLoginProtocol(KeycloakSession session, RealmModel realm, UriInfo uriInfo, HttpHeaders headers) {
|
||||
this.session = session;
|
||||
this.realm = realm;
|
||||
this.uriInfo = uriInfo;
|
||||
this.headers = headers;
|
||||
}
|
||||
|
||||
public OIDCLoginProtocol() {
|
||||
public OIDCLoginProtocol(){
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -90,6 +95,12 @@ public class OIDCLoginProtocol implements LoginProtocol {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public OIDCLoginProtocol setHttpHeaders(HttpHeaders headers){
|
||||
this.headers = headers;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Response cancelLogin(ClientSessionModel clientSession) {
|
||||
String redirect = clientSession.getRedirectUri();
|
||||
|
||||
@@ -67,6 +67,9 @@ public class OIDCLoginProtocolService {
|
||||
@Context
|
||||
private KeycloakSession session;
|
||||
|
||||
@Context
|
||||
private HttpHeaders headers;
|
||||
|
||||
public OIDCLoginProtocolService(RealmModel realm, EventBuilder event, AuthenticationManager authManager) {
|
||||
this.realm = realm;
|
||||
this.tokenManager = new TokenManager();
|
||||
@@ -226,7 +229,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);
|
||||
LoginFormsProvider forms = Flows.forms(session, realm, null, uriInfo, headers);
|
||||
if (code != null) {
|
||||
return forms.setClientSessionCode(code).createCode();
|
||||
} else {
|
||||
|
||||
@@ -30,6 +30,7 @@ import org.keycloak.representations.RefreshToken;
|
||||
import org.keycloak.services.managers.AuthenticationManager;
|
||||
import org.keycloak.util.Time;
|
||||
|
||||
import javax.ws.rs.core.HttpHeaders;
|
||||
import javax.ws.rs.core.UriInfo;
|
||||
import java.io.IOException;
|
||||
import java.util.HashSet;
|
||||
@@ -73,7 +74,7 @@ public class TokenManager {
|
||||
}
|
||||
}
|
||||
|
||||
public TokenValidation validateToken(KeycloakSession session, UriInfo uriInfo, ClientConnection connection, RealmModel realm, AccessToken oldToken) throws OAuthErrorException {
|
||||
public TokenValidation validateToken(KeycloakSession session, UriInfo uriInfo, ClientConnection connection, RealmModel realm, AccessToken oldToken, HttpHeaders headers) throws OAuthErrorException {
|
||||
UserModel user = session.users().getUserById(oldToken.getSubject(), realm);
|
||||
if (user == null) {
|
||||
throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Invalid refresh token", "Unknown user");
|
||||
@@ -85,7 +86,7 @@ public class TokenManager {
|
||||
|
||||
UserSessionModel userSession = session.sessions().getUserSession(realm, oldToken.getSessionState());
|
||||
if (!AuthenticationManager.isSessionValid(realm, userSession)) {
|
||||
AuthenticationManager.logout(session, realm, userSession, uriInfo, connection);
|
||||
AuthenticationManager.logout(session, realm, userSession, uriInfo, connection, headers);
|
||||
throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Session not active", "Session not active");
|
||||
}
|
||||
ClientSessionModel clientSession = null;
|
||||
@@ -124,12 +125,12 @@ public class TokenManager {
|
||||
|
||||
}
|
||||
|
||||
public AccessTokenResponse refreshAccessToken(KeycloakSession session, UriInfo uriInfo, ClientConnection connection, RealmModel realm, ClientModel authorizedClient, String encodedRefreshToken, EventBuilder event) throws OAuthErrorException {
|
||||
public AccessTokenResponse refreshAccessToken(KeycloakSession session, UriInfo uriInfo, ClientConnection connection, RealmModel realm, ClientModel authorizedClient, String encodedRefreshToken, EventBuilder event, HttpHeaders headers) throws OAuthErrorException {
|
||||
RefreshToken refreshToken = verifyRefreshToken(realm, encodedRefreshToken);
|
||||
|
||||
event.user(refreshToken.getSubject()).session(refreshToken.getSessionState()).detail(Details.REFRESH_TOKEN_ID, refreshToken.getId());
|
||||
|
||||
TokenValidation validation = validateToken(session, uriInfo, connection, realm, refreshToken);
|
||||
TokenValidation validation = validateToken(session, uriInfo, connection, realm, refreshToken, headers);
|
||||
// validate authorizedClient is same as validated client
|
||||
if (!validation.clientSession.getClient().getId().equals(authorizedClient.getId())) {
|
||||
throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Invalid refresh token. Token client and authorized client don't match");
|
||||
|
||||
+19
-18
@@ -24,6 +24,7 @@ import org.keycloak.services.ErrorPageException;
|
||||
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;
|
||||
|
||||
@@ -116,7 +117,7 @@ public class AuthorizationEndpoint {
|
||||
action = Action.REGISTER;
|
||||
|
||||
if (!realm.isRegistrationAllowed()) {
|
||||
throw new ErrorPageException(session, realm, uriInfo, "Registration not allowed");
|
||||
throw new ErrorPageException(session, realm, uriInfo, headers, Messages.REGISTRATION_NOT_ALLOWED);
|
||||
}
|
||||
|
||||
return this;
|
||||
@@ -148,21 +149,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, "HTTPS required");
|
||||
throw new ErrorPageException(session, realm, uriInfo, headers, Messages.HTTPS_REQUIRED);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkRealm() {
|
||||
if (!realm.isEnabled()) {
|
||||
event.error(Errors.REALM_DISABLED);
|
||||
throw new ErrorPageException(session, realm, uriInfo, "Realm not enabled");
|
||||
throw new ErrorPageException(session, realm, uriInfo, headers, Messages.REALM_NOT_ENABLED);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkClient() {
|
||||
if (clientId == null) {
|
||||
event.error(Errors.INVALID_REQUEST);
|
||||
throw new ErrorPageException(session, realm, uriInfo, "Missing paramater: " + OIDCLoginProtocol.CLIENT_ID_PARAM);
|
||||
throw new ErrorPageException(session, realm, uriInfo, headers, Messages.MISSING_PARAMETER, OIDCLoginProtocol.CLIENT_ID_PARAM );
|
||||
}
|
||||
|
||||
event.client(clientId);
|
||||
@@ -170,17 +171,17 @@ public class AuthorizationEndpoint {
|
||||
client = realm.findClient(clientId);
|
||||
if (client == null) {
|
||||
event.error(Errors.CLIENT_NOT_FOUND);
|
||||
throw new ErrorPageException(session, realm, uriInfo, "Client not found");
|
||||
throw new ErrorPageException(session, realm, uriInfo, headers, Messages.CLIENT_NOT_FOUND );
|
||||
}
|
||||
|
||||
if ((client instanceof ApplicationModel) && ((ApplicationModel) client).isBearerOnly()) {
|
||||
event.error(Errors.NOT_ALLOWED);
|
||||
throw new ErrorPageException(session, realm, uriInfo, "Bearer only clients are not allowed to initiate browser login");
|
||||
throw new ErrorPageException(session, realm, uriInfo, headers, Messages.BEARER_ONLY );
|
||||
}
|
||||
|
||||
if (client.isDirectGrantsOnly()) {
|
||||
event.error(Errors.NOT_ALLOWED);
|
||||
throw new ErrorPageException(session, realm, uriInfo, "Direct grants only clients are not allowed to initiate browser login");
|
||||
throw new ErrorPageException(session, realm, uriInfo, headers, Messages.DIRECT_GRANTS_ONLY);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -190,7 +191,7 @@ public class AuthorizationEndpoint {
|
||||
responseType = legacyResponseType;
|
||||
} else {
|
||||
event.error(Errors.INVALID_REQUEST);
|
||||
throw new ErrorPageException(session, realm, uriInfo, "Missing query parameter: " + OIDCLoginProtocol.RESPONSE_TYPE_PARAM);
|
||||
throw new ErrorPageException(session, realm, uriInfo, headers, 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, "Invalid " + OIDCLoginProtocol.RESPONSE_TYPE_PARAM);
|
||||
throw new ErrorPageException(session, realm, uriInfo, headers, 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, "Invalid " + OIDCLoginProtocol.REDIRECT_URI_PARAM);
|
||||
throw new ErrorPageException(session, realm, uriInfo, headers, Messages.INVALID_PARAMETER, OIDCLoginProtocol.REDIRECT_URI_PARAM);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -237,8 +238,8 @@ public class AuthorizationEndpoint {
|
||||
IdentityProviderModel identityProviderModel = realm.getIdentityProviderById(idpHint);
|
||||
|
||||
if (identityProviderModel == null) {
|
||||
return Flows.forms(session, realm, null, uriInfo)
|
||||
.setError("Could not find an identity provider with the identifier [" + idpHint + "].")
|
||||
return Flows.forms(session, realm, null, uriInfo, headers)
|
||||
.setError(Messages.IDENTITY_PROVIDER_NOT_FOUND, idpHint)
|
||||
.createErrorPage();
|
||||
}
|
||||
return buildRedirectToIdentityProvider(idpHint, accessCode);
|
||||
@@ -249,11 +250,11 @@ public class AuthorizationEndpoint {
|
||||
|
||||
// SPNEGO/Kerberos authentication TODO: This should be somehow pluggable instead of hardcoded this way (Authentication interceptors?)
|
||||
HttpAuthenticationManager httpAuthManager = new HttpAuthenticationManager(session, clientSession, realm, uriInfo, request, clientConnection, event);
|
||||
HttpAuthenticationManager.HttpAuthOutput httpAuthOutput = httpAuthManager.spnegoAuthenticate();
|
||||
HttpAuthenticationManager.HttpAuthOutput httpAuthOutput = httpAuthManager.spnegoAuthenticate(headers);
|
||||
if (httpAuthOutput.getResponse() != null) return httpAuthOutput.getResponse();
|
||||
|
||||
if (prompt != null && prompt.equals("none")) {
|
||||
OIDCLoginProtocol oauth = new OIDCLoginProtocol(session, realm, uriInfo);
|
||||
OIDCLoginProtocol oauth = new OIDCLoginProtocol(session, realm, uriInfo, headers);
|
||||
return oauth.cancelLogin(clientSession);
|
||||
}
|
||||
|
||||
@@ -271,13 +272,13 @@ public class AuthorizationEndpoint {
|
||||
return buildRedirectToIdentityProvider(identityProviders.get(0).getId(), accessCode);
|
||||
}
|
||||
|
||||
return Flows.forms(session, realm, null, uriInfo).setError("Realm [" + realm.getName() + "] supports multiple identity providers. Could not determine which identity provider should be used to authenticate with.").createErrorPage();
|
||||
return Flows.forms(session, realm, null, uriInfo, headers).setError(Messages.IDENTITY_PROVIDER_NOT_UNIQUE, realm.getName()).createErrorPage();
|
||||
}
|
||||
|
||||
return Flows.forms(session, realm, null, uriInfo).setError("Realm [" + realm.getName() + "] does not support any credential type.").createErrorPage();
|
||||
return Flows.forms(session, realm, null, uriInfo, headers).setError(Messages.REALM_SUPPORTS_NO_CREDENTIALS, realm.getName()).createErrorPage();
|
||||
}
|
||||
|
||||
LoginFormsProvider forms = Flows.forms(session, realm, clientSession.getClient(), uriInfo)
|
||||
LoginFormsProvider forms = Flows.forms(session, realm, clientSession.getClient(), uriInfo, headers)
|
||||
.setClientSessionCode(accessCode);
|
||||
|
||||
// Attach state from SPNEGO authentication
|
||||
@@ -306,7 +307,7 @@ public class AuthorizationEndpoint {
|
||||
private Response buildRegister() {
|
||||
authManager.expireIdentityCookie(realm, uriInfo, clientConnection);
|
||||
|
||||
return Flows.forms(session, realm, client, uriInfo)
|
||||
return Flows.forms(session, realm, client, uriInfo, headers)
|
||||
.setClientSessionCode(new ClientSessionCode(realm, clientSession).getCode())
|
||||
.createRegistration();
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import org.keycloak.protocol.oidc.utils.RedirectUtils;
|
||||
import org.keycloak.representations.RefreshToken;
|
||||
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;
|
||||
|
||||
@@ -91,7 +92,7 @@ public class LogoutEndpoint {
|
||||
if (redirectUri != null) {
|
||||
String validatedRedirect = RedirectUtils.verifyRealmRedirectUri(uriInfo, redirectUri, realm);
|
||||
if (validatedRedirect == null) {
|
||||
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, "Invalid redirect uri.");
|
||||
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.INVALID_REDIRECT_URI);
|
||||
}
|
||||
return Response.status(302).location(UriBuilder.fromUri(validatedRedirect).build()).build();
|
||||
} else {
|
||||
@@ -143,7 +144,7 @@ public class LogoutEndpoint {
|
||||
}
|
||||
|
||||
private void logout(UserSessionModel userSession) {
|
||||
authManager.logout(session, realm, userSession, uriInfo, clientConnection);
|
||||
authManager.logout(session, realm, userSession, uriInfo, clientConnection, headers);
|
||||
event.user(userSession.getUser()).session(userSession).success();
|
||||
}
|
||||
|
||||
|
||||
@@ -276,7 +276,7 @@ public class TokenEndpoint {
|
||||
|
||||
AccessTokenResponse res;
|
||||
try {
|
||||
res = tokenManager.refreshAccessToken(session, uriInfo, clientConnection, realm, client, refreshToken, event);
|
||||
res = tokenManager.refreshAccessToken(session, uriInfo, clientConnection, realm, client, refreshToken, event, headers);
|
||||
} catch (OAuthErrorException e) {
|
||||
event.error(Errors.INVALID_TOKEN);
|
||||
throw new ErrorResponseException(e.getError(), e.getDescription(), Response.Status.BAD_REQUEST);
|
||||
|
||||
+5
-5
@@ -20,10 +20,7 @@ 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.Context;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.core.UriInfo;
|
||||
import javax.ws.rs.core.*;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -43,6 +40,9 @@ public class ValidateTokenEndpoint {
|
||||
@Context
|
||||
private UriInfo uriInfo;
|
||||
|
||||
@Context
|
||||
private HttpHeaders headers;
|
||||
|
||||
private TokenManager tokenManager;
|
||||
private RealmModel realm;
|
||||
private EventBuilder event;
|
||||
@@ -81,7 +81,7 @@ public class ValidateTokenEndpoint {
|
||||
event.user(token.getSubject()).session(token.getSessionState()).detail(Details.VALIDATE_ACCESS_TOKEN, token.getId());
|
||||
|
||||
try {
|
||||
tokenManager.validateToken(session, uriInfo, clientConnection, realm, token);
|
||||
tokenManager.validateToken(session, uriInfo, clientConnection, realm, token, headers);
|
||||
} catch (OAuthErrorException e) {
|
||||
Map<String, String> error = new HashMap<String, String>();
|
||||
error.put(OAuth2Constants.ERROR, e.getError());
|
||||
|
||||
@@ -5,6 +5,7 @@ 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;
|
||||
|
||||
@@ -16,18 +17,22 @@ 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, String errorMessage) {
|
||||
public ErrorPageException(KeycloakSession session, RealmModel realm, UriInfo uriInfo, HttpHeaders headers, 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, errorMessage);
|
||||
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, httpHeaders, errorMessage, parameters);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -42,7 +42,7 @@ public class AppAuthManager extends AuthenticationManager {
|
||||
public AuthResult authenticateBearerToken(KeycloakSession session, RealmModel realm, UriInfo uriInfo, ClientConnection connection, HttpHeaders headers) {
|
||||
String tokenString = extractAuthorizationHeaderToken(headers);
|
||||
if (tokenString == null) return null;
|
||||
AuthResult authResult = verifyIdentityToken(session, realm, uriInfo, connection, true, tokenString);
|
||||
AuthResult authResult = verifyIdentityToken(session, realm, uriInfo, connection, true, tokenString, headers);
|
||||
return authResult;
|
||||
}
|
||||
|
||||
|
||||
@@ -79,7 +79,7 @@ public class AuthenticationManager {
|
||||
return userSession != null && userSession.getLastSessionRefresh() + realm.getSsoSessionIdleTimeout() > currentTime && max > currentTime;
|
||||
}
|
||||
|
||||
public static void logout(KeycloakSession session, RealmModel realm, UserSessionModel userSession, UriInfo uriInfo, ClientConnection connection) {
|
||||
public static void logout(KeycloakSession session, RealmModel realm, UserSessionModel userSession, UriInfo uriInfo, ClientConnection connection, HttpHeaders headers) {
|
||||
if (userSession == null) return;
|
||||
UserModel user = userSession.getUser();
|
||||
userSession.setState(UserSessionModel.State.LOGGING_OUT);
|
||||
@@ -95,6 +95,7 @@ public class AuthenticationManager {
|
||||
if (authMethod == null) continue; // must be a keycloak service like account
|
||||
LoginProtocol protocol = session.getProvider(LoginProtocol.class, authMethod);
|
||||
protocol.setRealm(realm)
|
||||
.setHttpHeaders(headers)
|
||||
.setUriInfo(uriInfo);
|
||||
protocol.backchannelLogout(userSession, clientSession);
|
||||
clientSession.setAction(ClientSessionModel.Action.LOGGED_OUT);
|
||||
@@ -105,7 +106,7 @@ public class AuthenticationManager {
|
||||
}
|
||||
|
||||
|
||||
public static Response browserLogout(KeycloakSession session, RealmModel realm, UserSessionModel userSession, UriInfo uriInfo, ClientConnection connection) {
|
||||
public static Response browserLogout(KeycloakSession session, RealmModel realm, UserSessionModel userSession, UriInfo uriInfo, ClientConnection connection, HttpHeaders headers) {
|
||||
if (userSession == null) return null;
|
||||
UserModel user = userSession.getUser();
|
||||
|
||||
@@ -128,6 +129,7 @@ public class AuthenticationManager {
|
||||
if (authMethod == null) continue; // must be a keycloak service like account
|
||||
LoginProtocol protocol = session.getProvider(LoginProtocol.class, authMethod);
|
||||
protocol.setRealm(realm)
|
||||
.setHttpHeaders(headers)
|
||||
.setUriInfo(uriInfo);
|
||||
try {
|
||||
logger.debugv("backchannel logout to: {0}", client.getClientId());
|
||||
@@ -140,12 +142,13 @@ public class AuthenticationManager {
|
||||
}
|
||||
|
||||
if (redirectClients.size() == 0) {
|
||||
return finishBrowserLogout(session, realm, userSession, uriInfo, connection);
|
||||
return finishBrowserLogout(session, realm, userSession, uriInfo, connection, headers);
|
||||
}
|
||||
for (ClientSessionModel nextRedirectClient : redirectClients) {
|
||||
String authMethod = nextRedirectClient.getAuthMethod();
|
||||
LoginProtocol protocol = session.getProvider(LoginProtocol.class, authMethod);
|
||||
protocol.setRealm(realm)
|
||||
.setHttpHeaders(headers)
|
||||
.setUriInfo(uriInfo);
|
||||
// setting this to logged out cuz I"m not sure protocols can always verify that the client was logged out or not
|
||||
nextRedirectClient.setAction(ClientSessionModel.Action.LOGGED_OUT);
|
||||
@@ -161,16 +164,17 @@ public class AuthenticationManager {
|
||||
}
|
||||
|
||||
}
|
||||
return finishBrowserLogout(session, realm, userSession, uriInfo, connection);
|
||||
return finishBrowserLogout(session, realm, userSession, uriInfo, connection, headers);
|
||||
}
|
||||
|
||||
protected static Response finishBrowserLogout(KeycloakSession session, RealmModel realm, UserSessionModel userSession, UriInfo uriInfo, ClientConnection connection) {
|
||||
protected static Response finishBrowserLogout(KeycloakSession session, RealmModel realm, UserSessionModel userSession, UriInfo uriInfo, ClientConnection connection, HttpHeaders headers) {
|
||||
expireIdentityCookie(realm, uriInfo, connection);
|
||||
expireRememberMeCookie(realm, uriInfo, connection);
|
||||
userSession.setState(UserSessionModel.State.LOGGED_OUT);
|
||||
String method = userSession.getNote(KEYCLOAK_LOGOUT_PROTOCOL);
|
||||
LoginProtocol protocol = session.getProvider(LoginProtocol.class, method);
|
||||
protocol.setRealm(realm)
|
||||
.setHttpHeaders(headers)
|
||||
.setUriInfo(uriInfo);
|
||||
Response response = protocol.finishLogout(userSession);
|
||||
session.sessions().removeUserSession(realm, userSession);
|
||||
@@ -285,7 +289,7 @@ public class AuthenticationManager {
|
||||
}
|
||||
|
||||
String tokenString = cookie.getValue();
|
||||
AuthResult authResult = verifyIdentityToken(session, realm, uriInfo, connection, checkActive, tokenString);
|
||||
AuthResult authResult = verifyIdentityToken(session, realm, uriInfo, connection, checkActive, tokenString, headers);
|
||||
if (authResult == null) {
|
||||
expireIdentityCookie(realm, uriInfo, connection);
|
||||
return null;
|
||||
@@ -335,6 +339,7 @@ public class AuthenticationManager {
|
||||
if (userSession.isRememberMe()) createRememberMeCookie(realm, userSession.getUser().getUsername(), uriInfo, clientConnection);
|
||||
LoginProtocol protocol = session.getProvider(LoginProtocol.class, clientSession.getAuthMethod());
|
||||
protocol.setRealm(realm)
|
||||
.setHttpHeaders(request.getHttpHeaders())
|
||||
.setUriInfo(uriInfo);
|
||||
return protocol.authenticated(userSession, new ClientSessionCode(realm, clientSession));
|
||||
|
||||
@@ -364,7 +369,7 @@ public class AuthenticationManager {
|
||||
UserModel.RequiredAction action = user.getRequiredActions().iterator().next();
|
||||
accessCode.setRequiredAction(action);
|
||||
|
||||
LoginFormsProvider loginFormsProvider = Flows.forms(session, realm, client, uriInfo).setClientSessionCode(accessCode.getCode()).setUser(user);
|
||||
LoginFormsProvider loginFormsProvider = Flows.forms(session, realm, client, uriInfo, request.getHttpHeaders()).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();
|
||||
LoginActionsService.createActionCookie(realm, uriInfo, clientConnection, userSession.getId());
|
||||
@@ -387,7 +392,7 @@ public class AuthenticationManager {
|
||||
}
|
||||
}
|
||||
|
||||
return Flows.forms(session, realm, client, uriInfo)
|
||||
return Flows.forms(session, realm, client, uriInfo, request.getHttpHeaders())
|
||||
.setClientSessionCode(accessCode.getCode())
|
||||
.setAccessRequest(realmRoles, resourceRoles)
|
||||
.setClient(client)
|
||||
@@ -415,7 +420,7 @@ public class AuthenticationManager {
|
||||
}
|
||||
}
|
||||
|
||||
protected AuthResult verifyIdentityToken(KeycloakSession session, RealmModel realm, UriInfo uriInfo, ClientConnection connection, boolean checkActive, String tokenString) {
|
||||
protected AuthResult verifyIdentityToken(KeycloakSession session, RealmModel realm, UriInfo uriInfo, ClientConnection connection, boolean checkActive, String tokenString, HttpHeaders headers) {
|
||||
try {
|
||||
AccessToken token = RSATokenVerifier.verifyToken(tokenString, realm.getPublicKey(), realm.getName(), checkActive);
|
||||
if (checkActive) {
|
||||
@@ -435,7 +440,7 @@ public class AuthenticationManager {
|
||||
|
||||
UserSessionModel userSession = session.sessions().getUserSession(realm, token.getSessionState());
|
||||
if (!isSessionValid(realm, userSession)) {
|
||||
if (userSession != null) logout(session, realm, userSession, uriInfo, connection);
|
||||
if (userSession != null) logout(session, realm, userSession, uriInfo, connection, headers);
|
||||
logger.debug("User session not active");
|
||||
return null;
|
||||
}
|
||||
|
||||
+4
-4
@@ -58,7 +58,7 @@ public class HttpAuthenticationManager {
|
||||
}
|
||||
|
||||
|
||||
public HttpAuthOutput spnegoAuthenticate() {
|
||||
public HttpAuthOutput spnegoAuthenticate(HttpHeaders headers) {
|
||||
boolean kerberosSupported = false;
|
||||
for (RequiredCredentialModel c : realm.getRequiredCredentials()) {
|
||||
if (c.getType().equals(CredentialRepresentation.KERBEROS)) {
|
||||
@@ -96,7 +96,7 @@ public class HttpAuthenticationManager {
|
||||
CredentialValidationOutput output = session.users().validCredentials(realm, spnegoCredential);
|
||||
|
||||
if (output.getAuthStatus() == CredentialValidationOutput.Status.AUTHENTICATED) {
|
||||
return sendResponse(output.getAuthenticatedUser(), output.getState(), "spnego");
|
||||
return sendResponse(output.getAuthenticatedUser(), output.getState(), "spnego", headers);
|
||||
} else {
|
||||
String spnegoResponseToken = (String) output.getState().get(KerberosConstants.RESPONSE_TOKEN);
|
||||
return challengeNegotiation(spnegoResponseToken);
|
||||
@@ -106,7 +106,7 @@ public class HttpAuthenticationManager {
|
||||
|
||||
|
||||
// Send response after successful authentication
|
||||
private HttpAuthOutput sendResponse(UserModel user, Map<String, String> authState, String authMethod) {
|
||||
private HttpAuthOutput sendResponse(UserModel user, Map<String, String> authState, String authMethod, HttpHeaders headers) {
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("User " + user.getUsername() + " authenticated with " + authMethod);
|
||||
}
|
||||
@@ -114,7 +114,7 @@ public class HttpAuthenticationManager {
|
||||
Response response;
|
||||
if (!user.isEnabled()) {
|
||||
event.error(Errors.USER_DISABLED);
|
||||
response = Flows.forwardToSecurityFailurePage(session, realm, uriInfo, Messages.ACCOUNT_DISABLED);
|
||||
response = Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.ACCOUNT_DISABLED);
|
||||
} else {
|
||||
UserSessionModel userSession = session.sessions().createUserSession(realm, user, user.getUsername(), clientConnection.getRemoteAddr(), authMethod, false);
|
||||
|
||||
|
||||
@@ -26,67 +26,151 @@ package org.keycloak.services.messages;
|
||||
*/
|
||||
public class Messages {
|
||||
|
||||
public static final String ACCOUNT_DISABLED = "accountDisabled";
|
||||
public static final String ACCOUNT_TEMPORARILY_DISABLED = "accountTemporarilyDisabled";
|
||||
public static final String INVALID_USER = "invalidUserMessage";
|
||||
|
||||
public static final String INVALID_PASSWORD = "invalidPassword";
|
||||
public static final String INVALID_EMAIL = "invalidEmailMessage";
|
||||
|
||||
public static final String INVALID_PASSWORD_EXISTING = "invalidPasswordExisting";
|
||||
public static final String ACCOUNT_DISABLED = "accountDisabledMessage";
|
||||
|
||||
public static final String INVALID_PASSWORD_CONFIRM = "invalidPasswordConfirm";
|
||||
public static final String ACCOUNT_TEMPORARILY_DISABLED = "accountTemporarilyDisabledMessage";
|
||||
|
||||
public static final String INVALID_EMAIL = "invalidEmail";
|
||||
public static final String EXPIRED_CODE = "expiredCodeMessage";
|
||||
|
||||
public static final String INVALID_USER = "invalidUser";
|
||||
public static final String MISSING_FIRST_NAME = "missingFirstNameMessage";
|
||||
|
||||
public static final String EXPIRED_CODE = "expiredCode";
|
||||
public static final String MISSING_LAST_NAME = "missingLastNameMessage";
|
||||
|
||||
public static final String READ_ONLY_USER = "readOnlyUser";
|
||||
public static final String MISSING_EMAIL = "missingEmailMessage";
|
||||
|
||||
public static final String READ_ONLY_PASSWORD = "readOnlyPassword";
|
||||
public static final String MISSING_USERNAME = "missingUsernameMessage";
|
||||
|
||||
public static final String MISSING_EMAIL = "missingEmail";
|
||||
public static final String MISSING_PASSWORD = "missingPasswordMessage";
|
||||
|
||||
public static final String MISSING_FIRST_NAME = "missingFirstName";
|
||||
public static final String MISSING_TOTP = "missingTotpMessage";
|
||||
|
||||
public static final String MISSING_LAST_NAME = "missingLastName";
|
||||
public static final String NOTMATCH_PASSWORD = "notMatchPasswordMessage";
|
||||
|
||||
public static final String MISSING_PASSWORD = "missingPassword";
|
||||
public static final String INVALID_PASSWORD_EXISTING = "invalidPasswordExistingMessage";
|
||||
|
||||
public static final String NOTMATCH_PASSWORD = "notMatchPassword";
|
||||
public static final String INVALID_PASSWORD_CONFIRM = "invalidPasswordConfirmMessage";
|
||||
|
||||
public static final String MISSING_USERNAME = "missingUsername";
|
||||
public static final String INVALID_TOTP = "invalidTotpMessage";
|
||||
|
||||
public static final String MISSING_TOTP = "missingTotp";
|
||||
public static final String USERNAME_EXISTS = "usernameExistsMessage";
|
||||
|
||||
public static final String INVALID_TOTP = "invalidTotp";
|
||||
public static final String EMAIL_EXISTS = "emailExistsMessage";
|
||||
|
||||
public static final String USERNAME_EXISTS = "usernameExists";
|
||||
public static final String FEDERATED_IDENTITY_EMAIL_EXISTS = "federatedIdentityEmailExistsMessage";
|
||||
|
||||
public static final String EMAIL_EXISTS = "emailExists";
|
||||
public static final String FEDERATED_IDENTITY_USERNAME_EXISTS = "federatedIdentityUsernameExistsMessage";
|
||||
|
||||
public static final String ACTION_WARN_TOTP = "actionTotpWarning";
|
||||
public static final String CONFIGURE_TOTP = "configureTotpMessage";
|
||||
|
||||
public static final String ACTION_WARN_PROFILE = "actionProfileWarning";
|
||||
public static final String UPDATE_PROFILE = "updateProfileMessage";
|
||||
|
||||
public static final String ACTION_WARN_PASSWD = "actionPasswordWarning";
|
||||
public static final String UPDATE_PASSWORD = "updatePasswordMessage";
|
||||
|
||||
public static final String ACTION_WARN_EMAIL = "actionEmailWarning";
|
||||
public static final String VERIFY_EMAIL = "verifyEmailMessage";
|
||||
|
||||
public static final String MISSING_IDENTITY_PROVIDER = "missingIdentityProvider";
|
||||
public static final String EMAIL_VERIFIED = "emailVerifiedMessage";
|
||||
|
||||
public static final String INVALID_FEDERATED_IDENTITY_ACTION = "invalidFederatedIdentityAction";
|
||||
public static final String EMAIL_SENT = "emailSentMessage";
|
||||
|
||||
public static final String IDENTITY_PROVIDER_NOT_FOUND = "identityProviderNotFound";
|
||||
public static final String EMAIL_SENT_ERROR = "emailSendErrorMessage";
|
||||
|
||||
public static final String FEDERATED_IDENTITY_NOT_ACTIVE = "federatedIdentityLinkNotActive";
|
||||
public static final String ACCOUNT_UPDATED = "accountUpdatedMessage";
|
||||
|
||||
public static final String FEDERATED_IDENTITY_REMOVING_LAST_PROVIDER = "federatedIdentityRemovingLastProvider";
|
||||
public static final String ACCOUNT_PASSWORD_UPDATED = "accountPasswordUpdatedMessage";
|
||||
|
||||
public static final String IDENTITY_PROVIDER_REDIRECT_ERROR = "identityProviderRedirectError";
|
||||
public static final String NO_ACCESS = "noAccessMessage";
|
||||
|
||||
public static final String IDENTITY_PROVIDER_REMOVED = "identityProviderRemoved";
|
||||
public static final String FAILED_TO_PROCESS_RESPONSE = "failedToProcessResponseMessage";
|
||||
|
||||
public static final String ERROR = "error";
|
||||
public static final String HTTPS_REQUIRED = "httpsRequiredMessage";
|
||||
|
||||
public static final String REALM_NOT_ENABLED = "realmNotEnabledMessage";
|
||||
|
||||
public static final String INVALID_REQUEST = "invalidRequestMessage";
|
||||
|
||||
public static final String INVALID_REQUESTER = "invalidRequesterMessage";
|
||||
|
||||
public static final String UNKNOWN_LOGIN_REQUESTER = "unknownLoginRequesterMessage";
|
||||
|
||||
public static final String LOGIN_REQUESTER_NOT_ENABLED = "loginRequesterNotEnabledMessage";
|
||||
|
||||
public static final String BEARER_ONLY = "bearerOnlyMessage";
|
||||
|
||||
public static final String DIRECT_GRANTS_ONLY = "directGrantsOnlyMessage";
|
||||
|
||||
public static final String INVALID_REDIRECT_URI = "invalidRedirectUriMessage";
|
||||
|
||||
public static final String UNSUPPORTED_NAME_ID_FORMAT = "unsupportedNameIdFormatMessage";
|
||||
|
||||
public static final String REGISTRATION_NOT_ALLOWED = "registrationNotAllowedMessage";
|
||||
|
||||
public static final String PERMISSION_NOT_APPROVED = "permissionNotApprovedMessage";
|
||||
|
||||
public static final String NO_RELAY_STATE_IN_RESPONSE = "noRelayStateInResponseMessage";
|
||||
|
||||
public static final String IDENTITY_PROVIDER_ALREADY_LINKED = "identityProviderAlreadyLinkedMessage";
|
||||
|
||||
public static final String INSUFFICIENT_PERMISSION = "insufficientPermissionMessage";
|
||||
|
||||
public static final String COULD_NOT_PROCEED_WITH_AUTHENTICATION_REQUEST = "couldNotProceedWithAuthenticationRequestMessage";
|
||||
|
||||
public static final String COULD_NOT_OBTAIN_TOKEN = "couldNotObtainTokenMessage";
|
||||
|
||||
public static final String UNEXPECTED_ERROR_RETRIEVING_TOKEN = "unexpectedErrorRetrievingTokenMessage";
|
||||
|
||||
public static final String IDENTITY_PROVIDER_AUTHENTICATION_FAILED = "identityProviderAuthenticationFailedMessage";
|
||||
|
||||
public static final String UNEXPECTED_ERROR_HANDLING_RESPONSE = "unexpectedErrorHandlingResponseMessage";
|
||||
|
||||
public static final String COULD_NOT_SEND_AUTHENTICATION_REQUEST = "couldNotSendAuthenticationRequestMessage";
|
||||
|
||||
public static final String UNEXPECTED_ERROR_HANDLING_REQUEST = "unexpectedErrorHandlingRequestMessage";
|
||||
|
||||
public static final String INVALID_ACCESS_CODE = "invalidAccessCodeMessage";
|
||||
|
||||
public static final String SESSION_NOT_ACTIVE = "sessionNotActiveMessage";
|
||||
|
||||
public static final String UNKNOWN_CODE = "unknownCodeMessage";
|
||||
|
||||
public static final String INVALID_CODE = "invalidCodeMessage";
|
||||
|
||||
public static final String IDENTITY_PROVIDER_UNEXPECTED_ERROR = "identityProviderUnexpectedErrorMessage";
|
||||
|
||||
public static final String IDENTITY_PROVIDER_NOT_FOUND = "identityProviderNotFoundMessage";
|
||||
|
||||
public static final String IDENTITY_PROVIDER_NOT_UNIQUE = "identityProviderNotUniqueMessage";
|
||||
|
||||
public static final String REALM_SUPPORTS_NO_CREDENTIALS = "realmSupportsNoCredentialsMessage";
|
||||
|
||||
public static final String READ_ONLY_USER = "readOnlyUserMessage";
|
||||
|
||||
public static final String READ_ONLY_PASSWORD = "readOnlyPasswordMessage";
|
||||
|
||||
public static final String SUCCESS_TOTP_REMOVED = "successTotpRemovedMessage";
|
||||
|
||||
public static final String SUCCESS_TOTP = "successTotpMessage";
|
||||
|
||||
public static final String MISSING_IDENTITY_PROVIDER = "missingIdentityProviderMessage";
|
||||
|
||||
public static final String INVALID_FEDERATED_IDENTITY_ACTION = "invalidFederatedIdentityActionMessage";
|
||||
|
||||
public static final String FEDERATED_IDENTITY_NOT_ACTIVE = "federatedIdentityLinkNotActiveMessage";
|
||||
|
||||
public static final String FEDERATED_IDENTITY_REMOVING_LAST_PROVIDER = "federatedIdentityRemovingLastProviderMessage";
|
||||
|
||||
public static final String IDENTITY_PROVIDER_REDIRECT_ERROR = "identityProviderRedirectErrorMessage";
|
||||
|
||||
public static final String IDENTITY_PROVIDER_REMOVED = "identityProviderRemovedMessage";
|
||||
|
||||
public static final String MISSING_PARAMETER = "missingParameterMessage";
|
||||
|
||||
public static final String CLIENT_NOT_FOUND = "clientNotFoundMessage";
|
||||
|
||||
public static final String INVALID_PARAMETER = "invalidParameterMessage";
|
||||
|
||||
public static final String FEDERATED_IDENTITY_REGISTRATION_EMAIL_MISSING = "federatedIdentityRegistrationEmailMissingMessage";
|
||||
}
|
||||
@@ -32,20 +32,7 @@ import org.keycloak.events.Event;
|
||||
import org.keycloak.events.EventBuilder;
|
||||
import org.keycloak.events.EventStoreProvider;
|
||||
import org.keycloak.events.EventType;
|
||||
import org.keycloak.models.AccountRoles;
|
||||
import org.keycloak.models.ApplicationModel;
|
||||
import org.keycloak.models.ClientModel;
|
||||
import org.keycloak.models.ClientSessionModel;
|
||||
import org.keycloak.models.Constants;
|
||||
import org.keycloak.models.FederatedIdentityModel;
|
||||
import org.keycloak.models.IdentityProviderModel;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.ModelReadOnlyException;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.UserCredentialModel;
|
||||
import org.keycloak.models.UserCredentialValueModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.models.UserSessionModel;
|
||||
import org.keycloak.models.*;
|
||||
import org.keycloak.models.utils.ModelToRepresentation;
|
||||
import org.keycloak.models.utils.TimeBasedOTP;
|
||||
import org.keycloak.protocol.oidc.OIDCLoginProtocol;
|
||||
@@ -160,7 +147,7 @@ public class AccountService {
|
||||
public void init() {
|
||||
eventStore = session.getProvider(EventStoreProvider.class);
|
||||
|
||||
account = session.getProvider(AccountProvider.class).setRealm(realm).setUriInfo(uriInfo);
|
||||
account = session.getProvider(AccountProvider.class).setRealm(realm).setUriInfo(uriInfo).setHttpHeaders(headers);
|
||||
|
||||
AuthenticationManager.AuthResult authResult = authManager.authenticateBearerToken(session, realm, uriInfo, clientConnection, headers);
|
||||
if (authResult != null) {
|
||||
@@ -242,7 +229,7 @@ public class AccountService {
|
||||
try {
|
||||
require(AccountRoles.MANAGE_ACCOUNT);
|
||||
} catch (ForbiddenException e) {
|
||||
return Flows.forms(session, realm, null, uriInfo).setError("No access").createErrorPage();
|
||||
return Flows.forms(session, realm, null, uriInfo, headers).setError(Messages.NO_ACCESS).createErrorPage();
|
||||
}
|
||||
|
||||
setReferrerOnPage();
|
||||
@@ -442,7 +429,7 @@ public class AccountService {
|
||||
event.clone().event(EventType.UPDATE_EMAIL).detail(Details.PREVIOUS_EMAIL, oldEmail).detail(Details.UPDATED_EMAIL, email).success();
|
||||
}
|
||||
setReferrerOnPage();
|
||||
return account.setSuccess("accountUpdated").createResponse(AccountPages.ACCOUNT);
|
||||
return account.setSuccess(Messages.ACCOUNT_UPDATED).createResponse(AccountPages.ACCOUNT);
|
||||
} catch (ModelReadOnlyException roe) {
|
||||
setReferrerOnPage();
|
||||
return account.setError(Messages.READ_ONLY_USER).setProfileFormData(formData).createResponse(AccountPages.ACCOUNT);
|
||||
@@ -466,7 +453,7 @@ public class AccountService {
|
||||
event.event(EventType.REMOVE_TOTP).client(auth.getClient()).user(auth.getUser()).success();
|
||||
|
||||
setReferrerOnPage();
|
||||
return account.setSuccess("successTotpRemoved").createResponse(AccountPages.TOTP);
|
||||
return account.setSuccess(Messages.SUCCESS_TOTP_REMOVED).createResponse(AccountPages.TOTP);
|
||||
}
|
||||
|
||||
|
||||
@@ -545,7 +532,7 @@ public class AccountService {
|
||||
event.event(EventType.UPDATE_TOTP).client(auth.getClient()).user(auth.getUser()).success();
|
||||
|
||||
setReferrerOnPage();
|
||||
return account.setSuccess("successTotp").createResponse(AccountPages.TOTP);
|
||||
return account.setSuccess(Messages.SUCCESS_TOTP).createResponse(AccountPages.TOTP);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -614,7 +601,11 @@ public class AccountService {
|
||||
} catch (ModelReadOnlyException mre) {
|
||||
setReferrerOnPage();
|
||||
return account.setError(Messages.READ_ONLY_PASSWORD).createResponse(AccountPages.PASSWORD);
|
||||
} catch (Exception ape) {
|
||||
}catch (ModelException me) {
|
||||
logger.error("Failed to update password", me);
|
||||
setReferrerOnPage();
|
||||
return account.setError(me.getMessage(), me.getParameters()).createResponse(AccountPages.PASSWORD);
|
||||
}catch (Exception ape) {
|
||||
logger.error("Failed to update password", ape);
|
||||
setReferrerOnPage();
|
||||
return account.setError(ape.getMessage()).createResponse(AccountPages.PASSWORD);
|
||||
@@ -631,7 +622,7 @@ public class AccountService {
|
||||
event.event(EventType.UPDATE_PASSWORD).client(auth.getClient()).user(auth.getUser()).success();
|
||||
|
||||
setReferrerOnPage();
|
||||
return account.setPasswordSet(true).setSuccess("accountPasswordUpdated").createResponse(AccountPages.PASSWORD);
|
||||
return account.setPasswordSet(true).setSuccess(Messages.ACCOUNT_PASSWORD_UPDATED).createResponse(AccountPages.PASSWORD);
|
||||
}
|
||||
|
||||
@Path("federated-identity-update")
|
||||
|
||||
@@ -46,6 +46,7 @@ import org.keycloak.services.managers.AuthenticationManager;
|
||||
import org.keycloak.services.managers.AuthenticationManager.AuthResult;
|
||||
import org.keycloak.services.managers.ClientSessionCode;
|
||||
import org.keycloak.services.managers.EventsManager;
|
||||
import org.keycloak.services.messages.Messages;
|
||||
import org.keycloak.services.resources.flows.Flows;
|
||||
import org.keycloak.services.resources.flows.Urls;
|
||||
import org.keycloak.social.SocialIdentityProvider;
|
||||
@@ -57,13 +58,8 @@ import javax.ws.rs.POST;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.QueryParam;
|
||||
import javax.ws.rs.core.Context;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.MultivaluedMap;
|
||||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.core.*;
|
||||
import javax.ws.rs.core.Response.Status;
|
||||
import javax.ws.rs.core.UriBuilder;
|
||||
import javax.ws.rs.core.UriInfo;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
@@ -97,6 +93,10 @@ public class IdentityBrokerService {
|
||||
|
||||
@Context
|
||||
private HttpRequest request;
|
||||
|
||||
@Context
|
||||
private HttpHeaders headers;
|
||||
|
||||
private EventBuilder event;
|
||||
|
||||
public IdentityBrokerService(RealmModel realmModel) {
|
||||
@@ -135,12 +135,12 @@ public class IdentityBrokerService {
|
||||
return response;
|
||||
}
|
||||
} catch (IdentityBrokerException e) {
|
||||
return redirectToErrorPage("Could not send authentication request to identity provider [" + providerId + "].", e);
|
||||
return redirectToErrorPage(Messages.COULD_NOT_SEND_AUTHENTICATION_REQUEST, e, providerId);
|
||||
} catch (Exception e) {
|
||||
return redirectToErrorPage("Unexpected error when handling authentication request to identity provider [" + providerId + "].", e);
|
||||
return redirectToErrorPage(Messages.UNEXPECTED_ERROR_HANDLING_REQUEST, e, providerId);
|
||||
}
|
||||
|
||||
return redirectToErrorPage("Could not proceed with authentication request to identity provider.");
|
||||
return redirectToErrorPage(Messages.COULD_NOT_PROCEED_WITH_AUTHENTICATION_REQUEST);
|
||||
}
|
||||
|
||||
@GET
|
||||
@@ -191,11 +191,10 @@ public class IdentityBrokerService {
|
||||
}
|
||||
|
||||
if (OAuthClientModel.class.isInstance(clientModel) && !forceRetrieval) {
|
||||
return corsResponse(Flows.forms(this.session, this.realmModel, clientModel, this.uriInfo)
|
||||
return corsResponse(Flows.forms(this.session, this.realmModel, clientModel, this.uriInfo, headers)
|
||||
.setClientSessionCode(authManager.extractAuthorizationHeaderToken(this.request.getHttpHeaders()))
|
||||
.setAccessRequest("Your information from " + providerId + " identity provider.")
|
||||
.setClient(clientModel)
|
||||
.setUriInfo(this.uriInfo)
|
||||
.setActionUri(this.uriInfo.getRequestUri())
|
||||
.createOAuthGrant(null), clientModel);
|
||||
}
|
||||
@@ -220,9 +219,9 @@ public class IdentityBrokerService {
|
||||
|
||||
return badRequest("Invalid token.");
|
||||
} catch (IdentityBrokerException e) {
|
||||
return redirectToErrorPage("Could not obtain token fron identity provider [" + providerId + "].", e);
|
||||
return redirectToErrorPage(Messages.COULD_NOT_OBTAIN_TOKEN, e, providerId);
|
||||
} catch (Exception e) {
|
||||
return redirectToErrorPage("Unexpected error when retrieving token from identity provider [" + providerId + "].", e);
|
||||
return redirectToErrorPage(Messages.UNEXPECTED_ERROR_RETRIEVING_TOKEN, e, providerId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -232,7 +231,7 @@ public class IdentityBrokerService {
|
||||
public Response consentTokenRetrieval(@PathParam("provider_id") String providerId,
|
||||
MultivaluedMap<String, String> formData) {
|
||||
if (formData.containsKey("cancel")) {
|
||||
return redirectToErrorPage("Permission not approved.");
|
||||
return redirectToErrorPage(Messages.PERMISSION_NOT_APPROVED);
|
||||
}
|
||||
|
||||
return getToken(providerId, true);
|
||||
@@ -251,7 +250,7 @@ public class IdentityBrokerService {
|
||||
String relayState = identityProvider.getRelayState(createAuthenticationRequest(providerId, null));
|
||||
|
||||
if (relayState == null) {
|
||||
return redirectToErrorPage("No relay state in response from identity identity [" + providerId + ".");
|
||||
return redirectToErrorPage(Messages.NO_RELAY_STATE_IN_RESPONSE, providerId);
|
||||
}
|
||||
|
||||
if (isDebugEnabled()) {
|
||||
@@ -287,10 +286,10 @@ public class IdentityBrokerService {
|
||||
return performLocalAuthentication(identity, clientSessionCode);
|
||||
} catch (IdentityBrokerException e) {
|
||||
rollback();
|
||||
return redirectToErrorPage("Authentication failed. Could not authenticate with identity provider [" + providerId + "].", e);
|
||||
return redirectToErrorPage(Messages.IDENTITY_PROVIDER_AUTHENTICATION_FAILED, e, providerId);
|
||||
} catch (Exception e) {
|
||||
rollback();
|
||||
return redirectToErrorPage("Unexpected error when handling response from identity provider [" + providerId + "].", e);
|
||||
return redirectToErrorPage(Messages.UNEXPECTED_ERROR_HANDLING_RESPONSE, e, providerId);
|
||||
} finally {
|
||||
if (this.session.getTransaction().isActive()) {
|
||||
this.session.getTransaction().commit();
|
||||
@@ -353,7 +352,7 @@ public class IdentityBrokerService {
|
||||
this.event.event(EventType.IDENTITY_PROVIDER_ACCCOUNT_LINKING);
|
||||
|
||||
if (federatedUser != null) {
|
||||
return redirectToErrorPage("The identity returned by the identity provider [" + providerId + "] is already linked to other user.");
|
||||
return redirectToErrorPage(Messages.IDENTITY_PROVIDER_ALREADY_LINKED, providerId);
|
||||
}
|
||||
|
||||
UserModel authenticatedUser = clientSession.getUserSession().getUser();
|
||||
@@ -364,12 +363,12 @@ public class IdentityBrokerService {
|
||||
|
||||
if (!authenticatedUser.isEnabled()) {
|
||||
fireErrorEvent(Errors.USER_DISABLED);
|
||||
return redirectToErrorPage("User is disabled.");
|
||||
return redirectToErrorPage(Messages.ACCOUNT_DISABLED);
|
||||
}
|
||||
|
||||
if (!authenticatedUser.hasRole(this.realmModel.getApplicationByName(ACCOUNT_MANAGEMENT_APP).getRole(MANAGE_ACCOUNT))) {
|
||||
fireErrorEvent(Errors.NOT_ALLOWED);
|
||||
return redirectToErrorPage("Insufficient permissions to link identities.");
|
||||
return redirectToErrorPage(Messages.INSUFFICIENT_PERMISSION);
|
||||
}
|
||||
|
||||
this.session.users().addFederatedIdentity(this.realmModel, authenticatedUser, federatedIdentityModel);
|
||||
@@ -438,28 +437,28 @@ public class IdentityBrokerService {
|
||||
return Urls.identityProviderAuthnResponse(this.uriInfo.getBaseUri(), providerId, this.realmModel.getName()).toString();
|
||||
}
|
||||
|
||||
private Response redirectToErrorPage(String message) {
|
||||
return redirectToErrorPage(message, null);
|
||||
private Response redirectToErrorPage(String message, Object ... parameters) {
|
||||
return redirectToErrorPage(message, null, parameters);
|
||||
}
|
||||
|
||||
private Response redirectToErrorPage(String message, Throwable throwable) {
|
||||
private Response redirectToErrorPage(String message, Throwable throwable, Object ... parameters) {
|
||||
if (message == null) {
|
||||
message = "Unexpected error when authenticating with identity provider";
|
||||
message = Messages.IDENTITY_PROVIDER_UNEXPECTED_ERROR;
|
||||
}
|
||||
|
||||
fireErrorEvent(message, throwable);
|
||||
return Flows.forwardToSecurityFailurePage(this.session, this.realmModel, this.uriInfo, message);
|
||||
return Flows.forwardToSecurityFailurePage(this.session, this.realmModel, this.uriInfo, headers, message, parameters);
|
||||
}
|
||||
|
||||
private Response redirectToLoginPage(Throwable t, ClientSessionCode clientCode) {
|
||||
String message = t.getMessage();
|
||||
|
||||
if (message == null) {
|
||||
message = "Unexpected error when authenticating with identity provider";
|
||||
message = Messages.IDENTITY_PROVIDER_UNEXPECTED_ERROR;
|
||||
}
|
||||
|
||||
fireErrorEvent(message);
|
||||
return Flows.forms(this.session, this.realmModel, clientCode.getClientSession().getClient(), this.uriInfo)
|
||||
return Flows.forms(this.session, this.realmModel, clientCode.getClientSession().getClient(), this.uriInfo, headers)
|
||||
.setClientSessionCode(clientCode.getCode())
|
||||
.setError(message)
|
||||
.createLogin();
|
||||
@@ -535,7 +534,7 @@ public class IdentityBrokerService {
|
||||
|
||||
if (existingUser != null) {
|
||||
fireErrorEvent(Errors.FEDERATED_IDENTITY_EMAIL_EXISTS);
|
||||
throw new IdentityBrokerException("federatedIdentityEmailExists");
|
||||
throw new IdentityBrokerException(Messages.FEDERATED_IDENTITY_EMAIL_EXISTS);
|
||||
}
|
||||
|
||||
String username = updatedIdentity.getUsername();
|
||||
@@ -543,7 +542,7 @@ public class IdentityBrokerService {
|
||||
username = updatedIdentity.getEmail();
|
||||
if (username == null || username.trim().length() == 0) {
|
||||
fireErrorEvent(Errors.FEDERATED_IDENTITY_REGISTRATION_EMAIL_MISSING);
|
||||
throw new IdentityBrokerException("federatedIdentityRegistrationEmailMissing");
|
||||
throw new IdentityBrokerException(Messages.FEDERATED_IDENTITY_REGISTRATION_EMAIL_MISSING);
|
||||
// TODO KEYCLOAK-1053 (ask user to enter email address) should be implemented instead of plain exception as better solution for this case
|
||||
}
|
||||
username = username.trim();
|
||||
@@ -555,7 +554,7 @@ public class IdentityBrokerService {
|
||||
|
||||
if (existingUser != null) {
|
||||
fireErrorEvent(Errors.FEDERATED_IDENTITY_USERNAME_EXISTS);
|
||||
throw new IdentityBrokerException("federatedIdentityUsernameExists");
|
||||
throw new IdentityBrokerException(Messages.FEDERATED_IDENTITY_USERNAME_EXISTS);
|
||||
}
|
||||
|
||||
if (isDebugEnabled()) {
|
||||
|
||||
@@ -32,15 +32,8 @@ import org.keycloak.events.EventBuilder;
|
||||
import org.keycloak.events.EventType;
|
||||
import org.keycloak.jose.jws.JWSBuilder;
|
||||
import org.keycloak.login.LoginFormsProvider;
|
||||
import org.keycloak.models.ClientModel;
|
||||
import org.keycloak.models.ClientSessionModel;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.RequiredCredentialModel;
|
||||
import org.keycloak.models.UserCredentialModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.models.*;
|
||||
import org.keycloak.models.UserModel.RequiredAction;
|
||||
import org.keycloak.models.UserSessionModel;
|
||||
import org.keycloak.models.utils.KeycloakModelUtils;
|
||||
import org.keycloak.models.utils.TimeBasedOTP;
|
||||
import org.keycloak.protocol.LoginProtocol;
|
||||
@@ -160,7 +153,7 @@ public class LoginActionsService {
|
||||
return false;
|
||||
} else if (!clientCode.isValid(requiredAction)) {
|
||||
event.error(Errors.INVALID_CODE);
|
||||
response = Flows.forwardToSecurityFailurePage(session, realm, uriInfo, "Invalid code, please login again through your application.");
|
||||
response = Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.INVALID_CODE);
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
@@ -172,7 +165,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, "Invalid code, please login again through your application.");
|
||||
response = Flows.forwardToSecurityFailurePage(session, realm, uriInfo,headers, Messages.INVALID_CODE);
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
@@ -182,18 +175,18 @@ public class LoginActionsService {
|
||||
public boolean check(String code) {
|
||||
if (!checkSsl()) {
|
||||
event.error(Errors.SSL_REQUIRED);
|
||||
response = Flows.forwardToSecurityFailurePage(session, realm, uriInfo, "HTTPS required");
|
||||
response = Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.HTTPS_REQUIRED);
|
||||
return false;
|
||||
}
|
||||
if (!realm.isEnabled()) {
|
||||
event.error(Errors.REALM_DISABLED);
|
||||
response = Flows.forwardToSecurityFailurePage(session, realm, uriInfo, "Realm not enabled.");
|
||||
response = Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, 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, "Unknown code, please login again through your application.");
|
||||
response = Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.UNKNOWN_CODE);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -224,7 +217,7 @@ public class LoginActionsService {
|
||||
clientSession.setAction(ClientSessionModel.Action.AUTHENTICATE);
|
||||
}
|
||||
|
||||
LoginFormsProvider forms = Flows.forms(session, realm, clientSession.getClient(), uriInfo)
|
||||
LoginFormsProvider forms = Flows.forms(session, realm, clientSession.getClient(), uriInfo, headers)
|
||||
.setClientSessionCode(clientSessionCode.getCode());
|
||||
|
||||
return forms.createLogin();
|
||||
@@ -242,7 +235,7 @@ public class LoginActionsService {
|
||||
event.event(EventType.REGISTER);
|
||||
if (!realm.isRegistrationAllowed()) {
|
||||
event.error(Errors.REGISTRATION_DISABLED);
|
||||
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, "Registration not allowed");
|
||||
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.REGISTRATION_NOT_ALLOWED);
|
||||
}
|
||||
|
||||
Checks checks = new Checks();
|
||||
@@ -256,7 +249,7 @@ public class LoginActionsService {
|
||||
|
||||
authManager.expireIdentityCookie(realm, uriInfo, clientConnection);
|
||||
|
||||
return Flows.forms(session, realm, clientSession.getClient(), uriInfo)
|
||||
return Flows.forms(session, realm, clientSession.getClient(), uriInfo, headers)
|
||||
.setClientSessionCode(clientSessionCode.getCode())
|
||||
.createRegistration();
|
||||
}
|
||||
@@ -276,17 +269,17 @@ public class LoginActionsService {
|
||||
event.event(EventType.LOGIN);
|
||||
if (!checkSsl()) {
|
||||
event.error(Errors.SSL_REQUIRED);
|
||||
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, "HTTPS required");
|
||||
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.HTTPS_REQUIRED);
|
||||
}
|
||||
|
||||
if (!realm.isEnabled()) {
|
||||
event.error(Errors.REALM_DISABLED);
|
||||
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, "Realm not enabled.");
|
||||
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, 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, "Unknown code, please login again through your application.");
|
||||
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.UNKNOWN_CODE);
|
||||
}
|
||||
|
||||
ClientSessionModel clientSession = clientCode.getClientSession();
|
||||
@@ -295,7 +288,7 @@ 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).setError(Messages.EXPIRED_CODE)
|
||||
return Flows.forms(this.session, realm, clientSession.getClient(), uriInfo, headers).setError(Messages.EXPIRED_CODE)
|
||||
.setClientSessionCode(clientCode.getCode())
|
||||
.createLogin();
|
||||
}
|
||||
@@ -319,17 +312,18 @@ public class LoginActionsService {
|
||||
ClientModel client = clientSession.getClient();
|
||||
if (client == null) {
|
||||
event.error(Errors.CLIENT_NOT_FOUND);
|
||||
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, "Unknown login requester.");
|
||||
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.UNKNOWN_LOGIN_REQUESTER);
|
||||
}
|
||||
if (!client.isEnabled()) {
|
||||
event.error(Errors.CLIENT_NOT_FOUND);
|
||||
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, "Login requester not enabled.");
|
||||
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.LOGIN_REQUESTER_NOT_ENABLED);
|
||||
}
|
||||
|
||||
if (formData.containsKey("cancel")) {
|
||||
event.error(Errors.REJECTED_BY_USER);
|
||||
LoginProtocol protocol = session.getProvider(LoginProtocol.class, clientSession.getAuthMethod());
|
||||
protocol.setRealm(realm)
|
||||
.setHttpHeaders(headers)
|
||||
.setUriInfo(uriInfo);
|
||||
return protocol.cancelLogin(clientSession);
|
||||
}
|
||||
@@ -356,14 +350,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)
|
||||
return Flows.forms(this.session, realm, client, uriInfo, headers)
|
||||
.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)
|
||||
return Flows.forms(this.session, realm, client, uriInfo, headers)
|
||||
.setError(Messages.ACCOUNT_DISABLED)
|
||||
.setClientSessionCode(clientCode.getCode())
|
||||
.setFormData(formData).createLogin();
|
||||
@@ -373,19 +367,19 @@ 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)
|
||||
return Flows.forms(this.session, realm, client, uriInfo, headers)
|
||||
.setFormData(formData)
|
||||
.setClientSessionCode(clientCode.getCode())
|
||||
.createLoginTotp();
|
||||
case INVALID_USER:
|
||||
event.error(Errors.USER_NOT_FOUND);
|
||||
return Flows.forms(this.session, realm, client, uriInfo).setError(Messages.INVALID_USER)
|
||||
return Flows.forms(this.session, realm, client, uriInfo, headers).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).setError(Messages.INVALID_USER)
|
||||
return Flows.forms(this.session, realm, client, uriInfo, headers).setError(Messages.INVALID_USER)
|
||||
.setFormData(formData)
|
||||
.setClientSessionCode(clientCode.getCode())
|
||||
.createLogin();
|
||||
@@ -407,25 +401,25 @@ public class LoginActionsService {
|
||||
event.event(EventType.REGISTER);
|
||||
if (!checkSsl()) {
|
||||
event.error(Errors.SSL_REQUIRED);
|
||||
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, "HTTPS required");
|
||||
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.HTTPS_REQUIRED);
|
||||
}
|
||||
|
||||
if (!realm.isEnabled()) {
|
||||
event.error(Errors.REALM_DISABLED);
|
||||
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, "Realm not enabled.");
|
||||
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.REALM_NOT_ENABLED);
|
||||
}
|
||||
if (!realm.isRegistrationAllowed()) {
|
||||
event.error(Errors.REGISTRATION_DISABLED);
|
||||
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, "Registration not allowed");
|
||||
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, 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, "Unknown code, please login again through your application.");
|
||||
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.UNKNOWN_CODE);
|
||||
}
|
||||
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.");
|
||||
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.INVALID_CODE);
|
||||
}
|
||||
|
||||
String username = formData.getFirst("username");
|
||||
@@ -444,17 +438,17 @@ public class LoginActionsService {
|
||||
|
||||
if (!realm.isEnabled()) {
|
||||
event.error(Errors.REALM_DISABLED);
|
||||
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, "Realm not enabled");
|
||||
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.REALM_NOT_ENABLED);
|
||||
}
|
||||
ClientModel client = clientSession.getClient();
|
||||
if (client == null) {
|
||||
event.error(Errors.CLIENT_NOT_FOUND);
|
||||
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, "Unknown login requester.");
|
||||
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.UNKNOWN_LOGIN_REQUESTER);
|
||||
}
|
||||
|
||||
if (!client.isEnabled()) {
|
||||
event.error(Errors.CLIENT_DISABLED);
|
||||
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, "Login requester not enabled.");
|
||||
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.LOGIN_REQUESTER_NOT_ENABLED);
|
||||
}
|
||||
|
||||
|
||||
@@ -464,15 +458,20 @@ public class LoginActionsService {
|
||||
}
|
||||
|
||||
// Validate here, so user is not created if password doesn't validate to passwordPolicy of current realm
|
||||
String error = Validation.validateRegistrationForm(realm, formData, requiredCredentialTypes);
|
||||
if (error == null) {
|
||||
error = Validation.validatePassword(formData, realm.getPasswordPolicy());
|
||||
String errorMessage = Validation.validateRegistrationForm(realm, formData, requiredCredentialTypes);
|
||||
Object[] parameters = new Object[0];
|
||||
if (errorMessage == null) {
|
||||
PasswordPolicy.Error error = Validation.validatePassword(formData, realm.getPasswordPolicy());
|
||||
if(error != null){
|
||||
errorMessage = error.getMessage();
|
||||
parameters = error.getParameters();
|
||||
}
|
||||
}
|
||||
|
||||
if (error != null) {
|
||||
if (errorMessage != null) {
|
||||
event.error(Errors.INVALID_REGISTRATION);
|
||||
return Flows.forms(session, realm, client, uriInfo)
|
||||
.setError(error)
|
||||
return Flows.forms(session, realm, client, uriInfo, headers)
|
||||
.setError(errorMessage, parameters)
|
||||
.setFormData(formData)
|
||||
.setClientSessionCode(clientCode.getCode())
|
||||
.createRegistration();
|
||||
@@ -481,7 +480,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)
|
||||
return Flows.forms(session, realm, client, uriInfo, headers)
|
||||
.setError(Messages.USERNAME_EXISTS)
|
||||
.setFormData(formData)
|
||||
.setClientSessionCode(clientCode.getCode())
|
||||
@@ -491,7 +490,7 @@ public class LoginActionsService {
|
||||
// Validate that user with this email doesn't exist in realm or any federation provider
|
||||
if (session.users().getUserByEmail(email, realm) != null) {
|
||||
event.error(Errors.EMAIL_IN_USE);
|
||||
return Flows.forms(session, realm, client, uriInfo)
|
||||
return Flows.forms(session, realm, client, uriInfo, headers)
|
||||
.setError(Messages.EMAIL_EXISTS)
|
||||
.setFormData(formData)
|
||||
.setClientSessionCode(clientCode.getCode())
|
||||
@@ -512,9 +511,14 @@ public class LoginActionsService {
|
||||
|
||||
boolean passwordUpdateSuccessful;
|
||||
String passwordUpdateError = null;
|
||||
Object[] passwordUpdateErrorParameters = null;
|
||||
try {
|
||||
session.users().updateCredential(realm, user, UserCredentialModel.password(formData.getFirst("password")));
|
||||
passwordUpdateSuccessful = true;
|
||||
} catch (ModelException me) {
|
||||
passwordUpdateSuccessful = false;
|
||||
passwordUpdateError = me.getMessage();
|
||||
passwordUpdateErrorParameters = me.getParameters();
|
||||
} catch (Exception ape) {
|
||||
passwordUpdateSuccessful = false;
|
||||
passwordUpdateError = ape.getMessage();
|
||||
@@ -523,8 +527,8 @@ 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)
|
||||
.setError(passwordUpdateError)
|
||||
return Flows.forms(session, realm, client, uriInfo, headers)
|
||||
.setError(passwordUpdateError, passwordUpdateErrorParameters)
|
||||
.setClientSessionCode(clientCode.getCode())
|
||||
.createResponse(UserModel.RequiredAction.UPDATE_PASSWORD);
|
||||
}
|
||||
@@ -552,7 +556,7 @@ public class LoginActionsService {
|
||||
|
||||
|
||||
if (!checkSsl()) {
|
||||
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, "HTTPS required");
|
||||
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.HTTPS_REQUIRED);
|
||||
}
|
||||
|
||||
String code = formData.getFirst("code");
|
||||
@@ -560,7 +564,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, "Invalid access code.");
|
||||
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.INVALID_ACCESS_CODE);
|
||||
}
|
||||
ClientSessionModel clientSession = accessCode.getClientSession();
|
||||
event.detail(Details.CODE_ID, clientSession.getId());
|
||||
@@ -582,14 +586,15 @@ public class LoginActionsService {
|
||||
}
|
||||
|
||||
if (!AuthenticationManager.isSessionValid(realm, userSession)) {
|
||||
AuthenticationManager.logout(session, realm, userSession, uriInfo, clientConnection);
|
||||
AuthenticationManager.logout(session, realm, userSession, uriInfo, clientConnection, headers);
|
||||
event.error(Errors.INVALID_CODE);
|
||||
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, "Session not active");
|
||||
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.SESSION_NOT_ACTIVE);
|
||||
}
|
||||
event.session(userSession);
|
||||
|
||||
LoginProtocol protocol = session.getProvider(LoginProtocol.class, clientSession.getAuthMethod());
|
||||
protocol.setRealm(realm)
|
||||
.setHttpHeaders(headers)
|
||||
.setUriInfo(uriInfo);
|
||||
if (formData.containsKey("cancel")) {
|
||||
event.error(Errors.REJECTED_BY_USER);
|
||||
@@ -623,7 +628,7 @@ public class LoginActionsService {
|
||||
|
||||
String error = Validation.validateUpdateProfileForm(formData);
|
||||
if (error != null) {
|
||||
return Flows.forms(session, realm, null, uriInfo).setUser(user).setError(error)
|
||||
return Flows.forms(session, realm, null, uriInfo, headers).setUser(user).setError(error)
|
||||
.setClientSessionCode(accessCode.getCode())
|
||||
.createResponse(RequiredAction.UPDATE_PROFILE);
|
||||
}
|
||||
@@ -641,7 +646,7 @@ public class LoginActionsService {
|
||||
|
||||
// check for duplicated email
|
||||
if (userByEmail != null && !userByEmail.getId().equals(user.getId())) {
|
||||
return Flows.forms(session, realm, null, uriInfo).setUser(user).setError(Messages.EMAIL_EXISTS)
|
||||
return Flows.forms(session, realm, null, uriInfo, headers).setUser(user).setError(Messages.EMAIL_EXISTS)
|
||||
.setClientSessionCode(accessCode.getCode())
|
||||
.createResponse(RequiredAction.UPDATE_PROFILE);
|
||||
}
|
||||
@@ -680,7 +685,7 @@ public class LoginActionsService {
|
||||
String totp = formData.getFirst("totp");
|
||||
String totpSecret = formData.getFirst("totpSecret");
|
||||
|
||||
LoginFormsProvider loginForms = Flows.forms(session, realm, null, uriInfo).setUser(user);
|
||||
LoginFormsProvider loginForms = Flows.forms(session, realm, null, uriInfo, headers).setUser(user);
|
||||
if (Validation.isEmpty(totp)) {
|
||||
return loginForms.setError(Messages.MISSING_TOTP)
|
||||
.setClientSessionCode(accessCode.getCode())
|
||||
@@ -725,7 +730,7 @@ public class LoginActionsService {
|
||||
String passwordNew = formData.getFirst("password-new");
|
||||
String passwordConfirm = formData.getFirst("password-confirm");
|
||||
|
||||
LoginFormsProvider loginForms = Flows.forms(session, realm, null, uriInfo).setUser(user);
|
||||
LoginFormsProvider loginForms = Flows.forms(session, realm, null, uriInfo, headers).setUser(user);
|
||||
if (Validation.isEmpty(passwordNew)) {
|
||||
return loginForms.setError(Messages.MISSING_PASSWORD)
|
||||
.setClientSessionCode(accessCode.getCode())
|
||||
@@ -738,6 +743,10 @@ public class LoginActionsService {
|
||||
|
||||
try {
|
||||
session.users().updateCredential(realm, user, UserCredentialModel.password(passwordNew));
|
||||
} catch (ModelException me) {
|
||||
return loginForms.setError(me.getMessage(), me.getParameters())
|
||||
.setClientSessionCode(accessCode.getCode())
|
||||
.createResponse(RequiredAction.UPDATE_PASSWORD);
|
||||
} catch (Exception ape) {
|
||||
return loginForms.setError(ape.getMessage())
|
||||
.setClientSessionCode(accessCode.getCode())
|
||||
@@ -751,7 +760,7 @@ 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).setSuccess("passwordUpdated").createInfoPage();
|
||||
return Flows.forms(session, realm, clientSession.getClient(), uriInfo, headers).setSuccess(Messages.ACCOUNT_PASSWORD_UPDATED).createInfoPage();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -783,7 +792,7 @@ public class LoginActionsService {
|
||||
|
||||
String actionCookieValue = getActionCookie();
|
||||
if (actionCookieValue == null || !actionCookieValue.equals(userSession.getId())) {
|
||||
return Flows.forms(session, realm, clientSession.getClient(), uriInfo).setSuccess("emailVerified").createInfoPage();
|
||||
return Flows.forms(session, realm, clientSession.getClient(), uriInfo, headers).setSuccess(Messages.EMAIL_VERIFIED).createInfoPage();
|
||||
}
|
||||
|
||||
event = event.clone().removeDetail(Details.EMAIL).event(EventType.LOGIN);
|
||||
@@ -801,7 +810,7 @@ public class LoginActionsService {
|
||||
|
||||
createActionCookie(realm, uriInfo, clientConnection, userSession.getId());
|
||||
|
||||
return Flows.forms(session, realm, null, uriInfo)
|
||||
return Flows.forms(session, realm, null, uriInfo, headers)
|
||||
.setClientSessionCode(accessCode.getCode())
|
||||
.setUser(userSession.getUser())
|
||||
.createResponse(RequiredAction.VERIFY_EMAIL);
|
||||
@@ -818,11 +827,11 @@ public class LoginActionsService {
|
||||
return checks.response;
|
||||
}
|
||||
ClientSessionCode accessCode = checks.clientCode;
|
||||
return Flows.forms(session, realm, null, uriInfo)
|
||||
return Flows.forms(session, realm, null, uriInfo, headers)
|
||||
.setClientSessionCode(accessCode.getCode())
|
||||
.createResponse(RequiredAction.UPDATE_PASSWORD);
|
||||
} else {
|
||||
return Flows.forms(session, realm, null, uriInfo)
|
||||
return Flows.forms(session, realm, null, uriInfo, headers)
|
||||
.setClientSessionCode(code)
|
||||
.createPasswordReset();
|
||||
}
|
||||
@@ -835,16 +844,16 @@ public class LoginActionsService {
|
||||
final MultivaluedMap<String, String> formData) {
|
||||
event.event(EventType.SEND_RESET_PASSWORD);
|
||||
if (!checkSsl()) {
|
||||
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, "HTTPS required");
|
||||
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.HTTPS_REQUIRED);
|
||||
}
|
||||
if (!realm.isEnabled()) {
|
||||
event.error(Errors.REALM_DISABLED);
|
||||
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, "Realm not enabled.");
|
||||
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, 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, "Unknown code, please login again through your application.");
|
||||
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.UNKNOWN_CODE);
|
||||
}
|
||||
ClientSessionModel clientSession = accessCode.getClientSession();
|
||||
|
||||
@@ -852,12 +861,10 @@ public class LoginActionsService {
|
||||
|
||||
ClientModel client = clientSession.getClient();
|
||||
if (client == null) {
|
||||
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo,
|
||||
"Unknown login requester.");
|
||||
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.UNKNOWN_LOGIN_REQUESTER);
|
||||
}
|
||||
if (!client.isEnabled()) {
|
||||
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo,
|
||||
"Login requester not enabled.");
|
||||
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.LOGIN_REQUESTER_NOT_ENABLED);
|
||||
}
|
||||
|
||||
event.client(client.getClientId())
|
||||
@@ -900,7 +907,7 @@ 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).setError("emailSendError")
|
||||
return Flows.forms(this.session, realm, client, uriInfo, headers).setError(Messages.EMAIL_SENT_ERROR)
|
||||
.setClientSessionCode(accessCode.getCode())
|
||||
.createErrorPage();
|
||||
}
|
||||
@@ -908,7 +915,7 @@ public class LoginActionsService {
|
||||
createActionCookie(realm, uriInfo, clientConnection, userSession.getId());
|
||||
}
|
||||
|
||||
return Flows.forms(session, realm, client, uriInfo).setSuccess("emailSent").setClientSessionCode(accessCode.getCode()).createPasswordReset();
|
||||
return Flows.forms(session, realm, client, uriInfo, headers).setSuccess(Messages.EMAIL_SENT).setClientSessionCode(accessCode.getCode()).createPasswordReset();
|
||||
}
|
||||
|
||||
private String getActionCookie() {
|
||||
|
||||
@@ -26,6 +26,7 @@ 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;
|
||||
|
||||
@@ -37,16 +38,16 @@ public class Flows {
|
||||
private Flows() {
|
||||
}
|
||||
|
||||
public static LoginFormsProvider forms(KeycloakSession session, RealmModel realm, ClientModel client, UriInfo uriInfo) {
|
||||
return session.getProvider(LoginFormsProvider.class).setRealm(realm).setUriInfo(uriInfo).setClient(client);
|
||||
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, String message) {
|
||||
return Flows.forms(session, realm, null, uriInfo).setError(message).createErrorPage();
|
||||
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();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -190,6 +190,10 @@ public class Urls {
|
||||
return requiredActionsBase(baseUri).path(LoginActionsService.class, "processConsent").build(realmId);
|
||||
}
|
||||
|
||||
public static String localeCookiePath(URI baseUri, String realmName){
|
||||
return realmBase(baseUri).path(realmName).build().getRawPath();
|
||||
}
|
||||
|
||||
public static URI themeRoot(URI baseUri) {
|
||||
return themeBase(baseUri).path(Version.RESOURCES_VERSION).build();
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ public class Validation {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static String validatePassword(MultivaluedMap<String, String> formData, PasswordPolicy policy) {
|
||||
public static PasswordPolicy.Error validatePassword(MultivaluedMap<String, String> formData, PasswordPolicy policy) {
|
||||
return policy.validate(formData.getFirst("username"), formData.getFirst("password"));
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user