From c25988fc8f9ab343d7aa8b0f3421ba6a4ba43b71 Mon Sep 17 00:00:00 2001 From: "Brian M. Long" Date: Tue, 30 May 2023 18:23:39 -0400 Subject: [PATCH 1/4] removing errand enum enablement --- src/main/java/com/inteligr8/rs/Client.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/main/java/com/inteligr8/rs/Client.java b/src/main/java/com/inteligr8/rs/Client.java index 1700d99..2da7a6e 100644 --- a/src/main/java/com/inteligr8/rs/Client.java +++ b/src/main/java/com/inteligr8/rs/Client.java @@ -72,9 +72,6 @@ public abstract class Client { this.getConfig().configureJacksonMapper(om); JacksonJaxbJsonProvider provider = new JacksonJaxbJsonProvider(om, JacksonJaxbJsonProvider.DEFAULT_ANNOTATIONS); - provider.enable(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL); - provider.disable(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_USING_DEFAULT_VALUE); - this.getConfig().configureJacksonProvider(provider); if (this.getConfig().isWrapRootValueEnabled()) @@ -91,7 +88,6 @@ public abstract class Client { if (authFilter != null) clientBuilder.register(authFilter); this.buildClient(clientBuilder); - this.getConfig().configureClient(clientBuilder); return clientBuilder.build(); From ab6b0d8da7afe003029e0b8c1847942bfb699974 Mon Sep 17 00:00:00 2001 From: "Brian M. Long" Date: Mon, 12 Jun 2023 15:52:55 -0400 Subject: [PATCH 2/4] refacter OAuth filter error handling --- .../java/com/inteligr8/rs/ClientImpl.java | 83 +++++++++++++++++++ .../java/com/inteligr8/rs/LoggingFilter.java | 2 +- .../rs/OAuthAuthorizationFilter.java | 42 +++++----- 3 files changed, 107 insertions(+), 20 deletions(-) create mode 100644 src/main/java/com/inteligr8/rs/ClientImpl.java diff --git a/src/main/java/com/inteligr8/rs/ClientImpl.java b/src/main/java/com/inteligr8/rs/ClientImpl.java new file mode 100644 index 0000000..330ebc2 --- /dev/null +++ b/src/main/java/com/inteligr8/rs/ClientImpl.java @@ -0,0 +1,83 @@ +/* + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ +package com.inteligr8.rs; + +import javax.annotation.PostConstruct; +import javax.ws.rs.client.ClientBuilder; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +/** + * A class that provides pre-configured JAX-RS Client & WebTarget objects + * for Jersey. + * + * @author brian@inteligr8.com + */ +@Component("client.jaxrs") +public class ClientImpl extends Client { + + private final Logger logger = LoggerFactory.getLogger(ClientImpl.class); + + private ClientConfiguration config; + + /** + * This constructor is for Spring or POJO use. + * @param config The client configuration. + */ + @Autowired + public ClientImpl(ClientConfiguration config) { + this.config = config; + } + + /** + * This method registers the Jersey library as the default provider for the + * JAX-RS specification. + */ + @PostConstruct + public void register() { + this.logger.info("API Base URL: {}", this.getConfig().getBaseUrl()); + } + + /** + * @param clientBuilder A client builder. + */ + @Override + public void buildClient(ClientBuilder clientBuilder) { + } + + /** + * @return The client configuration. + */ + public ClientConfiguration getConfig() { + return this.config; + } + + /** + * This method retrieves a JAX-RS implementation of the specified API with + * the specified authorization. + * + * @param authFilter A dynamic authorization filter. + * @param apiClass A JAX-RS annotation API class. + * @return An instance of the API class. + */ + @Override + public T getApi(AuthorizationFilter authFilter, Class apiClass) { + throw new UnsupportedOperationException(); + } + +} diff --git a/src/main/java/com/inteligr8/rs/LoggingFilter.java b/src/main/java/com/inteligr8/rs/LoggingFilter.java index 3fedd1c..0631659 100644 --- a/src/main/java/com/inteligr8/rs/LoggingFilter.java +++ b/src/main/java/com/inteligr8/rs/LoggingFilter.java @@ -58,7 +58,7 @@ public class LoggingFilter implements ClientRequestFilter, ClientResponseFilter logger.trace("request: {} {}: {}", requestContext.getMethod(), requestContext.getUri(), ((Form)requestContext.getEntity()).asMap()); } else { - this.loggerRequest.trace("request: {} {}: failed to output form", requestContext.getMethod(), requestContext.getUri()); + logger.trace("request: {} {}: failed to output form", requestContext.getMethod(), requestContext.getUri()); } } else { this.logUnhandledRequest(requestContext, logger); diff --git a/src/main/java/com/inteligr8/rs/OAuthAuthorizationFilter.java b/src/main/java/com/inteligr8/rs/OAuthAuthorizationFilter.java index be2d42b..e8d175a 100755 --- a/src/main/java/com/inteligr8/rs/OAuthAuthorizationFilter.java +++ b/src/main/java/com/inteligr8/rs/OAuthAuthorizationFilter.java @@ -17,12 +17,15 @@ package com.inteligr8.rs; import java.util.Map; import javax.ws.rs.WebApplicationException; +import javax.ws.rs.client.Client; import javax.ws.rs.client.ClientBuilder; import javax.ws.rs.client.ClientRequestContext; import javax.ws.rs.client.Entity; import javax.ws.rs.client.WebTarget; import javax.ws.rs.core.Form; import javax.ws.rs.core.HttpHeaders; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status.Family; import com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider; @@ -115,25 +118,32 @@ public abstract class OAuthAuthorizationFilter implements AuthorizationFilter { form.param("client_secret", this.clientSecret); if (this.scope != null) form.param("scope", this.scope); - this.extendRefreshTokenForm(form); Entity
entity = Entity.form(form); - WebTarget target = ClientBuilder.newBuilder() - .register(new JacksonJaxbJsonProvider()) - .build() - .target(this.tokenUrl); + Client client = ClientBuilder.newBuilder() + .register(new JacksonJaxbJsonProvider()) + .build(); + WebTarget target = client.target(this.tokenUrl); - @SuppressWarnings("unchecked") - Map response = target.request().post(entity, Map.class); + Response response = target.request().post(entity); + + @SuppressWarnings("unchecked") + Map responseMap = response.readEntity(Map.class); - if (response.containsKey("error")) - throw new WebApplicationException((String)response.get("error"), 400); + if (response.getStatusInfo().getFamily() != Family.SUCCESSFUL) { + String code = (String) responseMap.get("error"); + if (code != null) { + String description = (String) responseMap.get("error_description"); + throw new WebApplicationException(code + ": " + description, response.getStatus()); + } else { + throw new WebApplicationException(response); + } + } - this.accessToken = (String)response.get("access_token"); - this.expiration = System.currentTimeMillis() + ((Number)response.get("expires_in")).longValue() * 1000L; - this.refreshToken = (String)response.get("refresh_token"); - this.extendRefreshTokenResponse(response); + this.accessToken = (String)responseMap.get("access_token"); + this.expiration = System.currentTimeMillis() + ((Number)responseMap.get("expires_in")).longValue() * 1000L; + this.refreshToken = (String)responseMap.get("refresh_token"); } protected Form createRefreshForm() { @@ -142,11 +152,5 @@ public abstract class OAuthAuthorizationFilter implements AuthorizationFilter { } protected abstract Form createForm(); - - protected void extendRefreshTokenForm(Form form) { - } - - protected void extendRefreshTokenResponse(Map response) { - } } From ab920aedd7c299289099e1cac488d8be1238b2ff Mon Sep 17 00:00:00 2001 From: "Brian M. Long" Date: Mon, 12 Jun 2023 16:01:29 -0400 Subject: [PATCH 3/4] added OAuth filter logging --- ...hAuthorizationCodeAuthorizationFilter.java | 8 ++++-- .../rs/OAuthAuthorizationFilter.java | 27 +++++++++++++++++-- ...thClientCredentialAuthorizationFilter.java | 4 +++ ...OAuthPasswordGrantAuthorizationFilter.java | 8 ++++-- 4 files changed, 41 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/inteligr8/rs/OAuthAuthorizationCodeAuthorizationFilter.java b/src/main/java/com/inteligr8/rs/OAuthAuthorizationCodeAuthorizationFilter.java index 128cefe..77073bc 100755 --- a/src/main/java/com/inteligr8/rs/OAuthAuthorizationCodeAuthorizationFilter.java +++ b/src/main/java/com/inteligr8/rs/OAuthAuthorizationCodeAuthorizationFilter.java @@ -74,11 +74,15 @@ public class OAuthAuthorizationCodeAuthorizationFilter extends OAuthAuthorizatio @Override protected Form createForm() { - Form form = new Form().param("grant_type", "authorization_code") - .param("code", this.code); + Form form = new Form().param("grant_type", "authorization_code"); if (this.redirectUri != null) form.param("redirect_uri", this.redirectUri.toString()); return form; } + + @Override + protected void extendFormSensitive(Form form) { + form.param("code", this.code); + } } diff --git a/src/main/java/com/inteligr8/rs/OAuthAuthorizationFilter.java b/src/main/java/com/inteligr8/rs/OAuthAuthorizationFilter.java index e8d175a..389d263 100755 --- a/src/main/java/com/inteligr8/rs/OAuthAuthorizationFilter.java +++ b/src/main/java/com/inteligr8/rs/OAuthAuthorizationFilter.java @@ -27,6 +27,9 @@ import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.Response; import javax.ws.rs.core.Response.Status.Family; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider; /** @@ -36,6 +39,8 @@ import com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider; */ public abstract class OAuthAuthorizationFilter implements AuthorizationFilter { + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + private final String tokenUrl; private final String clientId; private final String clientSecret; @@ -114,11 +119,20 @@ public abstract class OAuthAuthorizationFilter implements AuthorizationFilter { } form.param("client_id", this.clientId); - if (this.clientSecret != null) - form.param("client_secret", this.clientSecret); if (this.scope != null) form.param("scope", this.scope); + this.logger.trace("Sending OAuth request: {}", form); + + if (this.refreshToken != null) { + this.extendRefreshFormSensitive(form); + } else { + this.extendFormSensitive(form); + } + + if (this.clientSecret != null) + form.param("client_secret", this.clientSecret); + Entity entity = Entity.form(form); Client client = ClientBuilder.newBuilder() @@ -127,9 +141,13 @@ public abstract class OAuthAuthorizationFilter implements AuthorizationFilter { WebTarget target = client.target(this.tokenUrl); Response response = target.request().post(entity); + + this.logger.debug("Received OAuth response: {}", response.getStatus()); @SuppressWarnings("unchecked") Map responseMap = response.readEntity(Map.class); + + this.logger.trace("Received OAuth response: {}", responseMap); if (response.getStatusInfo().getFamily() != Family.SUCCESSFUL) { String code = (String) responseMap.get("error"); @@ -152,5 +170,10 @@ public abstract class OAuthAuthorizationFilter implements AuthorizationFilter { } protected abstract Form createForm(); + + protected void extendRefreshFormSensitive(Form form) { + } + + protected abstract void extendFormSensitive(Form form); } diff --git a/src/main/java/com/inteligr8/rs/OAuthClientCredentialAuthorizationFilter.java b/src/main/java/com/inteligr8/rs/OAuthClientCredentialAuthorizationFilter.java index 79e63da..40856e8 100755 --- a/src/main/java/com/inteligr8/rs/OAuthClientCredentialAuthorizationFilter.java +++ b/src/main/java/com/inteligr8/rs/OAuthClientCredentialAuthorizationFilter.java @@ -37,5 +37,9 @@ public class OAuthClientCredentialAuthorizationFilter extends OAuthAuthorization protected Form createForm() { return new Form().param("grant_type", "client_credentials"); } + + @Override + protected void extendFormSensitive(Form form) { + } } diff --git a/src/main/java/com/inteligr8/rs/OAuthPasswordGrantAuthorizationFilter.java b/src/main/java/com/inteligr8/rs/OAuthPasswordGrantAuthorizationFilter.java index 2037127..39a1a2e 100755 --- a/src/main/java/com/inteligr8/rs/OAuthPasswordGrantAuthorizationFilter.java +++ b/src/main/java/com/inteligr8/rs/OAuthPasswordGrantAuthorizationFilter.java @@ -53,8 +53,12 @@ public class OAuthPasswordGrantAuthorizationFilter extends OAuthAuthorizationFil @Override protected Form createForm() { return new Form().param("grant_type", "password") - .param("username", this.username) - .param("password", this.password); + .param("username", this.username); + } + + @Override + protected void extendFormSensitive(Form form) { + form.param("password", this.password); } } From 44e82b3a6b01e6f204aeec40ae1f86087743ab9a Mon Sep 17 00:00:00 2001 From: "Brian M. Long" Date: Mon, 12 Jun 2023 16:05:37 -0400 Subject: [PATCH 4/4] fixed build issue without jersey/cxf --- pom.xml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pom.xml b/pom.xml index ab8628b..c1f40f3 100644 --- a/pom.xml +++ b/pom.xml @@ -49,6 +49,11 @@ + + javax.annotation + javax.annotation-api + 1.3.2 + org.springframework spring-context