From 9f1861313982b1b702f854260b94637eac768a68 Mon Sep 17 00:00:00 2001 From: YuriyZ Date: Wed, 19 Jan 2022 10:26:34 +0200 Subject: [PATCH 1/7] feat(jans-core): added methods for register response modification https://github.com/JanssenProject/jans/issues/380 --- .../script/type/client/ClientRegistrationType.java | 4 ++++ .../type/client/DummyClientRegistrationType.java | 10 ++++++++++ 2 files changed, 14 insertions(+) diff --git a/jans-core/script/src/main/java/io/jans/model/custom/script/type/client/ClientRegistrationType.java b/jans-core/script/src/main/java/io/jans/model/custom/script/type/client/ClientRegistrationType.java index 9dd3a2ab64b..df02865449d 100644 --- a/jans-core/script/src/main/java/io/jans/model/custom/script/type/client/ClientRegistrationType.java +++ b/jans-core/script/src/main/java/io/jans/model/custom/script/type/client/ClientRegistrationType.java @@ -35,4 +35,8 @@ public interface ClientRegistrationType extends BaseExternalType { // context - io.jans.as.server.service.external.context.DynamicClientRegistrationContext // cert - java.security.cert.X509Certificate boolean isCertValidForClient(Object cert, Object context); + + boolean modifyPutResponse(Object responseAsJsonObject, Object executionContext); + + boolean modifyPostResponse(Object responseAsJsonObject, Object executionContext); } diff --git a/jans-core/script/src/main/java/io/jans/model/custom/script/type/client/DummyClientRegistrationType.java b/jans-core/script/src/main/java/io/jans/model/custom/script/type/client/DummyClientRegistrationType.java index 0ef1da9e494..5efbf539bcb 100644 --- a/jans-core/script/src/main/java/io/jans/model/custom/script/type/client/DummyClientRegistrationType.java +++ b/jans-core/script/src/main/java/io/jans/model/custom/script/type/client/DummyClientRegistrationType.java @@ -69,4 +69,14 @@ public String getDcrJwks(Object context) { public boolean isCertValidForClient(Object cert, Object context) { return false; } + + @Override + public boolean modifyPutResponse(Object responseAsJsonObject, Object executionContext) { + return false; + } + + @Override + public boolean modifyPostResponse(Object responseAsJsonObject, Object executionContext) { + return false; + } } From db936f9de9ec31f3fa62d23a5e96922c5e892227 Mon Sep 17 00:00:00 2001 From: YuriyZ Date: Wed, 19 Jan 2022 11:02:32 +0200 Subject: [PATCH 2/7] feat(jans-auth-server): added post response modification method https://github.com/JanssenProject/jans/issues/380 --- ...ernalDynamicClientRegistrationService.java | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/jans-auth-server/server/src/main/java/io/jans/as/server/service/external/ExternalDynamicClientRegistrationService.java b/jans-auth-server/server/src/main/java/io/jans/as/server/service/external/ExternalDynamicClientRegistrationService.java index 3e81856e116..dab8d4f319f 100644 --- a/jans-auth-server/server/src/main/java/io/jans/as/server/service/external/ExternalDynamicClientRegistrationService.java +++ b/jans-auth-server/server/src/main/java/io/jans/as/server/service/external/ExternalDynamicClientRegistrationService.java @@ -11,6 +11,7 @@ import io.jans.as.model.error.ErrorResponseFactory; import io.jans.as.model.jwt.Jwt; import io.jans.as.model.util.CertUtils; +import io.jans.as.server.model.common.ExecutionContext; import io.jans.as.server.service.external.context.DynamicClientRegistrationContext; import io.jans.model.custom.script.CustomScriptType; import io.jans.model.custom.script.conf.CustomScriptConfiguration; @@ -231,4 +232,27 @@ public boolean isCertValidForClient(X509Certificate cert, DynamicClientRegistrat return false; } } + + public boolean modifyPostResponse(JSONObject responseAsJsonObject, ExecutionContext context) { + CustomScriptConfiguration script = defaultExternalCustomScript; + + try { + if (log.isTraceEnabled()) { + log.trace("Executing python 'modifyPostResponse' method, script name: {}, context: {}, response: {}", script.getName(), context, responseAsJsonObject.toString()); + } + context.setScript(script); + + ClientRegistrationType type = (ClientRegistrationType) script.getExternalType(); + final boolean result = type.modifyPostResponse(responseAsJsonObject, context); + if (log.isTraceEnabled()) { + log.trace("Finished 'modifyPostResponse' method, script name: {}, context: {}, result: {}, response: {}", script.getName(), context, result, responseAsJsonObject.toString()); + } + + return result; + } catch (Exception ex) { + log.error(ex.getMessage(), ex); + saveScriptError(script.getCustomScript(), ex); + } + return false; + } } From 00a24f22c15343207ab797155714722171cc3df8 Mon Sep 17 00:00:00 2001 From: YuriyZ Date: Wed, 19 Jan 2022 11:04:58 +0200 Subject: [PATCH 3/7] feat(jans-auth-server): added put response modification method https://github.com/JanssenProject/jans/issues/380 --- ...ernalDynamicClientRegistrationService.java | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/jans-auth-server/server/src/main/java/io/jans/as/server/service/external/ExternalDynamicClientRegistrationService.java b/jans-auth-server/server/src/main/java/io/jans/as/server/service/external/ExternalDynamicClientRegistrationService.java index dab8d4f319f..7fdaf746567 100644 --- a/jans-auth-server/server/src/main/java/io/jans/as/server/service/external/ExternalDynamicClientRegistrationService.java +++ b/jans-auth-server/server/src/main/java/io/jans/as/server/service/external/ExternalDynamicClientRegistrationService.java @@ -255,4 +255,27 @@ public boolean modifyPostResponse(JSONObject responseAsJsonObject, ExecutionCont } return false; } + + public boolean modifyPutResponse(JSONObject responseAsJsonObject, ExecutionContext context) { + CustomScriptConfiguration script = defaultExternalCustomScript; + + try { + if (log.isTraceEnabled()) { + log.trace("Executing python 'modifyPutResponse' method, script name: {}, context: {}, response: {}", script.getName(), context, responseAsJsonObject.toString()); + } + context.setScript(script); + + ClientRegistrationType type = (ClientRegistrationType) script.getExternalType(); + final boolean result = type.modifyPutResponse(responseAsJsonObject, context); + if (log.isTraceEnabled()) { + log.trace("Finished 'modifyPutResponse' method, script name: {}, context: {}, result: {}, response: {}", script.getName(), context, result, responseAsJsonObject.toString()); + } + + return result; + } catch (Exception ex) { + log.error(ex.getMessage(), ex); + saveScriptError(script.getCustomScript(), ex); + } + return false; + } } From 74bbe38ef5f4e3940e36a665c621daf95ca84bde Mon Sep 17 00:00:00 2001 From: YuriyZ Date: Wed, 19 Jan 2022 11:18:45 +0200 Subject: [PATCH 4/7] feat(jans-core): added read response modification method https://github.com/JanssenProject/jans/issues/380 --- .../custom/script/type/client/ClientRegistrationType.java | 2 ++ .../script/type/client/DummyClientRegistrationType.java | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/jans-core/script/src/main/java/io/jans/model/custom/script/type/client/ClientRegistrationType.java b/jans-core/script/src/main/java/io/jans/model/custom/script/type/client/ClientRegistrationType.java index df02865449d..31cd07cd481 100644 --- a/jans-core/script/src/main/java/io/jans/model/custom/script/type/client/ClientRegistrationType.java +++ b/jans-core/script/src/main/java/io/jans/model/custom/script/type/client/ClientRegistrationType.java @@ -38,5 +38,7 @@ public interface ClientRegistrationType extends BaseExternalType { boolean modifyPutResponse(Object responseAsJsonObject, Object executionContext); + boolean modifyReadResponse(Object responseAsJsonObject, Object executionContext); + boolean modifyPostResponse(Object responseAsJsonObject, Object executionContext); } diff --git a/jans-core/script/src/main/java/io/jans/model/custom/script/type/client/DummyClientRegistrationType.java b/jans-core/script/src/main/java/io/jans/model/custom/script/type/client/DummyClientRegistrationType.java index 5efbf539bcb..8858230aa6d 100644 --- a/jans-core/script/src/main/java/io/jans/model/custom/script/type/client/DummyClientRegistrationType.java +++ b/jans-core/script/src/main/java/io/jans/model/custom/script/type/client/DummyClientRegistrationType.java @@ -75,6 +75,11 @@ public boolean modifyPutResponse(Object responseAsJsonObject, Object executionCo return false; } + @Override + public boolean modifyReadResponse(Object responseAsJsonObject, Object executionContext) { + return false; + } + @Override public boolean modifyPostResponse(Object responseAsJsonObject, Object executionContext) { return false; From ec8864bad991f2f27a2ab8969001d2cc59a00979 Mon Sep 17 00:00:00 2001 From: YuriyZ Date: Thu, 20 Jan 2022 12:13:08 +0200 Subject: [PATCH 5/7] feat(jans-auth-server): added read response modification method https://github.com/JanssenProject/jans/issues/380 --- ...ernalDynamicClientRegistrationService.java | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/jans-auth-server/server/src/main/java/io/jans/as/server/service/external/ExternalDynamicClientRegistrationService.java b/jans-auth-server/server/src/main/java/io/jans/as/server/service/external/ExternalDynamicClientRegistrationService.java index 7fdaf746567..0e4d1275e10 100644 --- a/jans-auth-server/server/src/main/java/io/jans/as/server/service/external/ExternalDynamicClientRegistrationService.java +++ b/jans-auth-server/server/src/main/java/io/jans/as/server/service/external/ExternalDynamicClientRegistrationService.java @@ -278,4 +278,27 @@ public boolean modifyPutResponse(JSONObject responseAsJsonObject, ExecutionConte } return false; } + + public boolean modifyReadResponse(JSONObject responseAsJsonObject, ExecutionContext context) { + CustomScriptConfiguration script = defaultExternalCustomScript; + + try { + if (log.isTraceEnabled()) { + log.trace("Executing python 'modifyReadResponse' method, script name: {}, context: {}, response: {}", script.getName(), context, responseAsJsonObject.toString()); + } + context.setScript(script); + + ClientRegistrationType type = (ClientRegistrationType) script.getExternalType(); + final boolean result = type.modifyReadResponse(responseAsJsonObject, context); + if (log.isTraceEnabled()) { + log.trace("Finished 'modifyReadResponse' method, script name: {}, context: {}, result: {}, response: {}", script.getName(), context, result, responseAsJsonObject.toString()); + } + + return result; + } catch (Exception ex) { + log.error(ex.getMessage(), ex); + saveScriptError(script.getCustomScript(), ex); + } + return false; + } } From da44d5a033b7a6343747e7aad01d3899984cc38d Mon Sep 17 00:00:00 2001 From: YuriyZ Date: Fri, 21 Jan 2022 13:24:31 +0200 Subject: [PATCH 6/7] feat(jans-auth-server): invoke custom script methods for response modification https://github.com/JanssenProject/jans/issues/380 --- .../server/model/common/ExecutionContext.java | 3 +- .../ws/rs/RegisterRestWebServiceImpl.java | 43 ++++++++++++++++--- 2 files changed, 40 insertions(+), 6 deletions(-) diff --git a/jans-auth-server/server/src/main/java/io/jans/as/server/model/common/ExecutionContext.java b/jans-auth-server/server/src/main/java/io/jans/as/server/model/common/ExecutionContext.java index aa602436fde..bafcf750e52 100644 --- a/jans-auth-server/server/src/main/java/io/jans/as/server/model/common/ExecutionContext.java +++ b/jans-auth-server/server/src/main/java/io/jans/as/server/model/common/ExecutionContext.java @@ -94,8 +94,9 @@ public Client getClient() { return client; } - public void setClient(Client client) { + public ExecutionContext setClient(Client client) { this.client = client; + return this; } public void setHttpRequest(HttpServletRequest httpRequest) { diff --git a/jans-auth-server/server/src/main/java/io/jans/as/server/register/ws/rs/RegisterRestWebServiceImpl.java b/jans-auth-server/server/src/main/java/io/jans/as/server/register/ws/rs/RegisterRestWebServiceImpl.java index f18d4c00a0b..86ed1bff2c1 100644 --- a/jans-auth-server/server/src/main/java/io/jans/as/server/register/ws/rs/RegisterRestWebServiceImpl.java +++ b/jans-auth-server/server/src/main/java/io/jans/as/server/register/ws/rs/RegisterRestWebServiceImpl.java @@ -43,6 +43,7 @@ import io.jans.as.server.model.common.AbstractToken; import io.jans.as.server.model.common.AuthorizationGrant; import io.jans.as.server.model.common.AuthorizationGrantList; +import io.jans.as.server.model.common.ExecutionContext; import io.jans.as.server.model.registration.RegisterParamsValidator; import io.jans.as.server.model.token.HandleTokenFactory; import io.jans.as.server.service.ClientService; @@ -374,7 +375,10 @@ private Response registerClientImpl(String requestParams, HttpServletRequest htt clientService.persist(client); JSONObject jsonObject = getJSONObject(client); - builder.entity(jsonObject.toString(4).replace("\\/", "/")); + + jsonObject = modifyPostScript(jsonObject, new ExecutionContext(httpRequest, null).setClient(client)); + + builder.entity(jsonObjectToString(jsonObject)); log.info("Client registered: clientId = {}, applicationType = {}, clientName = {}, redirectUris = {}, sectorIdentifierUri = {}", client.getClientId(), client.getApplicationType(), client.getClientName(), client.getRedirectUris(), client.getSectorIdentifierUri()); @@ -946,10 +950,16 @@ public Response requestClientUpdate(String requestParams, String clientId, @Head if (updateClient) { clientService.merge(client); + JSONObject jsonObject = getJSONObject(client); + jsonObject = modifyPutScript(jsonObject, new ExecutionContext(httpRequest, null).setClient(client)); + + final Response response = Response.ok().entity(jsonObjectToString(jsonObject)).build(); + oAuth2AuditLog.setScope(clientScopesToString(client)); oAuth2AuditLog.setSuccess(true); applicationAuditLogger.sendMessage(oAuth2AuditLog); - return Response.ok().entity(clientAsEntity(client)).build(); + + return response; } else { clientService.removeFromCache(client); // clear cache to force reload from persistence log.trace("The Access Token is not valid for the Client ID, returns invalid_token error, client_id: {}", clientId); @@ -1051,7 +1061,10 @@ public Response requestClientRead(String clientId, String authorization, HttpSer if (client != null) { oAuth2AuditLog.setScope(clientScopesToString(client)); oAuth2AuditLog.setSuccess(true); - builder.entity(clientAsEntity(client)); + + JSONObject jsonObject = getJSONObject(client); + jsonObject = modifyReadScript(jsonObject, new ExecutionContext(httpRequest, null).setClient(client)); + builder.entity(jsonObjectToString(jsonObject)); } else { log.trace("The Access Token is not valid for the Client ID, returns invalid_token error."); builder = Response.status(Response.Status.UNAUTHORIZED.getStatusCode()).type(MediaType.APPLICATION_JSON_TYPE); @@ -1075,8 +1088,7 @@ public Response requestClientRead(String clientId, String authorization, HttpSer return builder.build(); } - private String clientAsEntity(Client client) throws JSONException, StringEncrypter.EncryptionException { - final JSONObject jsonObject = getJSONObject(client); + private static String jsonObjectToString(JSONObject jsonObject) throws JSONException { return jsonObject.toString(4).replace("\\/", "/"); } @@ -1318,4 +1330,25 @@ private void putCustomAttributesInResponse(Client client, JSONObject responseJso } } + private JSONObject modifyPostScript(JSONObject jsonObject, ExecutionContext executionContext) throws StringEncrypter.EncryptionException { + if (!externalDynamicClientRegistrationService.modifyPostResponse(jsonObject, executionContext)) { + return getJSONObject(executionContext.getClient()); // script forbids modification, re-create json object + } + return jsonObject; + } + + private JSONObject modifyPutScript(JSONObject jsonObject, ExecutionContext executionContext) throws StringEncrypter.EncryptionException { + if (!externalDynamicClientRegistrationService.modifyPutResponse(jsonObject, executionContext)) { + return getJSONObject(executionContext.getClient()); // script forbids modification, re-create json object + } + return jsonObject; + } + + private JSONObject modifyReadScript(JSONObject jsonObject, ExecutionContext executionContext) throws StringEncrypter.EncryptionException { + if (!externalDynamicClientRegistrationService.modifyReadResponse(jsonObject, executionContext)) { + return getJSONObject(executionContext.getClient()); // script forbids modification, re-create json object + } + return jsonObject; + } + } \ No newline at end of file From 595bfd40106cc0a0ee24481187da2ad8ef8d1539 Mon Sep 17 00:00:00 2001 From: YuriyZ Date: Fri, 21 Jan 2022 13:39:02 +0200 Subject: [PATCH 7/7] feat(jans-ce-setup): updated client registration script with newly added methods https://github.com/JanssenProject/jans/issues/380 --- .../extension/client_registration/Registration.py | 15 +++++++++++++++ .../static/extension/client_registration/Casa.py | 15 +++++++++++++++ .../extension/client_registration/SampleScript.py | 15 +++++++++++++++ 3 files changed, 45 insertions(+) diff --git a/jans-ce-setup/openbanking/static/extension/client_registration/Registration.py b/jans-ce-setup/openbanking/static/extension/client_registration/Registration.py index 5bdfa95a7ea..6f1ecae3fcb 100644 --- a/jans-ce-setup/openbanking/static/extension/client_registration/Registration.py +++ b/jans-ce-setup/openbanking/static/extension/client_registration/Registration.py @@ -411,4 +411,19 @@ def getCN_of_AS(self ) : print "Client Registration. Failed to get CN of AS from the transport keystore. Exception: ", sys.exc_info()[1] return None + # responseAsJsonObject - is org.json.JSONObject, you can use any method to manipulate json + # context is reference of io.jans.as.server.model.common.ExecutionContext + def modifyPutResponse(self, responseAsJsonObject, executionContext): + return False + + # responseAsJsonObject - is org.json.JSONObject, you can use any method to manipulate json + # context is reference of io.jans.as.server.model.common.ExecutionContext + def modifyReadResponse(self, responseAsJsonObject, executionContext): + return False + + # responseAsJsonObject - is org.json.JSONObject, you can use any method to manipulate json + # context is reference of io.jans.as.server.model.common.ExecutionContext + def modifyPostResponse(self, responseAsJsonObject, executionContext): + return False + \ No newline at end of file diff --git a/jans-ce-setup/static/extension/client_registration/Casa.py b/jans-ce-setup/static/extension/client_registration/Casa.py index eae176003ad..f12f479e9f6 100644 --- a/jans-ce-setup/static/extension/client_registration/Casa.py +++ b/jans-ce-setup/static/extension/client_registration/Casa.py @@ -118,3 +118,18 @@ def prepareClientRedirectUris(self, configurationAttributes): i = i + 1 return clientRedirectUrisSet + + # responseAsJsonObject - is org.json.JSONObject, you can use any method to manipulate json + # context is reference of io.jans.as.server.model.common.ExecutionContext + def modifyPutResponse(self, responseAsJsonObject, executionContext): + return False + + # responseAsJsonObject - is org.json.JSONObject, you can use any method to manipulate json + # context is reference of io.jans.as.server.model.common.ExecutionContext + def modifyReadResponse(self, responseAsJsonObject, executionContext): + return False + + # responseAsJsonObject - is org.json.JSONObject, you can use any method to manipulate json + # context is reference of io.jans.as.server.model.common.ExecutionContext + def modifyPostResponse(self, responseAsJsonObject, executionContext): + return False diff --git a/jans-ce-setup/static/extension/client_registration/SampleScript.py b/jans-ce-setup/static/extension/client_registration/SampleScript.py index 5a02691aec8..c2cfd96d77a 100644 --- a/jans-ce-setup/static/extension/client_registration/SampleScript.py +++ b/jans-ce-setup/static/extension/client_registration/SampleScript.py @@ -109,3 +109,18 @@ def getSoftwareStatementJwks(self, context): # context refers to io.jans.as.server.service.external.context.DynamicClientRegistrationContext - see https://github.com/JanssenProject/jans-auth-server/blob/e083818272ac48813eca8525e94f7bd73a7a9f1b/server/src/main/java/io/jans/as/server/service/external/context/DynamicClientRegistrationContext.java#L24 def isCertValidForClient(self, cert, context): return False + + # responseAsJsonObject - is org.json.JSONObject, you can use any method to manipulate json + # context is reference of io.jans.as.server.model.common.ExecutionContext + def modifyPutResponse(self, responseAsJsonObject, executionContext): + return False + + # responseAsJsonObject - is org.json.JSONObject, you can use any method to manipulate json + # context is reference of io.jans.as.server.model.common.ExecutionContext + def modifyReadResponse(self, responseAsJsonObject, executionContext): + return False + + # responseAsJsonObject - is org.json.JSONObject, you can use any method to manipulate json + # context is reference of io.jans.as.server.model.common.ExecutionContext + def modifyPostResponse(self, responseAsJsonObject, executionContext): + return False