Compare commits
20
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c3fa471223 | ||
|
|
302d5a9334 | ||
|
|
8b8db265ba | ||
|
|
1bc75509e3 | ||
|
|
b896c2eb57 | ||
|
|
fed39d4953 | ||
|
|
88e77f7b08 | ||
|
|
e201f205d1 | ||
|
|
9f38e246df | ||
|
|
6ea9ed9be8 | ||
|
|
96fe460806 | ||
|
|
d7edee8a06 | ||
|
|
366ba829ab | ||
|
|
79cd646ac7 | ||
|
|
a3a33c2359 | ||
|
|
9f3babb66c | ||
|
|
4dd469933c | ||
|
|
570ea94a33 | ||
|
|
cc36cadebd | ||
|
|
f45ef2ccc8 |
No files matched your search
@@ -15,7 +15,6 @@ env:
|
||||
- TESTS=server-group3
|
||||
- TESTS=server-group4
|
||||
- TESTS=old
|
||||
- TESTS=crossdc
|
||||
|
||||
jdk:
|
||||
- oraclejdk8
|
||||
|
||||
@@ -38,7 +38,7 @@ Starting Keycloak
|
||||
|
||||
To start Keycloak during development first build as specified above, then run:
|
||||
|
||||
mvn -f testsuite/utils/pom.xml exec:java -Pkeycloak-server
|
||||
mvn -f testsuite/integration/pom.xml exec:java -Pkeycloak-server
|
||||
|
||||
|
||||
To start Keycloak from the server distribution first build the distribution it as specified above, then run:
|
||||
@@ -49,10 +49,6 @@ To start Keycloak from the server distribution first build the distribution it a
|
||||
|
||||
To stop the server press `Ctrl + C`.
|
||||
|
||||
Reporting security vulnerabilities
|
||||
----------------------------------
|
||||
|
||||
If you've found a security vulnerability, please look at the [instructions on how to properly report it](http://www.keycloak.org/security.html)
|
||||
|
||||
Help and Documentation
|
||||
----------------------
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>3.4.1.Final</version>
|
||||
<version>3.3.0.Final</version>
|
||||
<relativePath>../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
-10
@@ -277,16 +277,6 @@ public class AdapterDeploymentContext {
|
||||
delegate.setSslRequired(sslRequired);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getConfidentialPort() {
|
||||
return delegate.getConfidentialPort();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setConfidentialPort(int confidentialPort) {
|
||||
delegate.setConfidentialPort(confidentialPort);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TokenStore getTokenStore() {
|
||||
return delegate.getTokenStore();
|
||||
|
||||
+5
-6
@@ -71,10 +71,9 @@ public class BasicAuthRequestAuthenticator extends BearerTokenRequestAuthenticat
|
||||
AccessTokenResponse atr=null;
|
||||
try {
|
||||
String userpw=new String(Base64.decode(tokenString));
|
||||
int seperatorIndex = userpw.indexOf(":");
|
||||
String user = userpw.substring(0, seperatorIndex);
|
||||
String pw = userpw.substring(seperatorIndex + 1);
|
||||
atr = getToken(user, pw);
|
||||
String[] parts=userpw.split(":");
|
||||
|
||||
atr = getToken(parts[0], parts[1]);
|
||||
tokenString = atr.getToken();
|
||||
} catch (Exception e) {
|
||||
log.debug("Failed to obtain token", e);
|
||||
@@ -83,8 +82,8 @@ public class BasicAuthRequestAuthenticator extends BearerTokenRequestAuthenticat
|
||||
}
|
||||
|
||||
return authenticateToken(exchange, atr.getToken());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private AccessTokenResponse getToken(String username, String password) throws Exception {
|
||||
AccessTokenResponse tokenResponse=null;
|
||||
HttpClient client = deployment.getClient();
|
||||
|
||||
-13
@@ -23,8 +23,6 @@ import org.keycloak.adapters.spi.AuthChallenge;
|
||||
import org.keycloak.adapters.spi.AuthOutcome;
|
||||
import org.keycloak.adapters.spi.HttpFacade;
|
||||
import org.keycloak.common.VerificationException;
|
||||
import org.keycloak.jose.jws.JWSInput;
|
||||
import org.keycloak.jose.jws.JWSInputException;
|
||||
import org.keycloak.representations.AccessToken;
|
||||
|
||||
import javax.security.cert.X509Certificate;
|
||||
@@ -85,16 +83,6 @@ public class BearerTokenRequestAuthenticator {
|
||||
}
|
||||
|
||||
protected AuthOutcome authenticateToken(HttpFacade exchange, String tokenString) {
|
||||
log.debug("Verifying access_token");
|
||||
if (log.isTraceEnabled()) {
|
||||
try {
|
||||
JWSInput jwsInput = new JWSInput(tokenString);
|
||||
String wireString = jwsInput.getWireString();
|
||||
log.tracef("\taccess_token: %s", wireString.substring(0, wireString.lastIndexOf(".")) + ".signature");
|
||||
} catch (JWSInputException e) {
|
||||
log.errorf(e, "Failed to parse access_token: %s", tokenString);
|
||||
}
|
||||
}
|
||||
try {
|
||||
token = AdapterRSATokenVerifier.verifyToken(tokenString, deployment);
|
||||
} catch (VerificationException e) {
|
||||
@@ -136,7 +124,6 @@ public class BearerTokenRequestAuthenticator {
|
||||
}
|
||||
surrogate = chain[0].getSubjectDN().getName();
|
||||
}
|
||||
log.debug("successful authorized");
|
||||
return AuthOutcome.AUTHENTICATED;
|
||||
}
|
||||
|
||||
|
||||
@@ -68,7 +68,6 @@ public class KeycloakDeployment {
|
||||
|
||||
protected String scope;
|
||||
protected SslRequired sslRequired = SslRequired.ALL;
|
||||
protected int confidentialPort = -1;
|
||||
protected TokenStore tokenStore = TokenStore.SESSION;
|
||||
protected String stateCookieName = "OAuth_Token_Request_State";
|
||||
protected boolean useResourceRoleMappings;
|
||||
@@ -278,14 +277,6 @@ public class KeycloakDeployment {
|
||||
this.sslRequired = sslRequired;
|
||||
}
|
||||
|
||||
public int getConfidentialPort() {
|
||||
return confidentialPort;
|
||||
}
|
||||
|
||||
public void setConfidentialPort(int confidentialPort) {
|
||||
this.confidentialPort = confidentialPort;
|
||||
}
|
||||
|
||||
public TokenStore getTokenStore() {
|
||||
return tokenStore;
|
||||
}
|
||||
|
||||
-5
@@ -78,11 +78,6 @@ public class KeycloakDeploymentBuilder {
|
||||
} else {
|
||||
deployment.setSslRequired(SslRequired.EXTERNAL);
|
||||
}
|
||||
|
||||
if (adapterConfig.getConfidentialPort() != -1) {
|
||||
deployment.setConfidentialPort(adapterConfig.getConfidentialPort());
|
||||
}
|
||||
|
||||
if (adapterConfig.getTokenStore() != null) {
|
||||
deployment.setTokenStore(TokenStore.valueOf(adapterConfig.getTokenStore().toUpperCase()));
|
||||
} else {
|
||||
|
||||
+2
-25
@@ -66,7 +66,7 @@ public class OAuthRequestAuthenticator {
|
||||
this.reqAuthenticator = requestAuthenticator;
|
||||
this.facade = facade;
|
||||
this.deployment = deployment;
|
||||
this.sslRedirectPort = deployment.getConfidentialPort() != -1 ? deployment.getConfidentialPort() : sslRedirectPort;
|
||||
this.sslRedirectPort = sslRedirectPort;
|
||||
this.tokenStore = tokenStore;
|
||||
}
|
||||
|
||||
@@ -170,9 +170,6 @@ public class OAuthRequestAuthenticator {
|
||||
String maxAge = getQueryParamValue(OAuth2Constants.MAX_AGE);
|
||||
url = UriUtils.stripQueryParam(url, OAuth2Constants.MAX_AGE);
|
||||
|
||||
String uiLocales = getQueryParamValue(OAuth2Constants.UI_LOCALES_PARAM);
|
||||
url = UriUtils.stripQueryParam(url, OAuth2Constants.UI_LOCALES_PARAM);
|
||||
|
||||
KeycloakUriBuilder redirectUriBuilder = deployment.getAuthUrl().clone()
|
||||
.queryParam(OAuth2Constants.RESPONSE_TYPE, OAuth2Constants.CODE)
|
||||
.queryParam(OAuth2Constants.CLIENT_ID, deployment.getResourceName())
|
||||
@@ -191,9 +188,6 @@ public class OAuthRequestAuthenticator {
|
||||
if (maxAge != null && maxAge.length() > 0) {
|
||||
redirectUriBuilder.queryParam(OAuth2Constants.MAX_AGE, maxAge);
|
||||
}
|
||||
if (uiLocales != null && uiLocales.length() > 0) {
|
||||
redirectUriBuilder.queryParam(OAuth2Constants.UI_LOCALES_PARAM, uiLocales);
|
||||
}
|
||||
|
||||
scope = TokenUtil.attachOIDCScope(scope);
|
||||
redirectUriBuilder.queryParam(OAuth2Constants.SCOPE, scope);
|
||||
@@ -337,7 +331,7 @@ public class OAuthRequestAuthenticator {
|
||||
} catch (ServerRequest.HttpFailure failure) {
|
||||
log.error("failed to turn code into token");
|
||||
log.error("status from server: " + failure.getStatus());
|
||||
if (failure.getError() != null) {
|
||||
if (failure.getStatus() == 400 && failure.getError() != null) {
|
||||
log.error(" " + failure.getError());
|
||||
}
|
||||
return challenge(403, OIDCAuthenticationError.Reason.CODE_TO_TOKEN_FAILURE, null);
|
||||
@@ -350,14 +344,6 @@ public class OAuthRequestAuthenticator {
|
||||
tokenString = tokenResponse.getToken();
|
||||
refreshToken = tokenResponse.getRefreshToken();
|
||||
idTokenString = tokenResponse.getIdToken();
|
||||
|
||||
log.debug("Verifying tokens");
|
||||
if (log.isTraceEnabled()) {
|
||||
logToken("\taccess_token", tokenString);
|
||||
logToken("\tid_token", idTokenString);
|
||||
logToken("\trefresh_token", refreshToken);
|
||||
}
|
||||
|
||||
try {
|
||||
token = AdapterRSATokenVerifier.verifyToken(tokenString, deployment);
|
||||
if (idTokenString != null) {
|
||||
@@ -412,13 +398,4 @@ public class OAuthRequestAuthenticator {
|
||||
return originalUri;
|
||||
}
|
||||
|
||||
private void logToken(String name, String token) {
|
||||
try {
|
||||
JWSInput jwsInput = new JWSInput(token);
|
||||
String wireString = jwsInput.getWireString();
|
||||
log.tracef("\t%s: %s", name, wireString.substring(0, wireString.lastIndexOf(".")) + ".signature");
|
||||
} catch (JWSInputException e) {
|
||||
log.errorf(e, "Failed to parse %s: %s", name, token);
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -32,7 +32,7 @@ import java.util.Map;
|
||||
*/
|
||||
public class ClientIdAndSecretCredentialsProvider implements ClientCredentialsProvider {
|
||||
|
||||
private static Logger logger = Logger.getLogger(ClientIdAndSecretCredentialsProvider.class);
|
||||
private static Logger logger = Logger.getLogger(ClientCredentialsProviderUtils.class);
|
||||
|
||||
public static final String PROVIDER_ID = CredentialRepresentation.SECRET;
|
||||
|
||||
|
||||
+18
-41
@@ -33,7 +33,6 @@ import org.keycloak.authorization.client.ClientAuthorizationContext;
|
||||
import org.keycloak.representations.AccessToken;
|
||||
import org.keycloak.representations.adapters.config.PolicyEnforcerConfig;
|
||||
import org.keycloak.representations.adapters.config.PolicyEnforcerConfig.EnforcementMode;
|
||||
import org.keycloak.representations.adapters.config.PolicyEnforcerConfig.MethodConfig;
|
||||
import org.keycloak.representations.adapters.config.PolicyEnforcerConfig.PathConfig;
|
||||
import org.keycloak.representations.idm.authorization.Permission;
|
||||
|
||||
@@ -97,9 +96,9 @@ public abstract class AbstractPolicyEnforcer {
|
||||
return createEmptyAuthorizationContext(true);
|
||||
}
|
||||
|
||||
MethodConfig methodConfig = getRequiredScopes(pathConfig, request);
|
||||
Set<String> requiredScopes = getRequiredScopes(pathConfig, request);
|
||||
|
||||
if (isAuthorized(pathConfig, methodConfig, accessToken, httpFacade)) {
|
||||
if (isAuthorized(pathConfig, requiredScopes, accessToken, httpFacade)) {
|
||||
try {
|
||||
return createAuthorizationContext(accessToken, pathConfig);
|
||||
} catch (Exception e) {
|
||||
@@ -109,7 +108,7 @@ public abstract class AbstractPolicyEnforcer {
|
||||
|
||||
LOGGER.debugf("Sending challenge to the client. Path [%s]", pathConfig);
|
||||
|
||||
if (!challenge(pathConfig, methodConfig, httpFacade)) {
|
||||
if (!challenge(pathConfig, requiredScopes, httpFacade)) {
|
||||
LOGGER.debugf("Challenge not sent, sending default forbidden response. Path [%s]", pathConfig);
|
||||
handleAccessDenied(httpFacade);
|
||||
}
|
||||
@@ -119,9 +118,9 @@ public abstract class AbstractPolicyEnforcer {
|
||||
return createEmptyAuthorizationContext(false);
|
||||
}
|
||||
|
||||
protected abstract boolean challenge(PathConfig pathConfig, MethodConfig methodConfig, OIDCHttpFacade facade);
|
||||
protected abstract boolean challenge(PathConfig pathConfig, Set<String> requiredScopes, OIDCHttpFacade facade);
|
||||
|
||||
protected boolean isAuthorized(PathConfig actualPathConfig, MethodConfig methodConfig, AccessToken accessToken, OIDCHttpFacade httpFacade) {
|
||||
protected boolean isAuthorized(PathConfig actualPathConfig, Set<String> requiredScopes, AccessToken accessToken, OIDCHttpFacade httpFacade) {
|
||||
Request request = httpFacade.getRequest();
|
||||
PolicyEnforcerConfig enforcerConfig = getEnforcerConfig();
|
||||
|
||||
@@ -147,7 +146,7 @@ public abstract class AbstractPolicyEnforcer {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (hasResourceScopePermission(methodConfig, permission)) {
|
||||
if (hasResourceScopePermission(requiredScopes, permission, actualPathConfig)) {
|
||||
LOGGER.debugf("Authorization GRANTED for path [%s]. Permissions [%s].", actualPathConfig, permissions);
|
||||
if (request.getMethod().equalsIgnoreCase("DELETE") && actualPathConfig.isInstance()) {
|
||||
this.paths.remove(actualPathConfig);
|
||||
@@ -156,7 +155,7 @@ public abstract class AbstractPolicyEnforcer {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (hasResourceScopePermission(methodConfig, permission)) {
|
||||
if (hasResourceScopePermission(requiredScopes, permission, actualPathConfig)) {
|
||||
hasPermission = true;
|
||||
return true;
|
||||
}
|
||||
@@ -167,7 +166,7 @@ public abstract class AbstractPolicyEnforcer {
|
||||
return true;
|
||||
}
|
||||
|
||||
LOGGER.debugf("Authorization FAILED for path [%s]. Not enough permissions [%s].", actualPathConfig, permissions);
|
||||
LOGGER.debugf("Authorization FAILED for path [%s]. No enough permissions [%s].", actualPathConfig, permissions);
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -187,29 +186,9 @@ public abstract class AbstractPolicyEnforcer {
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean hasResourceScopePermission(MethodConfig methodConfig, Permission permission) {
|
||||
List<String> requiredScopes = methodConfig.getScopes();
|
||||
private boolean hasResourceScopePermission(Set<String> requiredScopes, Permission permission, PathConfig actualPathConfig) {
|
||||
Set<String> allowedScopes = permission.getScopes();
|
||||
|
||||
if (allowedScopes.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
PolicyEnforcerConfig.ScopeEnforcementMode enforcementMode = methodConfig.getScopesEnforcementMode();
|
||||
|
||||
if (PolicyEnforcerConfig.ScopeEnforcementMode.ALL.equals(enforcementMode)) {
|
||||
return allowedScopes.containsAll(requiredScopes);
|
||||
}
|
||||
|
||||
if (PolicyEnforcerConfig.ScopeEnforcementMode.ANY.equals(enforcementMode)) {
|
||||
for (String requiredScope : requiredScopes) {
|
||||
if (allowedScopes.contains(requiredScope)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return requiredScopes.isEmpty();
|
||||
return (allowedScopes.containsAll(requiredScopes) || allowedScopes.isEmpty());
|
||||
}
|
||||
|
||||
protected AuthzClient getAuthzClient() {
|
||||
@@ -257,22 +236,20 @@ public abstract class AbstractPolicyEnforcer {
|
||||
return request.getRelativePath();
|
||||
}
|
||||
|
||||
private MethodConfig getRequiredScopes(PathConfig pathConfig, Request request) {
|
||||
private Set<String> getRequiredScopes(PathConfig pathConfig, Request request) {
|
||||
Set<String> requiredScopes = new HashSet<>();
|
||||
|
||||
requiredScopes.addAll(pathConfig.getScopes());
|
||||
|
||||
String method = request.getMethod();
|
||||
|
||||
for (MethodConfig methodConfig : pathConfig.getMethods()) {
|
||||
for (PolicyEnforcerConfig.MethodConfig methodConfig : pathConfig.getMethods()) {
|
||||
if (methodConfig.getMethod().equals(method)) {
|
||||
return methodConfig;
|
||||
requiredScopes.addAll(methodConfig.getScopes());
|
||||
}
|
||||
}
|
||||
|
||||
MethodConfig methodConfig = new MethodConfig();
|
||||
|
||||
methodConfig.setMethod(request.getMethod());
|
||||
methodConfig.setScopes(pathConfig.getScopes());
|
||||
methodConfig.setScopesEnforcementMode(PolicyEnforcerConfig.ScopeEnforcementMode.ANY);
|
||||
|
||||
return methodConfig;
|
||||
return requiredScopes;
|
||||
}
|
||||
|
||||
private AuthorizationContext createAuthorizationContext(AccessToken accessToken, PathConfig pathConfig) {
|
||||
|
||||
+7
-8
@@ -17,7 +17,7 @@
|
||||
*/
|
||||
package org.keycloak.adapters.authorization;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
import org.keycloak.adapters.OIDCHttpFacade;
|
||||
@@ -26,7 +26,6 @@ import org.keycloak.authorization.client.AuthzClient;
|
||||
import org.keycloak.authorization.client.representation.PermissionRequest;
|
||||
import org.keycloak.authorization.client.resource.PermissionResource;
|
||||
import org.keycloak.authorization.client.resource.ProtectionResource;
|
||||
import org.keycloak.representations.adapters.config.PolicyEnforcerConfig;
|
||||
import org.keycloak.representations.adapters.config.PolicyEnforcerConfig.PathConfig;
|
||||
|
||||
/**
|
||||
@@ -41,9 +40,9 @@ public class BearerTokenPolicyEnforcer extends AbstractPolicyEnforcer {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean challenge(PathConfig pathConfig, PolicyEnforcerConfig.MethodConfig methodConfig, OIDCHttpFacade facade) {
|
||||
protected boolean challenge(PathConfig pathConfig, Set<String> requiredScopes, OIDCHttpFacade facade) {
|
||||
if (getEnforcerConfig().getUserManagedAccess() != null) {
|
||||
challengeUmaAuthentication(pathConfig, methodConfig, facade);
|
||||
challengeUmaAuthentication(pathConfig, requiredScopes, facade);
|
||||
} else {
|
||||
challengeEntitlementAuthentication(facade);
|
||||
}
|
||||
@@ -62,10 +61,10 @@ public class BearerTokenPolicyEnforcer extends AbstractPolicyEnforcer {
|
||||
}
|
||||
}
|
||||
|
||||
private void challengeUmaAuthentication(PathConfig pathConfig, PolicyEnforcerConfig.MethodConfig methodConfig, OIDCHttpFacade facade) {
|
||||
private void challengeUmaAuthentication(PathConfig pathConfig, Set<String> requiredScopes, OIDCHttpFacade facade) {
|
||||
HttpFacade.Response response = facade.getResponse();
|
||||
AuthzClient authzClient = getAuthzClient();
|
||||
String ticket = getPermissionTicket(pathConfig, methodConfig, authzClient);
|
||||
String ticket = getPermissionTicket(pathConfig, requiredScopes, authzClient);
|
||||
String clientId = authzClient.getConfiguration().getResource();
|
||||
String authorizationServerUri = authzClient.getServerConfiguration().getIssuer().toString() + "/authz/authorize";
|
||||
response.setStatus(401);
|
||||
@@ -75,12 +74,12 @@ public class BearerTokenPolicyEnforcer extends AbstractPolicyEnforcer {
|
||||
}
|
||||
}
|
||||
|
||||
private String getPermissionTicket(PathConfig pathConfig, PolicyEnforcerConfig.MethodConfig methodConfig, AuthzClient authzClient) {
|
||||
private String getPermissionTicket(PathConfig pathConfig, Set<String> requiredScopes, AuthzClient authzClient) {
|
||||
ProtectionResource protection = authzClient.protection();
|
||||
PermissionResource permission = protection.permission();
|
||||
PermissionRequest permissionRequest = new PermissionRequest();
|
||||
permissionRequest.setResourceSetId(pathConfig.getId());
|
||||
permissionRequest.setScopes(new HashSet<>(methodConfig.getScopes()));
|
||||
permissionRequest.setScopes(requiredScopes);
|
||||
return permission.forResource(permissionRequest).getTicket();
|
||||
}
|
||||
}
|
||||
+7
-8
@@ -35,7 +35,6 @@ import org.keycloak.authorization.client.representation.EntitlementResponse;
|
||||
import org.keycloak.authorization.client.representation.PermissionRequest;
|
||||
import org.keycloak.authorization.client.representation.PermissionResponse;
|
||||
import org.keycloak.representations.AccessToken;
|
||||
import org.keycloak.representations.adapters.config.PolicyEnforcerConfig;
|
||||
import org.keycloak.representations.adapters.config.PolicyEnforcerConfig.PathConfig;
|
||||
import org.keycloak.representations.idm.authorization.Permission;
|
||||
|
||||
@@ -51,14 +50,14 @@ public class KeycloakAdapterPolicyEnforcer extends AbstractPolicyEnforcer {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isAuthorized(PathConfig pathConfig, PolicyEnforcerConfig.MethodConfig methodConfig, AccessToken accessToken, OIDCHttpFacade httpFacade) {
|
||||
protected boolean isAuthorized(PathConfig pathConfig, Set<String> requiredScopes, AccessToken accessToken, OIDCHttpFacade httpFacade) {
|
||||
AccessToken original = accessToken;
|
||||
|
||||
if (super.isAuthorized(pathConfig, methodConfig, accessToken, httpFacade)) {
|
||||
if (super.isAuthorized(pathConfig, requiredScopes, accessToken, httpFacade)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
accessToken = requestAuthorizationToken(pathConfig, methodConfig, httpFacade);
|
||||
accessToken = requestAuthorizationToken(pathConfig, requiredScopes, httpFacade);
|
||||
|
||||
if (accessToken == null) {
|
||||
return false;
|
||||
@@ -79,11 +78,11 @@ public class KeycloakAdapterPolicyEnforcer extends AbstractPolicyEnforcer {
|
||||
|
||||
original.setAuthorization(authorization);
|
||||
|
||||
return super.isAuthorized(pathConfig, methodConfig, accessToken, httpFacade);
|
||||
return super.isAuthorized(pathConfig, requiredScopes, accessToken, httpFacade);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean challenge(PathConfig pathConfig, PolicyEnforcerConfig.MethodConfig methodConfig, OIDCHttpFacade facade) {
|
||||
protected boolean challenge(PathConfig pathConfig, Set<String> requiredScopes, OIDCHttpFacade facade) {
|
||||
handleAccessDenied(facade);
|
||||
return true;
|
||||
}
|
||||
@@ -101,7 +100,7 @@ public class KeycloakAdapterPolicyEnforcer extends AbstractPolicyEnforcer {
|
||||
}
|
||||
}
|
||||
|
||||
private AccessToken requestAuthorizationToken(PathConfig pathConfig, PolicyEnforcerConfig.MethodConfig methodConfig, OIDCHttpFacade httpFacade) {
|
||||
private AccessToken requestAuthorizationToken(PathConfig pathConfig, Set<String> requiredScopes, OIDCHttpFacade httpFacade) {
|
||||
try {
|
||||
String accessToken = httpFacade.getSecurityContext().getTokenString();
|
||||
AuthzClient authzClient = getAuthzClient();
|
||||
@@ -112,7 +111,7 @@ public class KeycloakAdapterPolicyEnforcer extends AbstractPolicyEnforcer {
|
||||
PermissionRequest permissionRequest = new PermissionRequest();
|
||||
|
||||
permissionRequest.setResourceSetId(pathConfig.getId());
|
||||
permissionRequest.setScopes(new HashSet<>(methodConfig.getScopes()));
|
||||
permissionRequest.setScopes(requiredScopes);
|
||||
|
||||
PermissionResponse permissionResponse = authzClient.protection().permission().forResource(permissionRequest);
|
||||
AuthorizationRequest authzRequest = new AuthorizationRequest(permissionResponse.getTicket());
|
||||
|
||||
+2
-19
@@ -37,12 +37,8 @@ import javax.security.auth.callback.PasswordCallback;
|
||||
import javax.security.auth.callback.UnsupportedCallbackException;
|
||||
import javax.security.auth.login.LoginException;
|
||||
import javax.security.auth.spi.LoginModule;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.security.Principal;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
@@ -57,7 +53,7 @@ public abstract class AbstractKeycloakLoginModule implements LoginModule {
|
||||
|
||||
public static final String KEYCLOAK_CONFIG_FILE_OPTION = "keycloak-config-file";
|
||||
public static final String ROLE_PRINCIPAL_CLASS_OPTION = "role-principal-class";
|
||||
public static final String PROFILE_RESOURCE = "profile:";
|
||||
|
||||
protected Subject subject;
|
||||
protected CallbackHandler callbackHandler;
|
||||
protected Auth auth;
|
||||
@@ -88,27 +84,14 @@ public abstract class AbstractKeycloakLoginModule implements LoginModule {
|
||||
|
||||
protected KeycloakDeployment resolveDeployment(String keycloakConfigFile) {
|
||||
try {
|
||||
InputStream is = null;
|
||||
if (keycloakConfigFile.startsWith(PROFILE_RESOURCE)) {
|
||||
try {
|
||||
is = new URL(keycloakConfigFile).openStream();
|
||||
} catch (MalformedURLException mfue) {
|
||||
throw new RuntimeException(mfue);
|
||||
} catch (IOException ioe) {
|
||||
throw new RuntimeException(ioe);
|
||||
}
|
||||
} else {
|
||||
is = FindFile.findFile(keycloakConfigFile);
|
||||
}
|
||||
InputStream is = FindFile.findFile(keycloakConfigFile);
|
||||
KeycloakDeployment kd = KeycloakDeploymentBuilder.build(is);
|
||||
return kd;
|
||||
|
||||
} catch (RuntimeException e) {
|
||||
getLogger().debug("Unable to find or parse file " + keycloakConfigFile + " due to " + e.getMessage(), e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean login() throws LoginException {
|
||||
|
||||
+1
-1
@@ -81,7 +81,7 @@ public class JWKPublicKeyLocator implements PublicKeyLocator {
|
||||
|
||||
|
||||
private PublicKey lookupCachedKey(int publicKeyCacheTtl, int currentTime, String kid) {
|
||||
if (lastRequestTime + publicKeyCacheTtl > currentTime && kid != null) {
|
||||
if (lastRequestTime + publicKeyCacheTtl > currentTime) {
|
||||
return currentKeys.get(kid);
|
||||
} else {
|
||||
return null;
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-as7-integration-pom</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>3.4.1.Final</version>
|
||||
<version>3.3.0.Final</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-as7-integration-pom</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>3.4.1.Final</version>
|
||||
<version>3.3.0.Final</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
-13
@@ -1,13 +0,0 @@
|
||||
package org.keycloak.adapters.jbossweb;
|
||||
|
||||
import org.apache.catalina.Container;
|
||||
import org.apache.catalina.Valve;
|
||||
import org.keycloak.adapters.AdapterDeploymentContext;
|
||||
import org.keycloak.adapters.tomcat.AbstractAuthenticatedActionsValve;
|
||||
|
||||
public class AuthenticatedActionsValve extends AbstractAuthenticatedActionsValve {
|
||||
|
||||
public AuthenticatedActionsValve(AdapterDeploymentContext deploymentContext, Valve next, Container container) {
|
||||
super(deploymentContext, next, container);
|
||||
}
|
||||
}
|
||||
+1
-9
@@ -17,15 +17,11 @@
|
||||
|
||||
package org.keycloak.adapters.jbossweb;
|
||||
|
||||
import org.apache.catalina.Container;
|
||||
import org.apache.catalina.LifecycleException;
|
||||
import org.apache.catalina.Valve;
|
||||
import org.apache.catalina.connector.Request;
|
||||
import org.apache.catalina.connector.Response;
|
||||
import org.apache.catalina.core.StandardContext;
|
||||
import org.apache.catalina.deploy.LoginConfig;
|
||||
import org.keycloak.adapters.AdapterDeploymentContext;
|
||||
import org.keycloak.adapters.tomcat.AbstractAuthenticatedActionsValve;
|
||||
import org.keycloak.adapters.tomcat.AbstractKeycloakAuthenticatorValve;
|
||||
import org.keycloak.adapters.tomcat.GenericPrincipalFactory;
|
||||
|
||||
@@ -60,6 +56,7 @@ public class KeycloakAuthenticatorValve extends AbstractKeycloakAuthenticatorVal
|
||||
super.start();
|
||||
}
|
||||
|
||||
|
||||
public void logout(Request request) {
|
||||
logoutInternal(request);
|
||||
}
|
||||
@@ -68,9 +65,4 @@ public class KeycloakAuthenticatorValve extends AbstractKeycloakAuthenticatorVal
|
||||
protected GenericPrincipalFactory createPrincipalFactory() {
|
||||
return new JBossWebPrincipalFactory();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AbstractAuthenticatedActionsValve createAuthenticatedActionsValve(AdapterDeploymentContext deploymentContext, Valve next, Container container) {
|
||||
return new AuthenticatedActionsValve(deploymentContext, next, container);
|
||||
}
|
||||
}
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-as7-integration-pom</artifactId>
|
||||
<version>3.4.1.Final</version>
|
||||
<version>3.3.0.Final</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>3.4.1.Final</version>
|
||||
<version>3.3.0.Final</version>
|
||||
<relativePath>../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<name>Keycloak AS7 / JBoss EAP 6 Integration</name>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>3.4.1.Final</version>
|
||||
<version>3.3.0.Final</version>
|
||||
<relativePath>../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>3.4.1.Final</version>
|
||||
<version>3.3.0.Final</version>
|
||||
<relativePath>../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>3.4.1.Final</version>
|
||||
<version>3.3.0.Final</version>
|
||||
<relativePath>../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>3.4.1.Final</version>
|
||||
<version>3.3.0.Final</version>
|
||||
<relativePath>../../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>3.4.1.Final</version>
|
||||
<version>3.3.0.Final</version>
|
||||
<relativePath>../../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>3.4.1.Final</version>
|
||||
<version>3.3.0.Final</version>
|
||||
<relativePath>../../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>3.4.1.Final</version>
|
||||
<version>3.3.0.Final</version>
|
||||
<relativePath>../../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>3.4.1.Final</version>
|
||||
<version>3.3.0.Final</version>
|
||||
<relativePath>../../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>3.4.1.Final</version>
|
||||
<version>3.3.0.Final</version>
|
||||
<relativePath>../../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>3.4.1.Final</version>
|
||||
<version>3.3.0.Final</version>
|
||||
<relativePath>../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<name>Keycloak Jetty Integration</name>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>3.4.1.Final</version>
|
||||
<version>3.3.0.Final</version>
|
||||
<relativePath>../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
} else if (initOptions && initOptions.adapter === 'default') {
|
||||
adapter = loadAdapter();
|
||||
} else {
|
||||
if (window.Cordova || window.cordova) {
|
||||
if (window.Cordova) {
|
||||
adapter = loadAdapter('cordova');
|
||||
} else {
|
||||
adapter = loadAdapter();
|
||||
@@ -948,14 +948,7 @@
|
||||
|
||||
if (type == 'cordova') {
|
||||
loginIframe.enable = false;
|
||||
var cordovaOpenWindowWrapper = function(loginUrl, target, options) {
|
||||
if (window.cordova && window.cordova.InAppBrowser) {
|
||||
// Use inappbrowser for IOS and Android if available
|
||||
return window.cordova.InAppBrowser.open(loginUrl, target, options);
|
||||
} else {
|
||||
return window.open(loginUrl, target, options);
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
login: function(options) {
|
||||
var promise = createPromise();
|
||||
@@ -966,7 +959,8 @@
|
||||
}
|
||||
|
||||
var loginUrl = kc.createLoginUrl(options);
|
||||
var ref = cordovaOpenWindowWrapper(loginUrl, '_blank', o);
|
||||
var ref = window.open(loginUrl, '_blank', o);
|
||||
|
||||
var completed = false;
|
||||
|
||||
ref.addEventListener('loadstart', function(event) {
|
||||
@@ -999,7 +993,7 @@
|
||||
var promise = createPromise();
|
||||
|
||||
var logoutUrl = kc.createLogoutUrl(options);
|
||||
var ref = cordovaOpenWindowWrapper(logoutUrl, '_blank', 'location=no,hidden=yes');
|
||||
var ref = window.open(logoutUrl, '_blank', 'location=no,hidden=yes');
|
||||
|
||||
var error;
|
||||
|
||||
@@ -1032,7 +1026,7 @@
|
||||
|
||||
register : function() {
|
||||
var registerUrl = kc.createRegisterUrl();
|
||||
var ref = cordovaOpenWindowWrapper(registerUrl, '_blank', 'location=no');
|
||||
var ref = window.open(registerUrl, '_blank', 'location=no');
|
||||
ref.addEventListener('loadstart', function(event) {
|
||||
if (event.url.indexOf('http://localhost') == 0) {
|
||||
ref.close();
|
||||
@@ -1042,7 +1036,7 @@
|
||||
|
||||
accountManagement : function() {
|
||||
var accountUrl = kc.createAccountUrl();
|
||||
var ref = cordovaOpenWindowWrapper(accountUrl, '_blank', 'location=no');
|
||||
var ref = window.open(accountUrl, '_blank', 'location=no');
|
||||
ref.addEventListener('loadstart', function(event) {
|
||||
if (event.url.indexOf('http://localhost') == 0) {
|
||||
ref.close();
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
|
||||
req.onreadystatechange = function () {
|
||||
if (req.readyState === 4) {
|
||||
if (req.status === 204 || req.status === 1223) {
|
||||
if (req.status === 204) {
|
||||
init = {
|
||||
clientId: clientId,
|
||||
origin: origin
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>3.4.1.Final</version>
|
||||
<version>3.3.0.Final</version>
|
||||
<relativePath>../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>3.4.1.Final</version>
|
||||
<version>3.3.0.Final</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<name>Keycloak OIDC Client Adapter Modules</name>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>3.4.1.Final</version>
|
||||
<version>3.3.0.Final</version>
|
||||
<relativePath>../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>3.4.1.Final</version>
|
||||
<version>3.3.0.Final</version>
|
||||
<relativePath>../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>3.4.1.Final</version>
|
||||
<version>3.3.0.Final</version>
|
||||
<relativePath>../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<artifactId>spring-boot-container-bundle</artifactId>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>3.4.1.Final</version>
|
||||
<version>3.3.0.Final</version>
|
||||
<relativePath>../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>3.4.1.Final</version>
|
||||
<version>3.3.0.Final</version>
|
||||
<relativePath>../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
+5
-1
@@ -45,7 +45,11 @@ public class HttpHeaderInspectingApiRequestMatcher implements RequestMatcher {
|
||||
*/
|
||||
@Override
|
||||
public boolean matches(HttpServletRequest request) {
|
||||
return X_REQUESTED_WITH_HEADER_AJAX_VALUE.equals(request.getHeader(X_REQUESTED_WITH_HEADER));
|
||||
boolean ajax = X_REQUESTED_WITH_HEADER_AJAX_VALUE.equals(request.getHeader(X_REQUESTED_WITH_HEADER));
|
||||
boolean html = request.getHeader(HttpHeaders.ACCEPT) != null && request.getHeader(HttpHeaders.ACCEPT).contains(
|
||||
MediaType.TEXT_HTML_VALUE);
|
||||
|
||||
return ajax || !html;
|
||||
}
|
||||
|
||||
}
|
||||
+17
-15
@@ -17,16 +17,7 @@
|
||||
|
||||
package org.keycloak.adapters.springsecurity.authentication;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.apache.http.HttpHeaders;
|
||||
import org.keycloak.adapters.AdapterDeploymentContext;
|
||||
import org.keycloak.adapters.spi.HttpFacade;
|
||||
import org.keycloak.adapters.springsecurity.facade.SimpleHttpFacade;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.http.HttpStatus;
|
||||
@@ -35,6 +26,17 @@ import org.springframework.security.web.AuthenticationEntryPoint;
|
||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import org.keycloak.adapters.AdapterDeploymentContext;
|
||||
import org.keycloak.adapters.spi.HttpFacade;
|
||||
import org.keycloak.adapters.springsecurity.config.KeycloakWebSecurityConfigurerAdapter;
|
||||
import org.keycloak.adapters.springsecurity.facade.SimpleHttpFacade;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
|
||||
/**
|
||||
* Provides a Keycloak {@link AuthenticationEntryPoint authentication entry point}. Uses a
|
||||
* {@link RequestMatcher} to determine if the request is an interactive login request or a
|
||||
@@ -60,14 +62,15 @@ public class KeycloakAuthenticationEntryPoint implements AuthenticationEntryPoin
|
||||
private final RequestMatcher apiRequestMatcher;
|
||||
private String loginUri = DEFAULT_LOGIN_URI;
|
||||
private String realm = DEFAULT_REALM;
|
||||
|
||||
|
||||
private AdapterDeploymentContext adapterDeploymentContext;
|
||||
|
||||
/**
|
||||
* Creates a new Keycloak authentication entry point.
|
||||
*/
|
||||
public KeycloakAuthenticationEntryPoint(AdapterDeploymentContext adapterDeploymentContext) {
|
||||
this(adapterDeploymentContext, DEFAULT_API_REQUEST_MATCHER);
|
||||
this(DEFAULT_API_REQUEST_MATCHER);
|
||||
this.adapterDeploymentContext = adapterDeploymentContext;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -77,15 +80,14 @@ public class KeycloakAuthenticationEntryPoint implements AuthenticationEntryPoin
|
||||
* @param apiRequestMatcher the <code>RequestMatcher</code> to use to determine
|
||||
* if the current request is an API request or a browser request (required)
|
||||
*/
|
||||
public KeycloakAuthenticationEntryPoint(AdapterDeploymentContext adapterDeploymentContext, RequestMatcher apiRequestMatcher) {
|
||||
public KeycloakAuthenticationEntryPoint(RequestMatcher apiRequestMatcher) {
|
||||
Assert.notNull(apiRequestMatcher, "apiRequestMatcher required");
|
||||
Assert.notNull(adapterDeploymentContext, "adapterDeploymentContext required");
|
||||
this.adapterDeploymentContext = adapterDeploymentContext;
|
||||
this.apiRequestMatcher = apiRequestMatcher;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
|
||||
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException
|
||||
{
|
||||
HttpFacade facade = new SimpleHttpFacade(request, response);
|
||||
if (apiRequestMatcher.matches(request) || adapterDeploymentContext.resolveDeployment(facade).isBearerOnly()) {
|
||||
commenceUnauthorizedResponse(request, response);
|
||||
|
||||
+5
-12
@@ -17,13 +17,14 @@
|
||||
|
||||
package org.keycloak.adapters.springsecurity.authentication;
|
||||
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
|
||||
|
||||
/**
|
||||
* To return the forbidden code with the corresponding message.
|
||||
@@ -35,14 +36,6 @@ public class KeycloakAuthenticationFailureHandler implements AuthenticationFailu
|
||||
|
||||
@Override
|
||||
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
|
||||
// Check that the response was not committed yet (this may happen when another
|
||||
// part of the Keycloak adapter sends a challenge or a redirect).
|
||||
if (!response.isCommitted()) {
|
||||
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unable to authenticate using the Authorization header");
|
||||
} else {
|
||||
if (200 <= response.getStatus() && response.getStatus() < 300) {
|
||||
throw new RuntimeException("Success response was committed while authentication failed!", exception);
|
||||
}
|
||||
}
|
||||
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unable to authenticate using the Authorization header");
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -50,7 +50,7 @@ public class KeycloakAuthenticationProvider implements AuthenticationProvider {
|
||||
for (String role : token.getAccount().getRoles()) {
|
||||
grantedAuthorities.add(new KeycloakRole(role));
|
||||
}
|
||||
return new KeycloakAuthenticationToken(token.getAccount(), token.isInteractive(), mapAuthorities(grantedAuthorities));
|
||||
return new KeycloakAuthenticationToken(token.getAccount(), mapAuthorities(grantedAuthorities));
|
||||
}
|
||||
|
||||
private Collection<? extends GrantedAuthority> mapAuthorities(
|
||||
|
||||
+1
-1
@@ -94,7 +94,7 @@ public class SpringSecurityRequestAuthenticator extends RequestAuthenticator {
|
||||
|
||||
logger.debug("Completing bearer authentication. Bearer roles: {} ",roles);
|
||||
|
||||
SecurityContextHolder.getContext().setAuthentication(new KeycloakAuthenticationToken(account, false));
|
||||
SecurityContextHolder.getContext().setAuthentication(new KeycloakAuthenticationToken(account));
|
||||
request.setAttribute(KeycloakSecurityContext.class.getName(), securityContext);
|
||||
}
|
||||
|
||||
|
||||
-15
@@ -23,11 +23,9 @@ import org.keycloak.adapters.springsecurity.AdapterDeploymentContextFactoryBean;
|
||||
import org.keycloak.adapters.springsecurity.authentication.KeycloakAuthenticationEntryPoint;
|
||||
import org.keycloak.adapters.springsecurity.authentication.KeycloakAuthenticationProvider;
|
||||
import org.keycloak.adapters.springsecurity.authentication.KeycloakLogoutHandler;
|
||||
import org.keycloak.adapters.springsecurity.filter.KeycloakAuthenticatedActionsFilter;
|
||||
import org.keycloak.adapters.springsecurity.filter.KeycloakAuthenticationProcessingFilter;
|
||||
import org.keycloak.adapters.springsecurity.filter.KeycloakCsrfRequestMatcher;
|
||||
import org.keycloak.adapters.springsecurity.filter.KeycloakPreAuthActionsFilter;
|
||||
import org.keycloak.adapters.springsecurity.filter.KeycloakSecurityContextRequestFilter;
|
||||
import org.keycloak.adapters.springsecurity.management.HttpSessionManager;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
@@ -43,7 +41,6 @@ import org.springframework.security.web.AuthenticationEntryPoint;
|
||||
import org.springframework.security.web.authentication.logout.LogoutFilter;
|
||||
import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy;
|
||||
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
|
||||
import org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter;
|
||||
|
||||
/**
|
||||
* Provides a convenient base class for creating a {@link WebSecurityConfigurer}
|
||||
@@ -94,11 +91,6 @@ public abstract class KeycloakWebSecurityConfigurerAdapter extends WebSecurityCo
|
||||
return new KeycloakPreAuthActionsFilter(httpSessionManager());
|
||||
}
|
||||
|
||||
@Bean
|
||||
protected KeycloakAuthenticatedActionsFilter keycloakAuthenticatedActionsFilter() {
|
||||
return new KeycloakAuthenticatedActionsFilter();
|
||||
}
|
||||
|
||||
protected KeycloakCsrfRequestMatcher keycloakCsrfRequestMatcher() {
|
||||
return new KeycloakCsrfRequestMatcher();
|
||||
}
|
||||
@@ -125,8 +117,6 @@ public abstract class KeycloakWebSecurityConfigurerAdapter extends WebSecurityCo
|
||||
.and()
|
||||
.addFilterBefore(keycloakPreAuthActionsFilter(), LogoutFilter.class)
|
||||
.addFilterBefore(keycloakAuthenticationProcessingFilter(), BasicAuthenticationFilter.class)
|
||||
.addFilterBefore(keycloakAuthenticatedActionsFilter(), BasicAuthenticationFilter.class)
|
||||
.addFilterAfter(keycloakSecurityContextRequestFilter(), SecurityContextHolderAwareRequestFilter.class)
|
||||
.exceptionHandling().authenticationEntryPoint(authenticationEntryPoint())
|
||||
.and()
|
||||
.logout()
|
||||
@@ -134,9 +124,4 @@ public abstract class KeycloakWebSecurityConfigurerAdapter extends WebSecurityCo
|
||||
.logoutUrl("/sso/logout").permitAll()
|
||||
.logoutSuccessUrl("/");
|
||||
}
|
||||
|
||||
@Bean
|
||||
protected KeycloakSecurityContextRequestFilter keycloakSecurityContextRequestFilter() {
|
||||
return new KeycloakSecurityContextRequestFilter();
|
||||
}
|
||||
}
|
||||
+33
-8
@@ -24,7 +24,6 @@ import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.keycloak.OAuth2Constants;
|
||||
import org.keycloak.adapters.AdapterDeploymentContext;
|
||||
import org.keycloak.adapters.AdapterTokenStore;
|
||||
import org.keycloak.adapters.KeycloakDeployment;
|
||||
@@ -37,7 +36,6 @@ import org.keycloak.adapters.springsecurity.authentication.KeycloakAuthenticatio
|
||||
import org.keycloak.adapters.springsecurity.authentication.SpringSecurityRequestAuthenticator;
|
||||
import org.keycloak.adapters.springsecurity.facade.SimpleHttpFacade;
|
||||
import org.keycloak.adapters.springsecurity.token.AdapterTokenStoreFactory;
|
||||
import org.keycloak.adapters.springsecurity.token.KeycloakAuthenticationToken;
|
||||
import org.keycloak.adapters.springsecurity.token.SpringSecurityAdapterTokenStoreFactory;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -63,19 +61,19 @@ import org.springframework.util.Assert;
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class KeycloakAuthenticationProcessingFilter extends AbstractAuthenticationProcessingFilter implements ApplicationContextAware {
|
||||
|
||||
public static final String DEFAULT_LOGIN_URL = "/sso/login";
|
||||
public static final String AUTHORIZATION_HEADER = "Authorization";
|
||||
public static final String SCHEME_BEARER = "bearer ";
|
||||
public static final String SCHEME_BASIC = "basic ";
|
||||
|
||||
|
||||
/**
|
||||
* Request matcher that matches requests to the {@link KeycloakAuthenticationEntryPoint#DEFAULT_LOGIN_URI default login URI}
|
||||
* and any request with a <code>Authorization</code> header.
|
||||
*/
|
||||
public static final RequestMatcher DEFAULT_REQUEST_MATCHER =
|
||||
new OrRequestMatcher(
|
||||
new AntPathRequestMatcher(DEFAULT_LOGIN_URL),
|
||||
new RequestHeaderRequestMatcher(AUTHORIZATION_HEADER),
|
||||
new QueryParamPresenceRequestMatcher(OAuth2Constants.ACCESS_TOKEN)
|
||||
);
|
||||
new OrRequestMatcher(new AntPathRequestMatcher(DEFAULT_LOGIN_URL), new RequestHeaderRequestMatcher(AUTHORIZATION_HEADER));
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(KeycloakAuthenticationProcessingFilter.class);
|
||||
|
||||
@@ -183,10 +181,36 @@ public class KeycloakAuthenticationProcessingFilter extends AbstractAuthenticati
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the request was made with a bearer token authorization header.
|
||||
*
|
||||
* @param request the current <code>HttpServletRequest</code>
|
||||
*
|
||||
* @return <code>true</code> if the <code>request</code> was made with a bearer token authorization header;
|
||||
* <code>false</code> otherwise.
|
||||
*/
|
||||
protected boolean isBearerTokenRequest(HttpServletRequest request) {
|
||||
String authValue = request.getHeader(AUTHORIZATION_HEADER);
|
||||
return authValue != null && authValue.toLowerCase().startsWith(SCHEME_BEARER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the request was made with a Basic authentication authorization header.
|
||||
*
|
||||
* @param request the current <code>HttpServletRequest</code>
|
||||
* @return <code>true</code> if the <code>request</code> was made with a Basic authentication authorization header;
|
||||
* <code>false</code> otherwise.
|
||||
*/
|
||||
protected boolean isBasicAuthRequest(HttpServletRequest request) {
|
||||
String authValue = request.getHeader(AUTHORIZATION_HEADER);
|
||||
return authValue != null && authValue.toLowerCase().startsWith(SCHEME_BASIC);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain,
|
||||
Authentication authResult) throws IOException, ServletException {
|
||||
if (authResult instanceof KeycloakAuthenticationToken && ((KeycloakAuthenticationToken) authResult).isInteractive()) {
|
||||
|
||||
if (!(this.isBearerTokenRequest(request) || this.isBasicAuthRequest(request))) {
|
||||
super.successfulAuthentication(request, response, chain, authResult);
|
||||
return;
|
||||
}
|
||||
@@ -207,6 +231,7 @@ public class KeycloakAuthenticationProcessingFilter extends AbstractAuthenticati
|
||||
} finally {
|
||||
SecurityContextHolder.clearContext();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
-113
@@ -1,113 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.keycloak.adapters.springsecurity.filter;
|
||||
|
||||
import org.keycloak.KeycloakPrincipal;
|
||||
import org.keycloak.KeycloakSecurityContext;
|
||||
import org.keycloak.adapters.AdapterDeploymentContext;
|
||||
import org.keycloak.adapters.KeycloakDeployment;
|
||||
import org.keycloak.adapters.RefreshableKeycloakSecurityContext;
|
||||
import org.keycloak.adapters.springsecurity.facade.SimpleHttpFacade;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.web.filter.GenericFilterBean;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
public class KeycloakSecurityContextRequestFilter extends GenericFilterBean implements ApplicationContextAware {
|
||||
|
||||
private static final String FILTER_APPLIED = KeycloakSecurityContext.class.getPackage().getName() + ".token-refreshed";
|
||||
|
||||
private ApplicationContext applicationContext;
|
||||
private AdapterDeploymentContext deploymentContext;
|
||||
|
||||
@Override
|
||||
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {
|
||||
if (request.getAttribute(FILTER_APPLIED) != null) {
|
||||
filterChain.doFilter(request, response);
|
||||
return;
|
||||
}
|
||||
|
||||
request.setAttribute(FILTER_APPLIED, Boolean.TRUE);
|
||||
|
||||
KeycloakSecurityContext keycloakSecurityContext = getKeycloakPrincipal();
|
||||
|
||||
if (keycloakSecurityContext instanceof RefreshableKeycloakSecurityContext) {
|
||||
RefreshableKeycloakSecurityContext refreshableSecurityContext = (RefreshableKeycloakSecurityContext) keycloakSecurityContext;
|
||||
|
||||
if (refreshableSecurityContext.isActive()) {
|
||||
KeycloakDeployment deployment = resolveDeployment(request, response);
|
||||
|
||||
if (deployment.isAlwaysRefreshToken()) {
|
||||
if (refreshableSecurityContext.refreshExpiredToken(false)) {
|
||||
request.setAttribute(KeycloakSecurityContext.class.getName(), refreshableSecurityContext);
|
||||
} else {
|
||||
clearAuthenticationContext();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
clearAuthenticationContext();
|
||||
}
|
||||
}
|
||||
|
||||
filterChain.doFilter(request, response);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initFilterBean() throws ServletException {
|
||||
deploymentContext = applicationContext.getBean(AdapterDeploymentContext.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
||||
this.applicationContext = applicationContext;
|
||||
}
|
||||
|
||||
private KeycloakSecurityContext getKeycloakPrincipal() {
|
||||
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
||||
|
||||
if (authentication != null) {
|
||||
Object principal = authentication.getPrincipal();
|
||||
|
||||
if (principal instanceof KeycloakPrincipal) {
|
||||
return KeycloakPrincipal.class.cast(principal).getKeycloakSecurityContext();
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private KeycloakDeployment resolveDeployment(ServletRequest servletRequest, ServletResponse servletResponse) {
|
||||
return deploymentContext.resolveDeployment(new SimpleHttpFacade(HttpServletRequest.class.cast(servletRequest), HttpServletResponse.class.cast(servletResponse)));
|
||||
}
|
||||
|
||||
private void clearAuthenticationContext() {
|
||||
SecurityContextHolder.clearContext();
|
||||
}
|
||||
}
|
||||
-39
@@ -1,39 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.keycloak.adapters.springsecurity.filter;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||
|
||||
/**
|
||||
* Spring RequestMatcher that checks for the presence of a query parameter.
|
||||
*
|
||||
* @author <a href="mailto:glavoie@gmail.com">Gabriel Lavoie</a>
|
||||
*/
|
||||
public class QueryParamPresenceRequestMatcher implements RequestMatcher {
|
||||
private String param;
|
||||
|
||||
public QueryParamPresenceRequestMatcher(String param) {
|
||||
this.param = param;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(HttpServletRequest httpServletRequest) {
|
||||
return param != null && httpServletRequest.getParameter(param) != null;
|
||||
}
|
||||
}
|
||||
+2
-9
@@ -38,27 +38,24 @@ import java.util.Collection;
|
||||
public class KeycloakAuthenticationToken extends AbstractAuthenticationToken implements Authentication {
|
||||
|
||||
private Principal principal;
|
||||
private boolean interactive;
|
||||
|
||||
/**
|
||||
* Creates a new, unauthenticated Keycloak security token for the given account.
|
||||
*/
|
||||
public KeycloakAuthenticationToken(KeycloakAccount account, boolean interactive) {
|
||||
public KeycloakAuthenticationToken(KeycloakAccount account) {
|
||||
super(null);
|
||||
Assert.notNull(account, "KeycloakAccount cannot be null");
|
||||
Assert.notNull(account.getPrincipal(), "KeycloakAccount.getPrincipal() cannot be null");
|
||||
this.principal = account.getPrincipal();
|
||||
this.setDetails(account);
|
||||
this.interactive = interactive;
|
||||
}
|
||||
|
||||
public KeycloakAuthenticationToken(KeycloakAccount account, boolean interactive, Collection<? extends GrantedAuthority> authorities) {
|
||||
public KeycloakAuthenticationToken(KeycloakAccount account, Collection<? extends GrantedAuthority> authorities) {
|
||||
super(authorities);
|
||||
Assert.notNull(account, "KeycloakAccount cannot be null");
|
||||
Assert.notNull(account.getPrincipal(), "KeycloakAccount.getPrincipal() cannot be null");
|
||||
this.principal = account.getPrincipal();
|
||||
this.setDetails(account);
|
||||
this.interactive = interactive;
|
||||
setAuthenticated(true);
|
||||
}
|
||||
|
||||
@@ -75,8 +72,4 @@ public class KeycloakAuthenticationToken extends AbstractAuthenticationToken imp
|
||||
public OidcKeycloakAccount getAccount() {
|
||||
return (OidcKeycloakAccount) this.getDetails();
|
||||
}
|
||||
|
||||
public boolean isInteractive() {
|
||||
return interactive;
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -105,7 +105,7 @@ public class SpringSecurityTokenStore implements AdapterTokenStore {
|
||||
}
|
||||
|
||||
logger.debug("Saving account info {}", account);
|
||||
SecurityContextHolder.getContext().setAuthentication(new KeycloakAuthenticationToken(account, true));
|
||||
SecurityContextHolder.getContext().setAuthentication(new KeycloakAuthenticationToken(account));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+7
-2
@@ -39,9 +39,14 @@ public class HttpHeaderInspectingApiRequestMatcherTest {
|
||||
request = new MockHttpServletRequest();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMatches() throws Exception {
|
||||
assertTrue(apiRequestMatcher.matches(request));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMatchesBrowserRequest() throws Exception {
|
||||
request.addHeader(HttpHeaders.ACCEPT, "application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
|
||||
request.addHeader(HttpHeaders.ACCEPT, "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
|
||||
assertFalse(apiRequestMatcher.matches(request));
|
||||
}
|
||||
|
||||
@@ -50,7 +55,7 @@ public class HttpHeaderInspectingApiRequestMatcherTest {
|
||||
request.addHeader(
|
||||
HttpHeaderInspectingApiRequestMatcher.X_REQUESTED_WITH_HEADER,
|
||||
HttpHeaderInspectingApiRequestMatcher.X_REQUESTED_WITH_HEADER_AJAX_VALUE);
|
||||
|
||||
assertTrue(apiRequestMatcher.matches(request));
|
||||
}
|
||||
|
||||
}
|
||||
+16
-30
@@ -17,27 +17,24 @@
|
||||
|
||||
package org.keycloak.adapters.springsecurity.authentication;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Matchers.eq;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import org.apache.http.HttpHeaders;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.keycloak.adapters.AdapterDeploymentContext;
|
||||
import org.keycloak.adapters.KeycloakDeployment;
|
||||
import org.keycloak.adapters.spi.HttpFacade;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import org.keycloak.adapters.AdapterDeploymentContext;
|
||||
import org.keycloak.adapters.KeycloakDeployment;
|
||||
import org.keycloak.adapters.spi.HttpFacade;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Matchers.eq;
|
||||
import org.mockito.Mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
|
||||
/**
|
||||
* Keycloak authentication entry point tests.
|
||||
@@ -49,16 +46,13 @@ public class KeycloakAuthenticationEntryPointTest {
|
||||
private MockHttpServletResponse response;
|
||||
@Mock
|
||||
private ApplicationContext applicationContext;
|
||||
|
||||
|
||||
@Mock
|
||||
private AdapterDeploymentContext adapterDeploymentContext;
|
||||
|
||||
|
||||
@Mock
|
||||
private KeycloakDeployment keycloakDeployment;
|
||||
|
||||
@Mock
|
||||
private RequestMatcher requestMatcher;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
@@ -92,8 +86,8 @@ public class KeycloakAuthenticationEntryPointTest {
|
||||
public void testCommenceWithUnauthorizedWithAccept() throws Exception {
|
||||
request.addHeader(HttpHeaders.ACCEPT, "application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
|
||||
authenticationEntryPoint.commence(request, response, null);
|
||||
assertEquals(HttpStatus.FOUND.value(), response.getStatus());
|
||||
assertNull(response.getHeader(HttpHeaders.WWW_AUTHENTICATE));
|
||||
assertEquals(HttpStatus.UNAUTHORIZED.value(), response.getStatus());
|
||||
assertNotNull(response.getHeader(HttpHeaders.WWW_AUTHENTICATE));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -106,14 +100,6 @@ public class KeycloakAuthenticationEntryPointTest {
|
||||
assertEquals(logoutUri, response.getHeader("Location"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCommenceWithCustomRequestMatcher() throws Exception {
|
||||
new KeycloakAuthenticationEntryPoint(adapterDeploymentContext, requestMatcher)
|
||||
.commence(request, response, null);
|
||||
|
||||
verify(requestMatcher).matches(request);
|
||||
}
|
||||
|
||||
private void configureBrowserRequest() {
|
||||
request.addHeader(HttpHeaders.ACCEPT, "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
|
||||
}
|
||||
|
||||
+8
-18
@@ -44,7 +44,6 @@ import static org.mockito.Mockito.mock;
|
||||
public class KeycloakAuthenticationProviderTest {
|
||||
private KeycloakAuthenticationProvider provider = new KeycloakAuthenticationProvider();
|
||||
private KeycloakAuthenticationToken token;
|
||||
private KeycloakAuthenticationToken interactiveToken;
|
||||
private Set<String> roles = Sets.newSet("user", "admin");
|
||||
|
||||
@Before
|
||||
@@ -53,18 +52,18 @@ public class KeycloakAuthenticationProviderTest {
|
||||
RefreshableKeycloakSecurityContext securityContext = mock(RefreshableKeycloakSecurityContext.class);
|
||||
KeycloakAccount account = new SimpleKeycloakAccount(principal, roles, securityContext);
|
||||
|
||||
token = new KeycloakAuthenticationToken(account, false);
|
||||
interactiveToken = new KeycloakAuthenticationToken(account, true);
|
||||
token = new KeycloakAuthenticationToken(account);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAuthenticate() throws Exception {
|
||||
assertAuthenticationResult(provider.authenticate(token));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAuthenticateInteractive() throws Exception {
|
||||
assertAuthenticationResult(provider.authenticate(interactiveToken));
|
||||
Authentication result = provider.authenticate(token);
|
||||
assertNotNull(result);
|
||||
assertEquals(roles, AuthorityUtils.authorityListToSet(result.getAuthorities()));
|
||||
assertTrue(result.isAuthenticated());
|
||||
assertNotNull(result.getPrincipal());
|
||||
assertNotNull(result.getCredentials());
|
||||
assertNotNull(result.getDetails());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -84,13 +83,4 @@ public class KeycloakAuthenticationProviderTest {
|
||||
assertEquals(Sets.newSet("ROLE_USER", "ROLE_ADMIN"),
|
||||
AuthorityUtils.authorityListToSet(result.getAuthorities()));
|
||||
}
|
||||
|
||||
private void assertAuthenticationResult(Authentication result) {
|
||||
assertNotNull(result);
|
||||
assertEquals(roles, AuthorityUtils.authorityListToSet(result.getAuthorities()));
|
||||
assertTrue(result.isAuthenticated());
|
||||
assertNotNull(result.getPrincipal());
|
||||
assertNotNull(result.getCredentials());
|
||||
assertNotNull(result.getDetails());
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -28,7 +28,7 @@ public class SimpleHttpFacadeTest {
|
||||
Principal principal = mock(Principal.class);
|
||||
RefreshableKeycloakSecurityContext keycloakSecurityContext = mock(RefreshableKeycloakSecurityContext.class);
|
||||
KeycloakAccount account = new SimpleKeycloakAccount(principal, roles, keycloakSecurityContext);
|
||||
KeycloakAuthenticationToken token = new KeycloakAuthenticationToken(account, false);
|
||||
KeycloakAuthenticationToken token = new KeycloakAuthenticationToken(account);
|
||||
springSecurityContext.setAuthentication(token);
|
||||
}
|
||||
|
||||
|
||||
+32
-3
@@ -53,6 +53,7 @@ import java.util.UUID;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Mockito.any;
|
||||
import static org.mockito.Mockito.anyString;
|
||||
import static org.mockito.Mockito.eq;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.spy;
|
||||
@@ -123,6 +124,34 @@ public class KeycloakAuthenticationProcessingFilterTest {
|
||||
filter.afterPropertiesSet();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsBearerTokenRequest() throws Exception {
|
||||
assertFalse(filter.isBearerTokenRequest(request));
|
||||
this.setBearerAuthHeader(request);
|
||||
assertTrue(filter.isBearerTokenRequest(request));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsBearerTokenRequestCaseInsensitive() throws Exception {
|
||||
assertFalse(filter.isBearerTokenRequest(request));
|
||||
this.setAuthorizationHeader(request, "bearer");
|
||||
assertTrue(filter.isBearerTokenRequest(request));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsBasicAuthRequest() throws Exception {
|
||||
assertFalse(filter.isBasicAuthRequest(request));
|
||||
this.setBasicAuthHeader(request);
|
||||
assertTrue(filter.isBasicAuthRequest(request));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsBasicAuthRequestCaseInsensitive() throws Exception {
|
||||
assertFalse(filter.isBasicAuthRequest(request));
|
||||
this.setAuthorizationHeader(request, "basic");
|
||||
assertTrue(filter.isBasicAuthRequest(request));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAttemptAuthenticationExpectRedirect() throws Exception {
|
||||
when(keycloakDeployment.getAuthUrl()).thenReturn(KeycloakUriBuilder.fromUri("http://localhost:8080/auth"));
|
||||
@@ -151,7 +180,7 @@ public class KeycloakAuthenticationProcessingFilterTest {
|
||||
|
||||
@Test
|
||||
public void testSuccessfulAuthenticationInteractive() throws Exception {
|
||||
Authentication authentication = new KeycloakAuthenticationToken(keycloakAccount, true, authorities);
|
||||
Authentication authentication = new KeycloakAuthenticationToken(keycloakAccount, authorities);
|
||||
filter.successfulAuthentication(request, response, chain, authentication);
|
||||
|
||||
verify(successHandler).onAuthenticationSuccess(eq(request), eq(response), eq(authentication));
|
||||
@@ -160,7 +189,7 @@ public class KeycloakAuthenticationProcessingFilterTest {
|
||||
|
||||
@Test
|
||||
public void testSuccessfulAuthenticationBearer() throws Exception {
|
||||
Authentication authentication = new KeycloakAuthenticationToken(keycloakAccount, false, authorities);
|
||||
Authentication authentication = new KeycloakAuthenticationToken(keycloakAccount, authorities);
|
||||
this.setBearerAuthHeader(request);
|
||||
filter.successfulAuthentication(request, response, chain, authentication);
|
||||
|
||||
@@ -171,7 +200,7 @@ public class KeycloakAuthenticationProcessingFilterTest {
|
||||
|
||||
@Test
|
||||
public void testSuccessfulAuthenticationBasicAuth() throws Exception {
|
||||
Authentication authentication = new KeycloakAuthenticationToken(keycloakAccount, false, authorities);
|
||||
Authentication authentication = new KeycloakAuthenticationToken(keycloakAccount, authorities);
|
||||
this.setBasicAuthHeader(request);
|
||||
filter.successfulAuthentication(request, response, chain, authentication);
|
||||
|
||||
|
||||
-68
@@ -1,68 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.keycloak.adapters.springsecurity.filter;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
|
||||
public class QueryParamPresenceRequestMatcherTest {
|
||||
private static final String ROOT_CONTEXT_PATH = "";
|
||||
|
||||
private static final String VALID_PARAMETER = "access_token";
|
||||
|
||||
private QueryParamPresenceRequestMatcher matcher = new QueryParamPresenceRequestMatcher(VALID_PARAMETER);
|
||||
|
||||
private MockHttpServletRequest request;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
request = new MockHttpServletRequest();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDoesNotMatchWithoutQueryParameter() throws Exception {
|
||||
prepareRequest(HttpMethod.GET, ROOT_CONTEXT_PATH, "some/random/uri", Collections.EMPTY_MAP);
|
||||
assertFalse(matcher.matches(request));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMatchesWithValidParameter() throws Exception {
|
||||
prepareRequest(HttpMethod.GET, ROOT_CONTEXT_PATH, "some/random/uri", Collections.singletonMap(VALID_PARAMETER, (Object) "123"));
|
||||
assertTrue(matcher.matches(request));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDoesNotMatchWithInvalidParameter() throws Exception {
|
||||
prepareRequest(HttpMethod.GET, ROOT_CONTEXT_PATH, "some/random/uri", Collections.singletonMap("some_parameter", (Object) "123"));
|
||||
assertFalse(matcher.matches(request));
|
||||
}
|
||||
|
||||
private void prepareRequest(HttpMethod method, String contextPath, String uri, Map<String, Object> params) {
|
||||
request.setMethod(method.name());
|
||||
request.setContextPath(contextPath);
|
||||
request.setRequestURI(contextPath + "/" + uri);
|
||||
request.setParameters(params);
|
||||
}
|
||||
}
|
||||
@@ -20,7 +20,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>3.4.1.Final</version>
|
||||
<version>3.3.0.Final</version>
|
||||
<relativePath>../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<name>Keycloak Tomcat Integration</name>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-tomcat-integration-pom</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>3.4.1.Final</version>
|
||||
<version>3.3.0.Final</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
+6
-3
@@ -17,7 +17,11 @@
|
||||
|
||||
package org.keycloak.adapters.tomcat;
|
||||
|
||||
import org.apache.catalina.*;
|
||||
import org.apache.catalina.Context;
|
||||
import org.apache.catalina.Lifecycle;
|
||||
import org.apache.catalina.LifecycleEvent;
|
||||
import org.apache.catalina.LifecycleListener;
|
||||
import org.apache.catalina.Manager;
|
||||
import org.apache.catalina.authenticator.FormAuthenticator;
|
||||
import org.apache.catalina.connector.Request;
|
||||
import org.apache.catalina.connector.Response;
|
||||
@@ -132,7 +136,7 @@ public abstract class AbstractKeycloakAuthenticatorValve extends FormAuthenticat
|
||||
}
|
||||
|
||||
context.getServletContext().setAttribute(AdapterDeploymentContext.class.getName(), deploymentContext);
|
||||
AbstractAuthenticatedActionsValve actions = createAuthenticatedActionsValve(deploymentContext, getNext(), getContainer());
|
||||
AuthenticatedActionsValve actions = new AuthenticatedActionsValve(deploymentContext, getNext(), getContainer());
|
||||
setNext(actions);
|
||||
|
||||
nodesRegistrationManagement = new NodesRegistrationManagement();
|
||||
@@ -185,7 +189,6 @@ public abstract class AbstractKeycloakAuthenticatorValve extends FormAuthenticat
|
||||
|
||||
protected abstract GenericPrincipalFactory createPrincipalFactory();
|
||||
protected abstract boolean forwardToErrorPageInternal(Request request, HttpServletResponse response, Object loginConfig) throws IOException;
|
||||
protected abstract AbstractAuthenticatedActionsValve createAuthenticatedActionsValve(AdapterDeploymentContext deploymentContext, Valve next, Container container);
|
||||
|
||||
protected boolean authenticateInternal(Request request, HttpServletResponse response, Object loginConfig) throws IOException {
|
||||
CatalinaHttpFacade facade = new OIDCCatalinaHttpFacade(request, response);
|
||||
|
||||
+5
-4
@@ -31,7 +31,7 @@ import javax.servlet.ServletException;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Abstract base for pre-installed actions that must be authenticated
|
||||
* Pre-installed actions that must be authenticated
|
||||
* <p/>
|
||||
* Actions include:
|
||||
* <p/>
|
||||
@@ -41,17 +41,18 @@ import java.io.IOException;
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public abstract class AbstractAuthenticatedActionsValve extends ValveBase {
|
||||
private static final Logger log = Logger.getLogger(AbstractAuthenticatedActionsValve.class);
|
||||
public class AuthenticatedActionsValve extends ValveBase {
|
||||
private static final Logger log = Logger.getLogger(AuthenticatedActionsValve.class);
|
||||
protected AdapterDeploymentContext deploymentContext;
|
||||
|
||||
public AbstractAuthenticatedActionsValve(AdapterDeploymentContext deploymentContext, Valve next, Container container) {
|
||||
public AuthenticatedActionsValve(AdapterDeploymentContext deploymentContext, Valve next, Container container) {
|
||||
this.deploymentContext = deploymentContext;
|
||||
if (next == null) throw new RuntimeException("Next valve is null!!!");
|
||||
setNext(next);
|
||||
setContainer(container);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void invoke(Request request, Response response) throws IOException, ServletException {
|
||||
log.debugv("AuthenticatedActionsValve.invoke {0}", request.getRequestURI());
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-tomcat-integration-pom</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>3.4.1.Final</version>
|
||||
<version>3.3.0.Final</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
-12
@@ -1,12 +0,0 @@
|
||||
package org.keycloak.adapters.tomcat;
|
||||
|
||||
import org.apache.catalina.Container;
|
||||
import org.apache.catalina.Valve;
|
||||
import org.keycloak.adapters.AdapterDeploymentContext;
|
||||
|
||||
public class AuthenticatedActionsValve extends AbstractAuthenticatedActionsValve {
|
||||
|
||||
public AuthenticatedActionsValve(AdapterDeploymentContext deploymentContext, Valve next, Container container) {
|
||||
super(deploymentContext, next, container);
|
||||
}
|
||||
}
|
||||
-7
@@ -17,15 +17,12 @@
|
||||
|
||||
package org.keycloak.adapters.tomcat;
|
||||
|
||||
import org.apache.catalina.Container;
|
||||
import org.apache.catalina.LifecycleException;
|
||||
import org.apache.catalina.Valve;
|
||||
import org.apache.catalina.connector.Request;
|
||||
import org.apache.catalina.connector.Response;
|
||||
import org.apache.catalina.core.StandardContext;
|
||||
import org.apache.catalina.deploy.LoginConfig;
|
||||
import org.apache.catalina.realm.GenericPrincipal;
|
||||
import org.keycloak.adapters.AdapterDeploymentContext;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
@@ -54,10 +51,6 @@ public class KeycloakAuthenticatorValve extends AbstractKeycloakAuthenticatorVal
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AbstractAuthenticatedActionsValve createAuthenticatedActionsValve(AdapterDeploymentContext deploymentContext, Valve next, Container container) {
|
||||
return new AuthenticatedActionsValve(deploymentContext, next, container);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start() throws LifecycleException {
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-tomcat-integration-pom</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>3.4.1.Final</version>
|
||||
<version>3.3.0.Final</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
-17
@@ -1,17 +0,0 @@
|
||||
package org.keycloak.adapters.tomcat;
|
||||
|
||||
import org.apache.catalina.Container;
|
||||
import org.apache.catalina.Valve;
|
||||
import org.keycloak.adapters.AdapterDeploymentContext;
|
||||
|
||||
public class AuthenticatedActionsValve extends AbstractAuthenticatedActionsValve {
|
||||
|
||||
public AuthenticatedActionsValve(AdapterDeploymentContext deploymentContext, Valve next, Container container) {
|
||||
super(deploymentContext, next, container);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAsyncSupported() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
-8
@@ -17,14 +17,11 @@
|
||||
|
||||
package org.keycloak.adapters.tomcat;
|
||||
|
||||
import org.apache.catalina.Container;
|
||||
import org.apache.catalina.Valve;
|
||||
import org.apache.catalina.connector.Request;
|
||||
import org.apache.catalina.connector.Response;
|
||||
import org.apache.catalina.core.StandardContext;
|
||||
import org.apache.catalina.deploy.LoginConfig;
|
||||
import org.apache.catalina.realm.GenericPrincipal;
|
||||
import org.keycloak.adapters.AdapterDeploymentContext;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
@@ -72,9 +69,4 @@ public class KeycloakAuthenticatorValve extends AbstractKeycloakAuthenticatorVal
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AbstractAuthenticatedActionsValve createAuthenticatedActionsValve(AdapterDeploymentContext deploymentContext, Valve next, Container container) {
|
||||
return new AuthenticatedActionsValve(deploymentContext, next, container);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-tomcat-integration-pom</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>3.4.1.Final</version>
|
||||
<version>3.3.0.Final</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
-17
@@ -1,17 +0,0 @@
|
||||
package org.keycloak.adapters.tomcat;
|
||||
|
||||
import org.apache.catalina.Container;
|
||||
import org.apache.catalina.Valve;
|
||||
import org.keycloak.adapters.AdapterDeploymentContext;
|
||||
|
||||
public class AuthenticatedActionsValve extends AbstractAuthenticatedActionsValve {
|
||||
|
||||
public AuthenticatedActionsValve(AdapterDeploymentContext deploymentContext, Valve next, Container container) {
|
||||
super(deploymentContext, next, container);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAsyncSupported() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
-8
@@ -17,14 +17,11 @@
|
||||
|
||||
package org.keycloak.adapters.tomcat;
|
||||
|
||||
import org.apache.catalina.Container;
|
||||
import org.apache.catalina.Valve;
|
||||
import org.apache.catalina.authenticator.FormAuthenticator;
|
||||
import org.apache.catalina.connector.Request;
|
||||
import org.apache.catalina.core.StandardContext;
|
||||
import org.apache.catalina.realm.GenericPrincipal;
|
||||
import org.apache.tomcat.util.descriptor.web.LoginConfig;
|
||||
import org.keycloak.adapters.AdapterDeploymentContext;
|
||||
import org.keycloak.adapters.AdapterTokenStore;
|
||||
import org.keycloak.adapters.KeycloakDeployment;
|
||||
import org.keycloak.adapters.spi.HttpFacade;
|
||||
@@ -105,9 +102,4 @@ public class KeycloakAuthenticatorValve extends AbstractKeycloakAuthenticatorVal
|
||||
protected AdapterTokenStore getTokenStore(Request request, HttpFacade facade, KeycloakDeployment resolvedDeployment) {
|
||||
return super.getTokenStore(request, facade, resolvedDeployment);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AbstractAuthenticatedActionsValve createAuthenticatedActionsValve(AdapterDeploymentContext deploymentContext, Valve next, Container container) {
|
||||
return new AuthenticatedActionsValve(deploymentContext, next, container);
|
||||
}
|
||||
}
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>3.4.1.Final</version>
|
||||
<version>3.3.0.Final</version>
|
||||
<relativePath>../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>3.4.1.Final</version>
|
||||
<version>3.3.0.Final</version>
|
||||
<relativePath>../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
@@ -40,7 +40,7 @@
|
||||
<dependency>
|
||||
<groupId>org.wildfly.common</groupId>
|
||||
<artifactId>wildfly-common</artifactId>
|
||||
<scope>provided</scope>
|
||||
<version>1.2.0.Beta1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.wildfly.security</groupId>
|
||||
|
||||
+1
-1
@@ -53,7 +53,7 @@ public class ElytronSessionTokenStore implements ElytronTokeStore {
|
||||
@Override
|
||||
public void checkCurrentToken() {
|
||||
HttpScope session = httpFacade.getScope(Scope.SESSION);
|
||||
if (session == null || !session.exists()) return;
|
||||
if (!session.exists()) return;
|
||||
RefreshableKeycloakSecurityContext securityContext = (RefreshableKeycloakSecurityContext) session.getAttachment(KeycloakSecurityContext.class.getName());
|
||||
if (securityContext == null) return;
|
||||
|
||||
|
||||
+20
-25
@@ -42,40 +42,35 @@ import java.io.InputStream;
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
public class KeycloakConfigurationServletListener implements ServletContextListener {
|
||||
|
||||
static final String ADAPTER_DEPLOYMENT_CONTEXT_ATTRIBUTE = AdapterDeploymentContext.class.getName() + ".elytron";
|
||||
|
||||
@Override
|
||||
public void contextInitialized(ServletContextEvent sce) {
|
||||
ServletContext servletContext = sce.getServletContext();
|
||||
String configResolverClass = servletContext.getInitParameter("keycloak.config.resolver");
|
||||
KeycloakConfigResolver configResolver;
|
||||
AdapterDeploymentContext deploymentContext = (AdapterDeploymentContext) servletContext.getAttribute(AdapterDeploymentContext.class.getName());
|
||||
AdapterDeploymentContext deploymentContext;
|
||||
|
||||
if (deploymentContext == null) {
|
||||
if (configResolverClass != null) {
|
||||
try {
|
||||
configResolver = (KeycloakConfigResolver) servletContext.getClassLoader().loadClass(configResolverClass).newInstance();
|
||||
deploymentContext = new AdapterDeploymentContext(configResolver);
|
||||
} catch (Exception ex) {
|
||||
deploymentContext = new AdapterDeploymentContext(new KeycloakDeployment());
|
||||
}
|
||||
} else {
|
||||
InputStream is = getConfigInputStream(servletContext);
|
||||
|
||||
KeycloakDeployment deployment;
|
||||
|
||||
if (is == null) {
|
||||
deployment = new KeycloakDeployment();
|
||||
} else {
|
||||
deployment = KeycloakDeploymentBuilder.build(is);
|
||||
}
|
||||
|
||||
deploymentContext = new AdapterDeploymentContext(deployment);
|
||||
if (configResolverClass != null) {
|
||||
try {
|
||||
configResolver = (KeycloakConfigResolver) servletContext.getClassLoader().loadClass(configResolverClass).newInstance();
|
||||
deploymentContext = new AdapterDeploymentContext(configResolver);
|
||||
} catch (Exception ex) {
|
||||
deploymentContext = new AdapterDeploymentContext(new KeycloakDeployment());
|
||||
}
|
||||
} else {
|
||||
InputStream is = getConfigInputStream(servletContext);
|
||||
|
||||
KeycloakDeployment deployment;
|
||||
|
||||
if (is == null) {
|
||||
deployment = new KeycloakDeployment();
|
||||
} else {
|
||||
deployment = KeycloakDeploymentBuilder.build(is);
|
||||
}
|
||||
|
||||
deploymentContext = new AdapterDeploymentContext(deployment);
|
||||
}
|
||||
|
||||
servletContext.setAttribute(ADAPTER_DEPLOYMENT_CONTEXT_ATTRIBUTE, deploymentContext);
|
||||
servletContext.setAttribute(AdapterDeploymentContext.class.getName(), deploymentContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+2
-1
@@ -31,6 +31,7 @@ import org.keycloak.adapters.AuthenticatedActionsHandler;
|
||||
import org.keycloak.adapters.KeycloakDeployment;
|
||||
import org.keycloak.adapters.NodesRegistrationManagement;
|
||||
import org.keycloak.adapters.PreAuthActionsHandler;
|
||||
import org.keycloak.adapters.RefreshableKeycloakSecurityContext;
|
||||
import org.keycloak.adapters.RequestAuthenticator;
|
||||
import org.keycloak.adapters.spi.AuthChallenge;
|
||||
import org.keycloak.adapters.spi.AuthOutcome;
|
||||
@@ -126,7 +127,7 @@ class KeycloakHttpServerAuthenticationMechanism implements HttpServerAuthenticat
|
||||
|
||||
private AdapterDeploymentContext getDeploymentContext(HttpServerRequest request) {
|
||||
if (this.deploymentContext == null) {
|
||||
return (AdapterDeploymentContext) request.getScope(Scope.APPLICATION).getAttachment(KeycloakConfigurationServletListener.ADAPTER_DEPLOYMENT_CONTEXT_ATTRIBUTE);
|
||||
return (AdapterDeploymentContext) request.getScope(Scope.APPLICATION).getAttachment(AdapterDeploymentContext.class.getName());
|
||||
}
|
||||
|
||||
return this.deploymentContext;
|
||||
|
||||
+1
-4
@@ -30,10 +30,8 @@ import org.keycloak.KeycloakPrincipal;
|
||||
import org.keycloak.adapters.RefreshableKeycloakSecurityContext;
|
||||
import org.wildfly.security.auth.callback.AuthenticationCompleteCallback;
|
||||
import org.wildfly.security.auth.callback.EvidenceVerifyCallback;
|
||||
import org.wildfly.security.auth.callback.IdentityCredentialCallback;
|
||||
import org.wildfly.security.auth.callback.SecurityIdentityCallback;
|
||||
import org.wildfly.security.auth.server.SecurityIdentity;
|
||||
import org.wildfly.security.credential.BearerTokenCredential;
|
||||
import org.wildfly.security.evidence.Evidence;
|
||||
import org.wildfly.security.http.HttpAuthenticationException;
|
||||
|
||||
@@ -65,9 +63,8 @@ final class SecurityIdentityUtil {
|
||||
}
|
||||
|
||||
SecurityIdentityCallback securityIdentityCallback = new SecurityIdentityCallback();
|
||||
IdentityCredentialCallback credentialCallback = new IdentityCredentialCallback(new BearerTokenCredential(KeycloakPrincipal.class.cast(principal).getKeycloakSecurityContext().getTokenString()), true);
|
||||
|
||||
callbackHandler.handle(new Callback[]{credentialCallback, AuthenticationCompleteCallback.SUCCEEDED, securityIdentityCallback});
|
||||
callbackHandler.handle(new Callback[]{AuthenticationCompleteCallback.SUCCEEDED, securityIdentityCallback});
|
||||
|
||||
SecurityIdentity securityIdentity = securityIdentityCallback.getSecurityIdentity();
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>3.4.1.Final</version>
|
||||
<version>3.3.0.Final</version>
|
||||
<relativePath>../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<name>Keycloak WildFly Integration</name>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<version>3.4.1.Final</version>
|
||||
<version>3.3.0.Final</version>
|
||||
<relativePath>../../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>3.4.1.Final</version>
|
||||
<version>3.3.0.Final</version>
|
||||
<relativePath>../../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<version>3.4.1.Final</version>
|
||||
<version>3.3.0.Final</version>
|
||||
<relativePath>../../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
||||
+8
-4
@@ -71,10 +71,11 @@ public class KeycloakAdapterConfigDeploymentProcessor implements DeploymentUnitP
|
||||
KeycloakAdapterConfigService service = KeycloakAdapterConfigService.getInstance();
|
||||
if (service.isSecureDeployment(deploymentUnit) && service.isDeploymentConfigured(deploymentUnit)) {
|
||||
addKeycloakAuthData(phaseContext, service);
|
||||
} else if (service.isElytronEnabled(deploymentUnit)) {
|
||||
WarMetaData warMetaData = deploymentUnit.getAttachment(WarMetaData.ATTACHMENT_KEY);
|
||||
addConfigurationListener(warMetaData);
|
||||
}
|
||||
|
||||
addConfigurationListener(deploymentUnit);
|
||||
|
||||
// FYI, Undertow Extension will find deployments that have auth-method set to KEYCLOAK
|
||||
|
||||
// todo notsure if we need this
|
||||
@@ -103,6 +104,10 @@ public class KeycloakAdapterConfigDeploymentProcessor implements DeploymentUnitP
|
||||
loginConfig.setAuthMethod("KEYCLOAK");
|
||||
loginConfig.setRealmName(service.getRealmName(deploymentUnit));
|
||||
KeycloakLogger.ROOT_LOGGER.deploymentSecured(deploymentUnit.getName());
|
||||
|
||||
if (service.isElytronEnabled(deploymentUnit)) {
|
||||
addConfigurationListener(warMetaData);
|
||||
}
|
||||
}
|
||||
|
||||
private void addJSONData(String json, WarMetaData warMetaData) {
|
||||
@@ -125,8 +130,7 @@ public class KeycloakAdapterConfigDeploymentProcessor implements DeploymentUnitP
|
||||
webMetaData.setContextParams(contextParams);
|
||||
}
|
||||
|
||||
private void addConfigurationListener(DeploymentUnit deploymentUnit) {
|
||||
WarMetaData warMetaData = deploymentUnit.getAttachment(WarMetaData.ATTACHMENT_KEY);
|
||||
private void addConfigurationListener(WarMetaData warMetaData) {
|
||||
if (warMetaData == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
+5
-7
@@ -276,13 +276,11 @@ public final class KeycloakAdapterConfigService {
|
||||
}
|
||||
|
||||
private void setJSONValues(ModelNode json, ModelNode values) {
|
||||
synchronized (values) {
|
||||
for (Property prop : new ArrayList<>(values.asPropertyList())) {
|
||||
String name = prop.getName();
|
||||
ModelNode value = prop.getValue();
|
||||
if (value.isDefined()) {
|
||||
json.get(name).set(value);
|
||||
}
|
||||
for (Property prop : new ArrayList<>(values.asPropertyList())) {
|
||||
String name = prop.getName();
|
||||
ModelNode value = prop.getValue();
|
||||
if (value.isDefined()) {
|
||||
json.get(name).set(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-7
@@ -186,12 +186,7 @@ public class SharedAttributeDefinitons {
|
||||
.setDefaultValue(new ModelNode(false))
|
||||
.build();
|
||||
|
||||
protected static final SimpleAttributeDefinition CONFIDENTIAL_PORT =
|
||||
new SimpleAttributeDefinitionBuilder("confidential-port", ModelType.INT, true)
|
||||
.setXmlName("confidential-port")
|
||||
.setAllowExpression(true)
|
||||
.setDefaultValue(new ModelNode(8443))
|
||||
.build();
|
||||
|
||||
|
||||
|
||||
protected static final List<SimpleAttributeDefinition> ATTRIBUTES = new ArrayList<SimpleAttributeDefinition>();
|
||||
@@ -201,7 +196,6 @@ public class SharedAttributeDefinitons {
|
||||
ATTRIBUTES.add(TRUSTSTORE);
|
||||
ATTRIBUTES.add(TRUSTSTORE_PASSWORD);
|
||||
ATTRIBUTES.add(SSL_REQUIRED);
|
||||
ATTRIBUTES.add(CONFIDENTIAL_PORT);
|
||||
ATTRIBUTES.add(ALLOW_ANY_HOSTNAME);
|
||||
ATTRIBUTES.add(DISABLE_TRUST_MANAGER);
|
||||
ATTRIBUTES.add(CONNECTION_POOL_SIZE);
|
||||
|
||||
-3
@@ -30,7 +30,6 @@ keycloak.realm.realm-public-key=Public key of the realm
|
||||
keycloak.realm.auth-server-url=Base URL of the Realm Auth Server
|
||||
keycloak.realm.disable-trust-manager=Adapter will not use a trust manager when making adapter HTTPS requests
|
||||
keycloak.realm.ssl-required=Specify if SSL is required (valid values are all, external and none)
|
||||
keycloak.realm.confidential-port=Specify the confidential port (SSL/TLS) used by the Realm Auth Server
|
||||
keycloak.realm.allow-any-hostname=SSL Setting
|
||||
keycloak.realm.truststore=Truststore used for adapter client HTTPS requests
|
||||
keycloak.realm.truststore-password=Password of the Truststore
|
||||
@@ -61,7 +60,6 @@ keycloak.secure-deployment.realm-public-key=Public key of the realm
|
||||
keycloak.secure-deployment.auth-server-url=Base URL of the Realm Auth Server
|
||||
keycloak.secure-deployment.disable-trust-manager=Adapter will not use a trust manager when making adapter HTTPS requests
|
||||
keycloak.secure-deployment.ssl-required=Specify if SSL is required (valid values are all, external and none)
|
||||
keycloak.secure-deployment.confidential-port=Specify the confidential port (SSL/TLS) used by the Realm Auth Server
|
||||
keycloak.secure-deployment.allow-any-hostname=SSL Setting
|
||||
keycloak.secure-deployment.truststore=Truststore used for adapter client HTTPS requests
|
||||
keycloak.secure-deployment.truststore-password=Password of the Truststore
|
||||
@@ -102,7 +100,6 @@ keycloak.secure-server.realm-public-key=Public key of the realm
|
||||
keycloak.secure-server.auth-server-url=Base URL of the Realm Auth Server
|
||||
keycloak.secure-server.disable-trust-manager=Adapter will not use a trust manager when making adapter HTTPS requests
|
||||
keycloak.secure-server.ssl-required=Specify if SSL is required (valid values are all, external and none)
|
||||
keycloak.secure-server.confidential-port=Specify the confidential port (SSL/TLS) used by the Realm Auth Server
|
||||
keycloak.secure-server.allow-any-hostname=SSL Setting
|
||||
keycloak.secure-server.truststore=Truststore used for adapter client HTTPS requests
|
||||
keycloak.secure-server.truststore-password=Password of the Truststore
|
||||
|
||||
-2
@@ -58,7 +58,6 @@
|
||||
<xs:element name="expose-token" type="xs:boolean" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="disable-trust-manager" type="xs:boolean" minOccurs="0" maxOccurs="1" />
|
||||
<xs:element name="ssl-required" type="xs:string" minOccurs="0" maxOccurs="1" />
|
||||
<xs:element name="confidential-port" type="xs:integer" minOccurs="0" maxOccurs="1" />
|
||||
<xs:element name="cors-allowed-methods" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="cors-exposed-headers" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="realm-public-key" type="xs:string" minOccurs="1" maxOccurs="1"/>
|
||||
@@ -101,7 +100,6 @@
|
||||
<xs:element name="connection-pool-size" type="xs:integer" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="expose-token" type="xs:boolean" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="ssl-required" type="xs:string" minOccurs="0" maxOccurs="1" />
|
||||
<xs:element name="confidential-port" type="xs:integer" minOccurs="0" maxOccurs="1" />
|
||||
<xs:element name="realm-public-key" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="credential" type="credential-type" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="redirect-rewrite-rule" type="redirect-rewrite-rule-type" minOccurs="0" maxOccurs="1"/>
|
||||
|
||||
-1
@@ -51,7 +51,6 @@ public class SubsystemParsingTestCase extends AbstractSubsystemBaseTest {
|
||||
node.get("auth-url").set("http://localhost:8080/auth-server/rest/realms/demo/protocol/openid-connect/login");
|
||||
node.get("code-url").set("http://localhost:8080/auth-server/rest/realms/demo/protocol/openid-connect/access/codes");
|
||||
node.get("ssl-required").set("external");
|
||||
node.get("confidential-port").set(443);
|
||||
node.get("expose-token").set(true);
|
||||
|
||||
ModelNode jwtCredential = new ModelNode();
|
||||
|
||||
-4
@@ -22,7 +22,6 @@
|
||||
<truststore>truststore.jks</truststore>
|
||||
<truststore-password>secret</truststore-password>
|
||||
<ssl-required>EXTERNAL</ssl-required>
|
||||
<confidential-port>443</confidential-port>
|
||||
<allow-any-hostname>false</allow-any-hostname>
|
||||
<disable-trust-manager>true</disable-trust-manager>
|
||||
<connection-pool-size>20</connection-pool-size>
|
||||
@@ -57,7 +56,6 @@
|
||||
</realm-public-key>
|
||||
<auth-server-url>http://localhost:8080/auth</auth-server-url>
|
||||
<ssl-required>EXTERNAL</ssl-required>
|
||||
<confidential-port>443</confidential-port>
|
||||
<credential name="secret">0aa31d98-e0aa-404c-b6e0-e771dba1e798</credential>
|
||||
<redirect-rewrite-rule name="^/wsmaster/api/(.*)$">api/$1/</redirect-rewrite-rule>
|
||||
</secure-deployment>
|
||||
@@ -86,7 +84,5 @@
|
||||
<realm>jboss-infra</realm>
|
||||
<resource>wildfly-console</resource>
|
||||
<public-client>true</public-client>
|
||||
<ssl-required>EXTERNAL</ssl-required>
|
||||
<confidential-port>443</confidential-port>
|
||||
</secure-server>
|
||||
</subsystem>
|
||||
+1
-1
@@ -20,7 +20,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>3.4.1.Final</version>
|
||||
<version>3.3.0.Final</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<name>Keycloak Adapters</name>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-saml-eap-integration-pom</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>3.4.1.Final</version>
|
||||
<version>3.3.0.Final</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>3.4.1.Final</version>
|
||||
<version>3.3.0.Final</version>
|
||||
<relativePath>../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<name>Keycloak SAML EAP Integration</name>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-saml-eap-integration-pom</artifactId>
|
||||
<version>3.4.1.Final</version>
|
||||
<version>3.3.0.Final</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
||||
+2
-3
@@ -16,6 +16,7 @@
|
||||
*/
|
||||
package org.keycloak.subsystem.saml.as7;
|
||||
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:mstrukel@redhat.com">Marko Strukelj</a>
|
||||
*/
|
||||
@@ -45,8 +46,6 @@ public class Constants {
|
||||
static final String SIGN_REQUEST = "signRequest";
|
||||
static final String VALIDATE_RESPONSE_SIGNATURE = "validateResponseSignature";
|
||||
static final String VALIDATE_ASSERTION_SIGNATURE = "validateAssertionSignature";
|
||||
static final String ASSERTION_CONSUMER_SERVICE_URL = "assertionConsumerServiceUrl";
|
||||
|
||||
static final String REQUEST_BINDING = "requestBinding";
|
||||
static final String BINDING_URL = "bindingUrl";
|
||||
static final String VALIDATE_REQUEST_SIGNATURE = "validateRequestSignature";
|
||||
@@ -70,6 +69,7 @@ public class Constants {
|
||||
static final String SIGNATURES_REQUIRED = "signaturesRequired";
|
||||
}
|
||||
|
||||
|
||||
static class XML {
|
||||
static final String SECURE_DEPLOYMENT = "secure-deployment";
|
||||
static final String SERVICE_PROVIDER = "SP";
|
||||
@@ -122,6 +122,5 @@ public class Constants {
|
||||
static final String ALIAS = "alias";
|
||||
static final String FILE = "file";
|
||||
static final String SIGNATURES_REQUIRED = "signaturesRequired";
|
||||
static final String ASSERTION_CONSUMER_SERVICE_URL = "assertionConsumerServiceUrl";
|
||||
}
|
||||
}
|
||||
+1
-6
@@ -56,13 +56,8 @@ abstract class SingleSignOnDefinition {
|
||||
new SimpleAttributeDefinitionBuilder(Constants.Model.BINDING_URL, ModelType.STRING, true)
|
||||
.setXmlName(Constants.XML.BINDING_URL)
|
||||
.build();
|
||||
|
||||
static final SimpleAttributeDefinition ASSERTION_CONSUMER_SERVICE_URL =
|
||||
new SimpleAttributeDefinitionBuilder(Constants.Model.ASSERTION_CONSUMER_SERVICE_URL, ModelType.STRING, true)
|
||||
.setXmlName(Constants.XML.ASSERTION_CONSUMER_SERVICE_URL)
|
||||
.build();
|
||||
|
||||
static final SimpleAttributeDefinition[] ATTRIBUTES = {SIGN_REQUEST, VALIDATE_RESPONSE_SIGNATURE, VALIDATE_ASSERTION_SIGNATURE, REQUEST_BINDING, RESPONSE_BINDING, BINDING_URL, ASSERTION_CONSUMER_SERVICE_URL};
|
||||
static final SimpleAttributeDefinition[] ATTRIBUTES = {SIGN_REQUEST, VALIDATE_RESPONSE_SIGNATURE, VALIDATE_ASSERTION_SIGNATURE, REQUEST_BINDING, RESPONSE_BINDING, BINDING_URL};
|
||||
|
||||
static final HashMap<String, SimpleAttributeDefinition> ATTRIBUTE_MAP = new HashMap<>();
|
||||
|
||||
|
||||
-1
@@ -71,7 +71,6 @@ keycloak-saml.IDP.SingleSignOnService.validateAssertionSignature=Validate an SSO
|
||||
keycloak-saml.IDP.SingleSignOnService.requestBinding=HTTP method to use for requests
|
||||
keycloak-saml.IDP.SingleSignOnService.responseBinding=HTTP method to use for responses
|
||||
keycloak-saml.IDP.SingleSignOnService.bindingUrl=SSO endpoint URL
|
||||
keycloak-saml.IDP.SingleSignOnService.assertionConsumerServiceUrl=Endpoint of Assertion Consumer Service at SP
|
||||
keycloak-saml.IDP.SingleLogoutService=Single logout configuration
|
||||
keycloak-saml.IDP.SingleLogoutService.validateRequestSignature=Validate a SingleLogoutService request signature
|
||||
keycloak-saml.IDP.SingleLogoutService.validateResponseSignature=Validate a SingleLogoutService response signature
|
||||
|
||||
-5
@@ -152,11 +152,6 @@
|
||||
<xs:documentation>SSO endpoint URL</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="assertionConsumerServiceUrl" type="xs:string" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Endpoint of Assertion Consumer Service at SP</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
</xs:complexType>
|
||||
<xs:complexType name="single-logout-type">
|
||||
<xs:attribute name="validateRequestSignature" type="xs:boolean" use="optional">
|
||||
|
||||
+1
-2
@@ -44,8 +44,7 @@
|
||||
validateResponseSignature="true"
|
||||
validateAssertionSignature="true"
|
||||
requestBinding="POST"
|
||||
bindingUrl="http://localhost:8080/auth/realms/saml-demo/protocol/saml"
|
||||
assertionConsumerServiceUrl="acsUrl"/>
|
||||
bindingUrl="http://localhost:8080/auth/realms/saml-demo/protocol/saml"/>
|
||||
<SingleLogoutService
|
||||
validateRequestSignature="true"
|
||||
validateResponseSignature="true"
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>3.4.1.Final</version>
|
||||
<version>3.3.0.Final</version>
|
||||
<relativePath>../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>3.4.1.Final</version>
|
||||
<version>3.3.0.Final</version>
|
||||
<relativePath>../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
+1
-1
@@ -187,7 +187,7 @@ public abstract class AbstractSamlAuthenticationHandler implements SamlAuthentic
|
||||
final StatusResponseType statusResponse = (StatusResponseType) holder.getSamlObject();
|
||||
// validate destination
|
||||
if (!requestUri.equals(statusResponse.getDestination())) {
|
||||
log.error("Request URI '" + requestUri + "' does not match SAML request destination '" + statusResponse.getDestination() + "'");
|
||||
log.error("Request URI does not match SAML request destination");
|
||||
return AuthOutcome.FAILED;
|
||||
}
|
||||
|
||||
|
||||
Loaded 100 of 2108 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user