Skip to content

Commit

Permalink
feat(jans-auth-server): add methods to dynamic client registration sc…
Browse files Browse the repository at this point in the history
…ript to modify POST, PUT and GET responses (#661)

* feat(jans-core): added methods for register response modification
* feat(jans-auth-server): added post response modification method
* feat(jans-auth-server): added put response modification method
* feat(jans-core): added read response modification method
* feat(jans-auth-server): added read response modification method
* feat(jans-auth-server): invoke custom script methods for response modification
  • Loading branch information
yuriyzz authored Jan 21, 2022
1 parent 6c7ef96 commit 2aa2ba8
Show file tree
Hide file tree
Showing 5 changed files with 131 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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());
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand All @@ -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("\\/", "/");
}

Expand Down Expand Up @@ -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;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -231,4 +232,73 @@ 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;
}

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;
}

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;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,10 @@ 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 modifyReadResponse(Object responseAsJsonObject, Object executionContext);

boolean modifyPostResponse(Object responseAsJsonObject, Object executionContext);
}
Original file line number Diff line number Diff line change
Expand Up @@ -69,4 +69,19 @@ 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 modifyReadResponse(Object responseAsJsonObject, Object executionContext) {
return false;
}

@Override
public boolean modifyPostResponse(Object responseAsJsonObject, Object executionContext) {
return false;
}
}

0 comments on commit 2aa2ba8

Please sign in to comment.