Merge pull request #2048 from stianst/KEYCLOAK-2286

KEYCLOAK-2286 Remove deprecated OpenID Connect endpoints
This commit is contained in:
Stian Thorgersen 2016-01-18 21:55:22 +01:00
commit 9d9ce6c04e
5 changed files with 3 additions and 257 deletions

View file

@ -14,9 +14,7 @@ import org.keycloak.protocol.oidc.endpoints.AuthorizationEndpoint;
import org.keycloak.protocol.oidc.endpoints.LoginStatusIframeEndpoint; import org.keycloak.protocol.oidc.endpoints.LoginStatusIframeEndpoint;
import org.keycloak.protocol.oidc.endpoints.LogoutEndpoint; import org.keycloak.protocol.oidc.endpoints.LogoutEndpoint;
import org.keycloak.protocol.oidc.endpoints.TokenEndpoint; import org.keycloak.protocol.oidc.endpoints.TokenEndpoint;
import org.keycloak.protocol.oidc.endpoints.TokenIntrospectionEndpoint;
import org.keycloak.protocol.oidc.endpoints.UserInfoEndpoint; import org.keycloak.protocol.oidc.endpoints.UserInfoEndpoint;
import org.keycloak.protocol.oidc.endpoints.ValidateTokenEndpoint;
import org.keycloak.protocol.oidc.representations.JSONWebKeySet; import org.keycloak.protocol.oidc.representations.JSONWebKeySet;
import org.keycloak.services.resources.RealmsResource; import org.keycloak.services.resources.RealmsResource;
@ -88,17 +86,6 @@ public class OIDCLoginProtocolService {
return tokenUrl(baseUriBuilder).path(TokenEndpoint.class, "introspect"); return tokenUrl(baseUriBuilder).path(TokenEndpoint.class, "introspect");
} }
/**
* @deprecated use {@link OIDCLoginProtocolService#tokenIntrospectionUrl(UriBuilder)} instead
* @param baseUriBuilder
* @return
*/
@Deprecated
public static UriBuilder validateAccessTokenUrl(UriBuilder baseUriBuilder) {
UriBuilder uriBuilder = tokenServiceBaseUrl(baseUriBuilder);
return uriBuilder.path(OIDCLoginProtocolService.class, "validateAccessToken");
}
public static UriBuilder logoutUrl(UriInfo uriInfo) { public static UriBuilder logoutUrl(UriInfo uriInfo) {
UriBuilder baseUriBuilder = uriInfo.getBaseUriBuilder(); UriBuilder baseUriBuilder = uriInfo.getBaseUriBuilder();
return logoutUrl(baseUriBuilder); return logoutUrl(baseUriBuilder);
@ -149,14 +136,6 @@ public class OIDCLoginProtocolService {
return endpoint; return endpoint;
} }
@Path("login")
@Deprecated
public Object loginPage() {
AuthorizationEndpoint endpoint = new AuthorizationEndpoint(realm, event);
ResteasyProviderFactory.getInstance().injectProperties(endpoint);
return endpoint.legacy(OIDCLoginProtocol.CODE_PARAM);
}
@Path("login-status-iframe.html") @Path("login-status-iframe.html")
public Object getLoginStatusIframe() { public Object getLoginStatusIframe() {
LoginStatusIframeEndpoint endpoint = new LoginStatusIframeEndpoint(realm); LoginStatusIframeEndpoint endpoint = new LoginStatusIframeEndpoint(realm);
@ -164,45 +143,6 @@ public class OIDCLoginProtocolService {
return endpoint; return endpoint;
} }
@Path("grants/access")
@Deprecated
public Object grantAccessToken() {
TokenEndpoint endpoint = new TokenEndpoint(tokenManager, realm, event);
ResteasyProviderFactory.getInstance().injectProperties(endpoint);
return endpoint.legacy(OAuth2Constants.PASSWORD);
}
@Path("refresh")
@Deprecated
public Object refreshAccessToken() {
TokenEndpoint endpoint = new TokenEndpoint(tokenManager, realm, event);
ResteasyProviderFactory.getInstance().injectProperties(endpoint);
return endpoint.legacy(OAuth2Constants.REFRESH_TOKEN);
}
@Path("access/codes")
@Deprecated
public Object accessCodeToToken() {
TokenEndpoint endpoint = new TokenEndpoint(tokenManager, realm, event);
ResteasyProviderFactory.getInstance().injectProperties(endpoint);
return endpoint.legacy(OAuth2Constants.AUTHORIZATION_CODE);
}
/**
* @deprecated use {@link TokenIntrospectionEndpoint#introspect()} instead
* @param tokenString
* @return
*/
@Path("validate")
@Deprecated
public Object validateAccessToken(@QueryParam("access_token") String tokenString) {
logger.warnv("Invoking deprecated endpoint {0}", uriInfo.getRequestUri());
ValidateTokenEndpoint endpoint = new ValidateTokenEndpoint(tokenManager, realm, event);
ResteasyProviderFactory.getInstance().injectProperties(endpoint);
return endpoint;
}
@GET @GET
@Path("certs") @Path("certs")
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)

View file

@ -60,8 +60,6 @@ public class AuthorizationEndpoint extends AuthorizationEndpointBase {
private String nonce; private String nonce;
private String idpHint; private String idpHint;
private String legacyResponseType;
public AuthorizationEndpoint(RealmModel realm, EventBuilder event) { public AuthorizationEndpoint(RealmModel realm, EventBuilder event) {
super(realm, event); super(realm, event);
event.event(EventType.LOGIN); event.event(EventType.LOGIN);
@ -102,15 +100,6 @@ public class AuthorizationEndpoint extends AuthorizationEndpointBase {
throw new RuntimeException("Unknown action " + action); throw new RuntimeException("Unknown action " + action);
} }
/**
* @deprecated
*/
public AuthorizationEndpoint legacy(String legacyResponseType) {
logger.warnv("Invoking deprecated endpoint {0}", uriInfo.getRequestUri());
this.legacyResponseType = legacyResponseType;
return this;
}
public AuthorizationEndpoint register() { public AuthorizationEndpoint register() {
event.event(EventType.REGISTER); event.event(EventType.REGISTER);
action = Action.REGISTER; action = Action.REGISTER;
@ -181,12 +170,8 @@ public class AuthorizationEndpoint extends AuthorizationEndpointBase {
private void checkResponseType() { private void checkResponseType() {
if (responseType == null) { if (responseType == null) {
if (legacyResponseType != null) { event.error(Errors.INVALID_REQUEST);
responseType = legacyResponseType; throw new ErrorPageException(session, Messages.MISSING_PARAMETER, OIDCLoginProtocol.RESPONSE_TYPE_PARAM);
} else {
event.error(Errors.INVALID_REQUEST);
throw new ErrorPageException(session, Messages.MISSING_PARAMETER, OIDCLoginProtocol.RESPONSE_TYPE_PARAM);
}
} }
event.detail(Details.RESPONSE_TYPE, responseType); event.detail(Details.RESPONSE_TYPE, responseType);

View file

@ -83,8 +83,6 @@ public class TokenEndpoint {
private String grantType; private String grantType;
private String legacyGrantType;
public TokenEndpoint(TokenManager tokenManager, RealmModel realm, EventBuilder event) { public TokenEndpoint(TokenManager tokenManager, RealmModel realm, EventBuilder event) {
this.tokenManager = tokenManager; this.tokenManager = tokenManager;
this.realm = realm; this.realm = realm;
@ -132,15 +130,6 @@ public class TokenEndpoint {
return Cors.add(request, Response.ok()).auth().preflight().build(); return Cors.add(request, Response.ok()).auth().preflight().build();
} }
/**
* @deprecated
*/
public TokenEndpoint legacy(String legacyGrantType) {
logger.warnv("Invoking deprecated endpoint {0}", uriInfo.getRequestUri());
this.legacyGrantType = legacyGrantType;
return this;
}
private void checkSsl() { private void checkSsl() {
if (!uriInfo.getBaseUri().getScheme().equals("https") && realm.getSslRequired().isRequired(clientConnection)) { if (!uriInfo.getBaseUri().getScheme().equals("https") && realm.getSslRequired().isRequired(clientConnection)) {
throw new ErrorResponseException("invalid_request", "HTTPS required", Response.Status.FORBIDDEN); throw new ErrorResponseException("invalid_request", "HTTPS required", Response.Status.FORBIDDEN);
@ -165,11 +154,7 @@ public class TokenEndpoint {
private void checkGrantType() { private void checkGrantType() {
if (grantType == null) { if (grantType == null) {
if (legacyGrantType != null) { throw new ErrorResponseException("invalid_request", "Missing form parameter: " + OIDCLoginProtocol.GRANT_TYPE_PARAM, Response.Status.BAD_REQUEST);
grantType = legacyGrantType;
} else {
throw new ErrorResponseException("invalid_request", "Missing form parameter: " + OIDCLoginProtocol.GRANT_TYPE_PARAM, Response.Status.BAD_REQUEST);
}
} }
if (grantType.equals(OAuth2Constants.AUTHORIZATION_CODE)) { if (grantType.equals(OAuth2Constants.AUTHORIZATION_CODE)) {

View file

@ -1,105 +0,0 @@
package org.keycloak.protocol.oidc.endpoints;
import org.jboss.logging.Logger;
import org.jboss.resteasy.annotations.cache.NoCache;
import org.keycloak.common.ClientConnection;
import org.keycloak.OAuth2Constants;
import org.keycloak.OAuthErrorException;
import org.keycloak.RSATokenVerifier;
import org.keycloak.events.Details;
import org.keycloak.events.Errors;
import org.keycloak.events.EventBuilder;
import org.keycloak.events.EventType;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.protocol.oidc.TokenManager;
import org.keycloak.representations.AccessToken;
import org.keycloak.services.ErrorResponseException;
import org.keycloak.services.Urls;
import javax.ws.rs.GET;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.*;
import java.util.HashMap;
import java.util.Map;
/**
* @deprecated use {@link TokenIntrospectionEndpoint} instead
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
@Deprecated
public class ValidateTokenEndpoint {
private static final Logger logger = Logger.getLogger(ValidateTokenEndpoint.class);
@Context
private KeycloakSession session;
@Context
private ClientConnection clientConnection;
@Context
private UriInfo uriInfo;
@Context
private HttpHeaders headers;
private TokenManager tokenManager;
private RealmModel realm;
private EventBuilder event;
public ValidateTokenEndpoint(TokenManager tokenManager, RealmModel realm, EventBuilder event) {
this.tokenManager = tokenManager;
this.realm = realm;
this.event = event;
}
/**
* Validate encoded access token.
*
* @param tokenString
* @return Unmarshalled token
*/
@GET
@NoCache
@Produces(MediaType.APPLICATION_JSON)
public Response validateAccessToken(@QueryParam("access_token") String tokenString) {
checkSsl();
event.event(EventType.VALIDATE_ACCESS_TOKEN);
AccessToken token = null;
try {
token = RSATokenVerifier.verifyToken(tokenString, realm.getPublicKey(), Urls.realmIssuer(uriInfo.getBaseUri(), realm.getName()));
} catch (Exception e) {
Map<String, String> err = new HashMap<String, String>();
err.put(OAuth2Constants.ERROR, OAuthErrorException.INVALID_GRANT);
err.put(OAuth2Constants.ERROR_DESCRIPTION, "Token invalid");
logger.error("Invalid token. Token verification failed.");
event.error(Errors.INVALID_TOKEN);
return Response.status(Response.Status.BAD_REQUEST).type(MediaType.APPLICATION_JSON_TYPE).entity(err)
.build();
}
event.user(token.getSubject()).session(token.getSessionState()).detail(Details.VALIDATE_ACCESS_TOKEN, token.getId());
try {
tokenManager.validateToken(session, uriInfo, clientConnection, realm, token, headers);
} catch (OAuthErrorException e) {
Map<String, String> error = new HashMap<String, String>();
error.put(OAuth2Constants.ERROR, e.getError());
if (e.getDescription() != null) error.put(OAuth2Constants.ERROR_DESCRIPTION, e.getDescription());
event.error(Errors.INVALID_TOKEN);
return Response.status(Response.Status.BAD_REQUEST).entity(error).type(MediaType.APPLICATION_JSON_TYPE).build();
}
event.success();
return Response.ok(token, MediaType.APPLICATION_JSON_TYPE).build();
}
private void checkSsl() {
if (!uriInfo.getBaseUri().getScheme().equals("https") && realm.getSslRequired().isRequired(clientConnection)) {
throw new ErrorResponseException("invalid_request", "HTTPS required", Response.Status.FORBIDDEN);
}
}
}

View file

@ -400,65 +400,6 @@ public class AccessTokenTest {
}); });
} }
@Test
public void testValidateAccessToken() throws Exception {
Client client = ClientBuilder.newClient();
UriBuilder builder = UriBuilder.fromUri(org.keycloak.testsuite.Constants.AUTH_SERVER_ROOT);
URI grantUri = OIDCLoginProtocolService.tokenUrl(builder).build("test");
WebTarget grantTarget = client.target(grantUri);
builder = UriBuilder.fromUri(org.keycloak.testsuite.Constants.AUTH_SERVER_ROOT);
URI validateUri = OIDCLoginProtocolService.validateAccessTokenUrl(builder).build("test");
WebTarget validateTarget = client.target(validateUri);
{
Response response = validateTarget.queryParam("access_token", "bad token").request().get();
Assert.assertEquals(400, response.getStatus());
HashMap<String, String> error = response.readEntity(new GenericType<HashMap<String, String>>() {
});
Assert.assertNotNull(error.get("error"));
}
org.keycloak.representations.AccessTokenResponse tokenResponse = null;
{
Response response = executeGrantAccessTokenRequest(grantTarget);
Assert.assertEquals(200, response.getStatus());
tokenResponse = response.readEntity(org.keycloak.representations.AccessTokenResponse.class);
response.close();
}
{
Response response = validateTarget.queryParam("access_token", tokenResponse.getToken()).request().get();
Assert.assertEquals(200, response.getStatus());
AccessToken token = response.readEntity(AccessToken.class);
Assert.assertNotNull(token);
response.close();
}
{
builder = UriBuilder.fromUri(org.keycloak.testsuite.Constants.AUTH_SERVER_ROOT);
URI logoutUri = OIDCLoginProtocolService.logoutUrl(builder).build("test");
String header = BasicAuthHelper.createHeader("test-app", "password");
Form form = new Form();
form.param("refresh_token", tokenResponse.getRefreshToken());
Response response = client.target(logoutUri).request()
.header(HttpHeaders.AUTHORIZATION, header)
.post(Entity.form(form));
Assert.assertEquals(204, response.getStatus());
response.close();
}
{
Response response = validateTarget.queryParam("access_token", tokenResponse.getToken()).request().get();
Assert.assertEquals(400, response.getStatus());
HashMap<String, String> error = response.readEntity(new GenericType<HashMap<String, String>>() {
});
Assert.assertNotNull(error.get("error"));
}
client.close();
events.clear();
}
@Test @Test
public void testGrantAccessToken() throws Exception { public void testGrantAccessToken() throws Exception {
Client client = ClientBuilder.newClient(); Client client = ClientBuilder.newClient();