Merge pull request #2048 from stianst/KEYCLOAK-2286
KEYCLOAK-2286 Remove deprecated OpenID Connect endpoints
This commit is contained in:
commit
9d9ce6c04e
5 changed files with 3 additions and 257 deletions
|
@ -14,9 +14,7 @@ import org.keycloak.protocol.oidc.endpoints.AuthorizationEndpoint;
|
|||
import org.keycloak.protocol.oidc.endpoints.LoginStatusIframeEndpoint;
|
||||
import org.keycloak.protocol.oidc.endpoints.LogoutEndpoint;
|
||||
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.ValidateTokenEndpoint;
|
||||
import org.keycloak.protocol.oidc.representations.JSONWebKeySet;
|
||||
import org.keycloak.services.resources.RealmsResource;
|
||||
|
||||
|
@ -88,17 +86,6 @@ public class OIDCLoginProtocolService {
|
|||
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) {
|
||||
UriBuilder baseUriBuilder = uriInfo.getBaseUriBuilder();
|
||||
return logoutUrl(baseUriBuilder);
|
||||
|
@ -149,14 +136,6 @@ public class OIDCLoginProtocolService {
|
|||
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")
|
||||
public Object getLoginStatusIframe() {
|
||||
LoginStatusIframeEndpoint endpoint = new LoginStatusIframeEndpoint(realm);
|
||||
|
@ -164,45 +143,6 @@ public class OIDCLoginProtocolService {
|
|||
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
|
||||
@Path("certs")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
|
|
|
@ -60,8 +60,6 @@ public class AuthorizationEndpoint extends AuthorizationEndpointBase {
|
|||
private String nonce;
|
||||
private String idpHint;
|
||||
|
||||
private String legacyResponseType;
|
||||
|
||||
public AuthorizationEndpoint(RealmModel realm, EventBuilder event) {
|
||||
super(realm, event);
|
||||
event.event(EventType.LOGIN);
|
||||
|
@ -102,15 +100,6 @@ public class AuthorizationEndpoint extends AuthorizationEndpointBase {
|
|||
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() {
|
||||
event.event(EventType.REGISTER);
|
||||
action = Action.REGISTER;
|
||||
|
@ -181,12 +170,8 @@ public class AuthorizationEndpoint extends AuthorizationEndpointBase {
|
|||
|
||||
private void checkResponseType() {
|
||||
if (responseType == null) {
|
||||
if (legacyResponseType != null) {
|
||||
responseType = legacyResponseType;
|
||||
} else {
|
||||
event.error(Errors.INVALID_REQUEST);
|
||||
throw new ErrorPageException(session, Messages.MISSING_PARAMETER, OIDCLoginProtocol.RESPONSE_TYPE_PARAM);
|
||||
}
|
||||
event.error(Errors.INVALID_REQUEST);
|
||||
throw new ErrorPageException(session, Messages.MISSING_PARAMETER, OIDCLoginProtocol.RESPONSE_TYPE_PARAM);
|
||||
}
|
||||
|
||||
event.detail(Details.RESPONSE_TYPE, responseType);
|
||||
|
|
|
@ -83,8 +83,6 @@ public class TokenEndpoint {
|
|||
|
||||
private String grantType;
|
||||
|
||||
private String legacyGrantType;
|
||||
|
||||
public TokenEndpoint(TokenManager tokenManager, RealmModel realm, EventBuilder event) {
|
||||
this.tokenManager = tokenManager;
|
||||
this.realm = realm;
|
||||
|
@ -132,15 +130,6 @@ public class TokenEndpoint {
|
|||
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() {
|
||||
if (!uriInfo.getBaseUri().getScheme().equals("https") && realm.getSslRequired().isRequired(clientConnection)) {
|
||||
throw new ErrorResponseException("invalid_request", "HTTPS required", Response.Status.FORBIDDEN);
|
||||
|
@ -165,11 +154,7 @@ public class TokenEndpoint {
|
|||
|
||||
private void checkGrantType() {
|
||||
if (grantType == null) {
|
||||
if (legacyGrantType != null) {
|
||||
grantType = legacyGrantType;
|
||||
} else {
|
||||
throw new ErrorResponseException("invalid_request", "Missing form parameter: " + OIDCLoginProtocol.GRANT_TYPE_PARAM, Response.Status.BAD_REQUEST);
|
||||
}
|
||||
throw new ErrorResponseException("invalid_request", "Missing form parameter: " + OIDCLoginProtocol.GRANT_TYPE_PARAM, Response.Status.BAD_REQUEST);
|
||||
}
|
||||
|
||||
if (grantType.equals(OAuth2Constants.AUTHORIZATION_CODE)) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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
|
||||
public void testGrantAccessToken() throws Exception {
|
||||
Client client = ClientBuilder.newClient();
|
||||
|
|
Loading…
Reference in a new issue