KEYCLOAK-3217 UserInfo endpoint wasn't accessible by POST request secured with Bearer header

This commit is contained in:
mposolda 2016-07-07 12:28:25 +02:00
parent 2591dd862b
commit 7aafbcd5d9
2 changed files with 122 additions and 37 deletions

View file

@ -40,8 +40,6 @@ import org.keycloak.services.managers.AuthenticationManager;
import org.keycloak.services.resources.Cors; import org.keycloak.services.resources.Cors;
import org.keycloak.services.Urls; import org.keycloak.services.Urls;
import javax.ws.rs.Consumes;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET; import javax.ws.rs.GET;
import javax.ws.rs.OPTIONS; import javax.ws.rs.OPTIONS;
import javax.ws.rs.POST; import javax.ws.rs.POST;
@ -105,9 +103,17 @@ public class UserInfoEndpoint {
@Path("/") @Path("/")
@POST @POST
@NoCache @NoCache
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
public Response issueUserInfoPost(@FormParam("access_token") String accessToken) { public Response issueUserInfoPost() {
// Try header first
HttpHeaders headers = request.getHttpHeaders();
String accessToken = this.appAuthManager.extractAuthorizationHeaderToken(headers);
// Fallback to form parameter
if (accessToken == null) {
accessToken = request.getDecodedFormParameters().getFirst("access_token");
}
return issueUserInfo(accessToken); return issueUserInfo(accessToken);
} }

View file

@ -75,57 +75,120 @@ public class UserInfoTest extends AbstractKeycloakTest {
} }
@Test @Test
public void testSuccessfulUserInfoRequest() throws Exception { public void testSuccess_getMethod_bearer() throws Exception {
Client client = ClientBuilder.newClient(); Client client = ClientBuilder.newClient();
UriBuilder builder = UriBuilder.fromUri(AUTH_SERVER_ROOT);
URI grantUri = OIDCLoginProtocolService.tokenUrl(builder).build("test");
WebTarget grantTarget = client.target(grantUri);
AccessTokenResponse accessTokenResponse = executeGrantAccessTokenRequest(grantTarget);
Response response = executeUserInfoRequest(accessTokenResponse.getToken());
assertEquals(Status.OK.getStatusCode(), response.getStatus()); try {
AccessTokenResponse accessTokenResponse = executeGrantAccessTokenRequest(client);
Response response = executeUserInfoRequest_getMethod(client, accessTokenResponse.getToken());
UserInfo userInfo = response.readEntity(UserInfo.class); testSuccessfulUserInfoResponse(response);
response.close(); } finally {
client.close();
}
}
assertNotNull(userInfo); @Test
assertNotNull(userInfo.getSubject()); public void testSuccess_postMethod_bearer() throws Exception {
assertEquals("test-user@localhost", userInfo.getEmail()); Client client = ClientBuilder.newClient();
assertEquals("test-user@localhost", userInfo.getPreferredUsername());
client.close(); try {
AccessTokenResponse accessTokenResponse = executeGrantAccessTokenRequest(client);
WebTarget userInfoTarget = getUserInfoWebTarget(client);
Response response = userInfoTarget.request()
.header(HttpHeaders.AUTHORIZATION, "bearer " + accessTokenResponse.getToken())
.post(Entity.form(new Form()));
testSuccessfulUserInfoResponse(response);
} finally {
client.close();
}
}
@Test
public void testSuccess_postMethod_body() throws Exception {
Client client = ClientBuilder.newClient();
try {
AccessTokenResponse accessTokenResponse = executeGrantAccessTokenRequest(client);
Form form = new Form();
form.param("access_token", accessTokenResponse.getToken());
WebTarget userInfoTarget = getUserInfoWebTarget(client);
Response response = userInfoTarget.request()
.post(Entity.form(form));
testSuccessfulUserInfoResponse(response);
} finally {
client.close();
}
}
@Test
public void testSuccess_postMethod_bearer_textEntity() throws Exception {
Client client = ClientBuilder.newClient();
try {
AccessTokenResponse accessTokenResponse = executeGrantAccessTokenRequest(client);
WebTarget userInfoTarget = getUserInfoWebTarget(client);
Response response = userInfoTarget.request()
.header(HttpHeaders.AUTHORIZATION, "bearer " + accessTokenResponse.getToken())
.post(Entity.text(""));
testSuccessfulUserInfoResponse(response);
} finally {
client.close();
}
} }
@Test @Test
public void testSessionExpired() throws Exception { public void testSessionExpired() throws Exception {
Client client = ClientBuilder.newClient(); Client client = ClientBuilder.newClient();
UriBuilder builder = UriBuilder.fromUri(AUTH_SERVER_ROOT);
URI grantUri = OIDCLoginProtocolService.tokenUrl(builder).build("test");
WebTarget grantTarget = client.target(grantUri);
AccessTokenResponse accessTokenResponse = executeGrantAccessTokenRequest(grantTarget);
testingClient.testing().removeUserSessions("test"); try {
AccessTokenResponse accessTokenResponse = executeGrantAccessTokenRequest(client);
Response response = executeUserInfoRequest(accessTokenResponse.getToken()); testingClient.testing().removeUserSessions("test");
assertEquals(Status.FORBIDDEN.getStatusCode(), response.getStatus()); Response response = executeUserInfoRequest_getMethod(client, accessTokenResponse.getToken());
response.close(); assertEquals(Status.FORBIDDEN.getStatusCode(), response.getStatus());
client.close(); response.close();
} finally {
client.close();
}
} }
@Test @Test
public void testUnsuccessfulUserInfoRequest() throws Exception { public void testUnsuccessfulUserInfoRequest() throws Exception {
Response response = executeUserInfoRequest("bad"); Client client = ClientBuilder.newClient();
response.close(); try {
Response response = executeUserInfoRequest_getMethod(client, "bad");
assertEquals(Status.FORBIDDEN.getStatusCode(), response.getStatus()); response.close();
assertEquals(Status.FORBIDDEN.getStatusCode(), response.getStatus());
} finally {
client.close();
}
} }
private AccessTokenResponse executeGrantAccessTokenRequest(WebTarget grantTarget) { private AccessTokenResponse executeGrantAccessTokenRequest(Client client) {
UriBuilder builder = UriBuilder.fromUri(AUTH_SERVER_ROOT);
URI grantUri = OIDCLoginProtocolService.tokenUrl(builder).build("test");
WebTarget grantTarget = client.target(grantUri);
String header = BasicAuthHelper.createHeader("test-app", "password"); String header = BasicAuthHelper.createHeader("test-app", "password");
Form form = new Form(); Form form = new Form();
form.param(OAuth2Constants.GRANT_TYPE, OAuth2Constants.PASSWORD) form.param(OAuth2Constants.GRANT_TYPE, OAuth2Constants.PASSWORD)
@ -145,15 +208,31 @@ public class UserInfoTest extends AbstractKeycloakTest {
return accessTokenResponse; return accessTokenResponse;
} }
private Response executeUserInfoRequest(String accessToken) { private Response executeUserInfoRequest_getMethod(Client client, String accessToken) {
UriBuilder builder = UriBuilder.fromUri(AUTH_SERVER_ROOT); WebTarget userInfoTarget = getUserInfoWebTarget(client);
UriBuilder uriBuilder = OIDCLoginProtocolService.tokenServiceBaseUrl(builder);
URI userInfoUri = uriBuilder.path(OIDCLoginProtocolService.class, "issueUserInfo").build("test");
Client client = ClientBuilder.newClient();
WebTarget userInfoTarget = client.target(userInfoUri);
return userInfoTarget.request() return userInfoTarget.request()
.header(HttpHeaders.AUTHORIZATION, "bearer " + accessToken) .header(HttpHeaders.AUTHORIZATION, "bearer " + accessToken)
.get(); .get();
} }
private WebTarget getUserInfoWebTarget(Client client) {
UriBuilder builder = UriBuilder.fromUri(AUTH_SERVER_ROOT);
UriBuilder uriBuilder = OIDCLoginProtocolService.tokenServiceBaseUrl(builder);
URI userInfoUri = uriBuilder.path(OIDCLoginProtocolService.class, "issueUserInfo").build("test");
return client.target(userInfoUri);
}
private void testSuccessfulUserInfoResponse(Response response) {
assertEquals(Status.OK.getStatusCode(), response.getStatus());
UserInfo userInfo = response.readEntity(UserInfo.class);
response.close();
assertNotNull(userInfo);
assertNotNull(userInfo.getSubject());
assertEquals("test-user@localhost", userInfo.getEmail());
assertEquals("test-user@localhost", userInfo.getPreferredUsername());
}
} }