Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Bill Burke 2016-07-20 11:01:01 -04:00
commit e719722e32
18 changed files with 436 additions and 35 deletions

View file

@ -35,7 +35,8 @@ public class OIDCAuthenticationError implements AuthenticationError {
CODE_TO_TOKEN_FAILURE,
INVALID_TOKEN,
STALE_TOKEN,
NO_AUTHORIZATION_HEADER
NO_AUTHORIZATION_HEADER,
NO_QUERY_PARAMETER_ACCESS_TOKEN
}
private Reason reason;

View file

@ -0,0 +1,54 @@
/*
* Copyright 2016 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;
import org.jboss.logging.Logger;
import org.keycloak.adapters.spi.AuthOutcome;
import org.keycloak.adapters.spi.HttpFacade;
/**
* @author <a href="mailto:froehlich.ch@gmail.com">Christian Froehlich</a>
* @version $Revision: 1 $
*/
public class QueryParamterTokenRequestAuthenticator extends BearerTokenRequestAuthenticator {
public static final String ACCESS_TOKEN = "access_token";
protected Logger log = Logger.getLogger(QueryParamterTokenRequestAuthenticator.class);
public QueryParamterTokenRequestAuthenticator(KeycloakDeployment deployment) {
super(deployment);
}
public AuthOutcome authenticate(HttpFacade exchange) {
tokenString = null;
tokenString = getAccessTokenFromQueryParamter(exchange);
if (tokenString == null || tokenString.trim().isEmpty()) {
challenge = challengeResponse(exchange, OIDCAuthenticationError.Reason.NO_QUERY_PARAMETER_ACCESS_TOKEN, null, null);
return AuthOutcome.NOT_ATTEMPTED;
}
return (authenticateToken(exchange, tokenString));
}
String getAccessTokenFromQueryParamter(HttpFacade exchange) {
try {
if (exchange != null && exchange.getRequest() != null) {
return exchange.getRequest().getQueryParamValue(ACCESS_TOKEN);
}
} catch (Exception ignore) {
}
return null;
}
}

View file

@ -61,7 +61,7 @@ public abstract class RequestAuthenticator {
if (log.isTraceEnabled()) {
log.trace("try bearer");
}
AuthOutcome outcome = bearer.authenticate(facade);
if (outcome == AuthOutcome.FAILED) {
challenge = bearer.getChallenge();
@ -74,18 +74,36 @@ public abstract class RequestAuthenticator {
return AuthOutcome.AUTHENTICATED;
}
QueryParamterTokenRequestAuthenticator queryParamAuth = createQueryParamterTokenRequestAuthenticator();
if (log.isTraceEnabled()) {
log.trace("try query paramter auth");
}
outcome = queryParamAuth.authenticate(facade);
if (outcome == AuthOutcome.FAILED) {
challenge = queryParamAuth.getChallenge();
log.debug("QueryParamAuth auth FAILED");
return AuthOutcome.FAILED;
} else if (outcome == AuthOutcome.AUTHENTICATED) {
if (verifySSL()) return AuthOutcome.FAILED;
log.debug("QueryParamAuth AUTHENTICATED");
completeAuthentication(queryParamAuth, "KEYCLOAK");
return AuthOutcome.AUTHENTICATED;
}
if (deployment.isEnableBasicAuth()) {
BasicAuthRequestAuthenticator basicAuth = createBasicAuthAuthenticator();
if (log.isTraceEnabled()) {
log.trace("try basic auth");
}
outcome = basicAuth.authenticate(facade);
if (outcome == AuthOutcome.FAILED) {
challenge = basicAuth.getChallenge();
log.debug("BasicAuth FAILED");
return AuthOutcome.FAILED;
} else if (outcome == AuthOutcome.AUTHENTICATED) {
if (verifySSL()) return AuthOutcome.FAILED;
log.debug("BasicAuth AUTHENTICATED");
completeAuthentication(basicAuth, "BASIC");
return AuthOutcome.AUTHENTICATED;
@ -150,6 +168,10 @@ public abstract class RequestAuthenticator {
return new BasicAuthRequestAuthenticator(deployment);
}
protected QueryParamterTokenRequestAuthenticator createQueryParamterTokenRequestAuthenticator() {
return new QueryParamterTokenRequestAuthenticator(deployment);
}
protected void completeAuthentication(OAuthRequestAuthenticator oauth) {
RefreshableKeycloakSecurityContext session = new RefreshableKeycloakSecurityContext(deployment, tokenStore, oauth.getTokenString(), oauth.getToken(), oauth.getIdTokenString(), oauth.getIdToken(), oauth.getRefreshToken());
final KeycloakPrincipal<RefreshableKeycloakSecurityContext> principal = new KeycloakPrincipal<RefreshableKeycloakSecurityContext>(AdapterUtils.getPrincipalName(deployment, oauth.getToken()), session);
@ -158,10 +180,12 @@ public abstract class RequestAuthenticator {
}
protected abstract void completeOAuthAuthentication(KeycloakPrincipal<RefreshableKeycloakSecurityContext> principal);
protected abstract void completeBearerAuthentication(KeycloakPrincipal<RefreshableKeycloakSecurityContext> principal, String method);
/**
* After code is received, we change the session id if possible to guard against https://www.owasp.org/index.php/Session_Fixation
*
* @param create
* @return
*/

View file

@ -88,6 +88,24 @@
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.undertow</groupId>
<artifactId>undertow-servlet</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.undertow</groupId>
<artifactId>undertow-core</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-undertow-adapter-spi</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>

View file

@ -17,6 +17,8 @@
package org.keycloak.adapters.springboot;
import io.undertow.servlet.api.DeploymentInfo;
import io.undertow.servlet.api.WebResourceCollection;
import org.apache.catalina.Context;
import org.apache.tomcat.util.descriptor.web.LoginConfig;
import org.apache.tomcat.util.descriptor.web.SecurityCollection;
@ -28,6 +30,7 @@ import org.eclipse.jetty.util.security.Constraint;
import org.eclipse.jetty.webapp.WebAppContext;
import org.keycloak.adapters.jetty.KeycloakJettyAuthenticator;
import org.keycloak.adapters.tomcat.KeycloakAuthenticatorValve;
import org.keycloak.adapters.undertow.KeycloakServletExtension;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
@ -108,7 +111,53 @@ public class KeycloakSpringBootConfiguration {
@Bean
@ConditionalOnClass(name = {"io.undertow.Undertow"})
public UndertowDeploymentInfoCustomizer undertowKeycloakContextCustomizer() {
throw new IllegalArgumentException("Undertow Keycloak integration is not yet implemented");
return new KeycloakUndertowDeploymentInfoCustomizer(keycloakProperties);
}
static class KeycloakUndertowDeploymentInfoCustomizer implements UndertowDeploymentInfoCustomizer {
private final KeycloakSpringBootProperties keycloakProperties;
public KeycloakUndertowDeploymentInfoCustomizer(KeycloakSpringBootProperties keycloakProperties) {
this.keycloakProperties = keycloakProperties;
}
@Override
public void customize(DeploymentInfo deploymentInfo) {
io.undertow.servlet.api.LoginConfig loginConfig = new io.undertow.servlet.api.LoginConfig(keycloakProperties.getRealm());
loginConfig.addFirstAuthMethod("KEYCLOAK");
deploymentInfo.setLoginConfig(loginConfig);
deploymentInfo.addInitParameter("keycloak.config.resolver", KeycloakSpringBootConfigResolver.class.getName());
deploymentInfo.addSecurityConstraints(getSecurityConstraints());
deploymentInfo.addServletExtension(new KeycloakServletExtension());
}
private List<io.undertow.servlet.api.SecurityConstraint> getSecurityConstraints() {
List<io.undertow.servlet.api.SecurityConstraint> undertowSecurityConstraints = new ArrayList<io.undertow.servlet.api.SecurityConstraint>();
for (KeycloakSpringBootProperties.SecurityConstraint constraintDefinition : keycloakProperties.getSecurityConstraints()) {
for (KeycloakSpringBootProperties.SecurityCollection collectionDefinition : constraintDefinition.getSecurityCollections()) {
io.undertow.servlet.api.SecurityConstraint undertowSecurityConstraint = new io.undertow.servlet.api.SecurityConstraint();
undertowSecurityConstraint.addRolesAllowed(collectionDefinition.getAuthRoles());
WebResourceCollection webResourceCollection = new WebResourceCollection();
webResourceCollection.addHttpMethods(collectionDefinition.getMethods());
webResourceCollection.addHttpMethodOmissions(collectionDefinition.getOmittedMethods());
webResourceCollection.addUrlPatterns(collectionDefinition.getPatterns());
undertowSecurityConstraint.addWebResourceCollections(webResourceCollection);
undertowSecurityConstraints.add(undertowSecurityConstraint);
}
}
return undertowSecurityConstraints;
}
}
static class KeycloakJettyServerCustomizer implements JettyServerCustomizer {

View file

@ -22,7 +22,7 @@ Step 2: Deploy and run the example
curl http://admin:password@localhost:8080/basicauth/service/echo?value=hello
(If we navigate directly to http://localhost:8080/basicauth/service/echo?value=hello, we get "Client is not allowed to initiate browser login with given response_type. Standard flow is disabled for the client.").
(If we navigate directly to http://localhost:8080/basicauth/service/echo?value=hello, we get an error in the browser because the request is not authenticated).
This should result in the value 'hello' being returned as a response.

View file

@ -244,16 +244,23 @@ public class TokenManager {
}
public RefreshToken verifyRefreshToken(RealmModel realm, String encodedRefreshToken) throws OAuthErrorException {
return verifyRefreshToken(realm, encodedRefreshToken, true);
}
public RefreshToken verifyRefreshToken(RealmModel realm, String encodedRefreshToken, boolean checkExpiration) throws OAuthErrorException {
try {
RefreshToken refreshToken = toRefreshToken(realm, encodedRefreshToken);
if (refreshToken.getExpiration() != 0 && refreshToken.isExpired()) {
throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Refresh token expired");
if (checkExpiration) {
if (refreshToken.getExpiration() != 0 && refreshToken.isExpired()) {
throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Refresh token expired");
}
if (refreshToken.getIssuedAt() < realm.getNotBefore()) {
throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Stale refresh token");
}
}
if (refreshToken.getIssuedAt() < realm.getNotBefore()) {
throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Stale refresh token");
}
return refreshToken;
} catch (JWSInputException e) {
throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Invalid refresh token", e);

View file

@ -187,7 +187,7 @@ public class LogoutEndpoint {
throw new ErrorResponseException(OAuthErrorException.INVALID_REQUEST, "No refresh token", Response.Status.BAD_REQUEST);
}
try {
RefreshToken token = tokenManager.verifyRefreshToken(realm, refreshToken);
RefreshToken token = tokenManager.verifyRefreshToken(realm, refreshToken, false);
UserSessionModel userSessionModel = session.sessions().getUserSession(realm, token.getSessionState());
if (userSessionModel != null) {
logout(userSessionModel);

View file

@ -0,0 +1,7 @@
set NOPAUSE=true
call %JBOSS_HOME%\bin\jboss-cli.bat --command="patch apply %PATCH_ZIP%"
if %ERRORLEVEL% neq 0 set ERROR=%ERRORLEVEL%
exit /b %ERROR%

View file

@ -0,0 +1,17 @@
#!/bin/bash
echo "JBOSS_HOME=$JBOSS_HOME"
if [ ! -d "$JBOSS_HOME/bin" ] ; then
>&2 echo "JBOSS_HOME/bin doesn't exist"
exit 1
fi
cd $JBOSS_HOME/bin
RESULT=0
./jboss-cli.sh --command="patch apply $PATCH_ZIP"
if [ $? -ne 0 ]; then RESULT=1; fi
exit $RESULT
fi
exit 1

View file

@ -292,6 +292,10 @@
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
@ -587,7 +591,42 @@
</pluginManagement>
</build>
</profile>
<profile>
<id>auth-server-apply-patch</id>
<activation>
<property>
<name>auth.server.patch.zip</name>
</property>
</activation>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<executions>
<execution>
<id>install-patch</id>
<phase>process-resources</phase>
<goals>
<goal>exec</goal>
</goals>
</execution>
</executions>
<configuration>
<executable>${common.resources}/install-patch.${script.suffix}</executable>
<workingDirectory>${auth.server.home}/bin</workingDirectory>
<environmentVariables>
<JAVA_HOME>${auth.server.java.home}</JAVA_HOME>
<JBOSS_HOME>${auth.server.home}</JBOSS_HOME>
<PATCH_ZIP>${auth.server.patch.zip}</PATCH_ZIP>
</environmentVariables>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
</profile>
<profile>
<id>auth-server-cluster</id>
<properties>

View file

@ -253,7 +253,7 @@ public abstract class AbstractSAMLServletsAdapterTest extends AbstractServletsAd
@Test
public void badClientSalesPostSigTest() {
badClientSalesPostSigServletPage.navigateTo();
waitUntilElement(By.xpath("//body")).text().contains("invalidRequesterMessage");
waitUntilElement(By.xpath("//body")).text().contains("Invalid requester");
}
@Test

View file

@ -0,0 +1,100 @@
/*
* Copyright 2016 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.testsuite.oauth;
import org.apache.http.HttpResponse;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.keycloak.OAuth2Constants;
import org.keycloak.common.util.Time;
import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.testsuite.AbstractKeycloakTest;
import org.keycloak.testsuite.AssertEvents;
import org.keycloak.testsuite.util.ClientManager;
import org.keycloak.testsuite.util.OAuthClient;
import org.keycloak.testsuite.util.RealmBuilder;
import java.util.List;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.keycloak.testsuite.admin.AbstractAdminTest.loadJson;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public class LogoutTest extends AbstractKeycloakTest {
@Rule
public AssertEvents events = new AssertEvents(this);
@Override
public void beforeAbstractKeycloakTest() throws Exception {
super.beforeAbstractKeycloakTest();
}
@Before
public void clientConfiguration() {
ClientManager.realm(adminClient.realm("test")).clientId("test-app").directAccessGrant(true);
}
@Override
public void addTestRealms(List<RealmRepresentation> testRealms) {
RealmRepresentation realmRepresentation = loadJson(getClass().getResourceAsStream("/testrealm.json"), RealmRepresentation.class);
RealmBuilder realm = RealmBuilder.edit(realmRepresentation).testEventListener();
testRealms.add(realm.build());
}
@Test
public void postLogout() throws Exception {
oauth.doLogin("test-user@localhost", "password");
String code = oauth.getCurrentQuery().get(OAuth2Constants.CODE);
oauth.clientSessionState("client-session");
OAuthClient.AccessTokenResponse tokenResponse = oauth.doAccessTokenRequest(code, "password");
String refreshTokenString = tokenResponse.getRefreshToken();
HttpResponse response = oauth.doLogout(refreshTokenString, "password");
assertEquals(204, response.getStatusLine().getStatusCode());
assertNotNull(testingClient.testApp().getAdminLogoutAction());
}
@Test
public void postLogoutExpiredRefreshToken() throws Exception {
oauth.doLogin("test-user@localhost", "password");
String code = oauth.getCurrentQuery().get(OAuth2Constants.CODE);
oauth.clientSessionState("client-session");
OAuthClient.AccessTokenResponse tokenResponse = oauth.doAccessTokenRequest(code, "password");
String refreshTokenString = tokenResponse.getRefreshToken();
adminClient.realm("test").update(RealmBuilder.create().notBefore(Time.currentTime() + 1).build());
// Logout should succeed with expired refresh token, see KEYCLOAK-3302
HttpResponse response = oauth.doLogout(refreshTokenString, "password");
assertEquals(204, response.getStatusLine().getStatusCode());
assertNotNull(testingClient.testApp().getAdminLogoutAction());
}
}

View file

@ -132,6 +132,11 @@ public class RealmBuilder {
return this;
}
public RealmBuilder notBefore(int i) {
rep.setNotBefore(i);
return this;
}
public RealmBuilder otpLookAheadWindow(int i) {
rep.setOtpPolicyLookAheadWindow(i);
return this;

View file

@ -105,7 +105,7 @@
"redirectUris": [
"http://localhost:8180/auth/realms/master/app/auth/*"
],
"adminUrl": "http://localhost:8180/auth/realms/master/app/logout",
"adminUrl": "http://localhost:8180/auth/realms/master/app/admin",
"secret": "password"
},
{

View file

@ -203,4 +203,17 @@ public class AdapterTest {
testStrategy.testAccountManagementSessionsLogout();
}
/**
* KEYCLOAK-1733
*/
@Test
public void testNullQueryParameterAccessToken() throws Exception {
testStrategy.testNullQueryParameterAccessToken();
}
@Test
public void testRestCallWithAccessTokenAsQueryParameter() throws Exception {
testStrategy.testRestCallWithAccessTokenAsQueryParameter();
}
}

View file

@ -17,34 +17,29 @@
package org.keycloak.testsuite.adapter;
import org.apache.http.conn.params.ConnManagerParams;
import org.json.JSONException;
import org.json.JSONObject;
import org.junit.Assert;
import org.junit.rules.ExternalResource;
import org.keycloak.OAuth2Constants;
import org.keycloak.adapters.OIDCAuthenticationError;
import org.keycloak.common.Version;
import org.keycloak.representations.VersionRepresentation;
import org.keycloak.admin.client.Keycloak;
import org.keycloak.common.Version;
import org.keycloak.common.util.Time;
import org.keycloak.constants.AdapterConstants;
import org.keycloak.models.ClientModel;
import org.keycloak.models.Constants;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.*;
import org.keycloak.protocol.oidc.OIDCLoginProtocolService;
import org.keycloak.representations.VersionRepresentation;
import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.representations.idm.UserRepresentation;
import org.keycloak.services.managers.RealmManager;
import org.keycloak.services.managers.ResourceAdminManager;
import org.keycloak.testsuite.KeycloakServer;
import org.keycloak.testsuite.OAuthClient;
import org.keycloak.testsuite.pages.AccountSessionsPage;
import org.keycloak.testsuite.pages.LoginPage;
import org.keycloak.testsuite.rule.AbstractKeycloakRule;
import org.keycloak.testsuite.rule.ErrorServlet;
import org.keycloak.testsuite.rule.KeycloakRule;
import org.keycloak.testsuite.rule.WebResource;
import org.keycloak.testsuite.rule.WebRule;
import org.keycloak.testsuite.KeycloakServer;
import org.keycloak.testsuite.rule.*;
import org.keycloak.util.BasicAuthHelper;
import org.keycloak.common.util.Time;
import org.openqa.selenium.WebDriver;
import javax.ws.rs.client.Client;
@ -59,7 +54,6 @@ import java.net.URI;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import org.keycloak.representations.idm.UserRepresentation;
/**
* Tests Undertow Adapter
@ -144,7 +138,8 @@ public class AdapterTestStrategy extends ExternalResource {
System.out.println("insecure: ");
System.out.println(driver.getPageSource());
Assert.assertTrue(driver.getPageSource().contains("Insecure Page"));
if (System.getProperty("insecure.user.principal.unsupported") == null) Assert.assertTrue(driver.getPageSource().contains("UserPrincipal"));
if (System.getProperty("insecure.user.principal.unsupported") == null)
Assert.assertTrue(driver.getPageSource().contains("UserPrincipal"));
// test logout
@ -384,6 +379,26 @@ public class AdapterTestStrategy extends ExternalResource {
}
/**
* KEYCLOAK-1733
*
* @throws Exception
*/
public void testNullQueryParameterAccessToken() throws Exception {
Client client = ClientBuilder.newClient();
WebTarget target = client.target(APP_SERVER_BASE_URL + "/customer-db/");
Response response = target.request().get();
Assert.assertEquals(401, response.getStatus());
response.close();
target = client.target(APP_SERVER_BASE_URL + "/customer-db?access_token=");
response = target.request().get();
Assert.assertEquals(401, response.getStatus());
response.close();
client.close();
}
/**
* KEYCLOAK-1368
* @throws Exception
@ -406,7 +421,7 @@ public class AdapterTestStrategy extends ExternalResource {
Assert.assertTrue(errorPageResponse.contains("Error Page"));
response.close();
Assert.assertNotNull(ErrorServlet.authError);
OIDCAuthenticationError error = (OIDCAuthenticationError)ErrorServlet.authError;
OIDCAuthenticationError error = (OIDCAuthenticationError) ErrorServlet.authError;
Assert.assertEquals(OIDCAuthenticationError.Reason.NO_BEARER_TOKEN, error.getReason());
ErrorServlet.authError = null;
@ -422,7 +437,7 @@ public class AdapterTestStrategy extends ExternalResource {
Assert.assertTrue(errorPageResponse.contains("Error Page"));
response.close();
Assert.assertNotNull(ErrorServlet.authError);
error = (OIDCAuthenticationError)ErrorServlet.authError;
error = (OIDCAuthenticationError) ErrorServlet.authError;
Assert.assertEquals(OIDCAuthenticationError.Reason.INVALID_TOKEN, error.getReason());
client.close();
@ -464,8 +479,8 @@ public class AdapterTestStrategy extends ExternalResource {
String header = BasicAuthHelper.createHeader("customer-portal", "password");
Form form = new Form();
form.param(OAuth2Constants.GRANT_TYPE, OAuth2Constants.PASSWORD)
.param("username", "monkey@redhat.com")
.param("password", "password");
.param("username", "monkey@redhat.com")
.param("password", "password");
Response response = target.request()
.header(HttpHeaders.AUTHORIZATION, header)
.post(Entity.form(form));
@ -496,7 +511,6 @@ public class AdapterTestStrategy extends ExternalResource {
}
public void testAuthenticated() throws Exception {
// test login to customer-portal which does a bearer request to customer-db
driver.navigate().to(APP_SERVER_BASE_URL + "/secure-portal");
@ -521,6 +535,53 @@ public class AdapterTestStrategy extends ExternalResource {
Assert.assertTrue(driver.getCurrentUrl().startsWith(LOGIN_URL));
}
/**
* KEYCLOAK-1733
*
* @throws Exception
*/
public void testRestCallWithAccessTokenAsQueryParameter() throws Exception {
String accessToken = getAccessToken();
Client client = ClientBuilder.newClient();
try {
// test without token
Response response = client.target(APP_SERVER_BASE_URL + "/customer-db").request().get();
Assert.assertEquals(401, response.getStatus());
response.close();
// test with access_token as QueryParamter
response = client.target(APP_SERVER_BASE_URL + "/customer-db").queryParam("access_token", accessToken).request().get();
Assert.assertEquals(200, response.getStatus());
response.close();
} finally {
client.close();
}
}
private String getAccessToken() throws JSONException {
String tokenUrl = AUTH_SERVER_URL + "/realms/demo/protocol/openid-connect/token";
Client client = ClientBuilder.newClient();
try {
WebTarget webTarget = client.target(tokenUrl);
Form form = new Form();
form.param("grant_type", "password");
form.param("client_id", "customer-portal-public");
form.param("username", "bburke@redhat.com");
form.param("password", "password");
Response response = webTarget.request().post(Entity.form(form));
Assert.assertEquals(200, response.getStatus());
JSONObject jsonObject = new JSONObject(response.readEntity(String.class));
System.out.println(jsonObject);
response.close();
return jsonObject.getString("access_token");
} finally {
client.close();
}
}
/**
* KEYCLOAK-732
*

View file

@ -156,6 +156,12 @@
"http://localhost"
]
},
{
"name": "customer-portal-public",
"enabled": true,
"publicClient": true,
"directAccessGrantsEnabled": true
},
{
"name": "product-portal",
"enabled": true,