From 892b87a2af5fa82ba4f5dceb38baba28e2029182 Mon Sep 17 00:00:00 2001 From: Milton Ch <86965029+Milton-Ch@users.noreply.github.com> Date: Tue, 15 Nov 2022 08:49:57 -0400 Subject: [PATCH] feat(jans-auth-server): java docs for ssa (#2995) --- .../server/ssa/ws/rs/SsaContextBuilder.java | 18 +++++ .../as/server/ssa/ws/rs/SsaJsonService.java | 35 +++++++++ .../server/ssa/ws/rs/SsaRestWebService.java | 40 +++++++++++ .../ssa/ws/rs/SsaRestWebServiceImpl.java | 44 ++++++++++++ .../ssa/ws/rs/SsaRestWebServiceValidator.java | 31 +++++++- .../jans/as/server/ssa/ws/rs/SsaService.java | 72 +++++++++++++++++++ .../ssa/ws/rs/action/SsaCreateAction.java | 43 +++++++++++ .../server/ssa/ws/rs/action/SsaGetAction.java | 38 ++++++++++ .../ssa/ws/rs/action/SsaRevokeAction.java | 35 +++++++++ .../ssa/ws/rs/action/SsaValidateAction.java | 17 +++++ 10 files changed, 370 insertions(+), 3 deletions(-) diff --git a/jans-auth-server/server/src/main/java/io/jans/as/server/ssa/ws/rs/SsaContextBuilder.java b/jans-auth-server/server/src/main/java/io/jans/as/server/ssa/ws/rs/SsaContextBuilder.java index 9357086d8d9..7016e264008 100644 --- a/jans-auth-server/server/src/main/java/io/jans/as/server/ssa/ws/rs/SsaContextBuilder.java +++ b/jans-auth-server/server/src/main/java/io/jans/as/server/ssa/ws/rs/SsaContextBuilder.java @@ -14,10 +14,28 @@ import jakarta.inject.Named; import jakarta.servlet.http.HttpServletRequest; +/** + * Provides builder methods for SSA + */ @Stateless @Named public class SsaContextBuilder { + /** + * ModifySsaResponseContext instance for use in the SSA custom script call. + *
+ * Method was created with the purpose of passing unit tests, since when instantiating ModifySsaResponseContext + * it internally call {@link io.jans.service.cdi.util.CdiUtil} and cannot be mocked + *
+ * + * @param httpRequest Http request + * @param grant Grant type + * @param client Client + * @param appConfiguration App configuration + * @param attributeService Attribute service + * @return New instance of {@link ModifySsaResponseContext} + */ + @Deprecated public ModifySsaResponseContext buildModifySsaResponseContext(HttpServletRequest httpRequest, AuthorizationGrant grant, Client client, AppConfiguration appConfiguration, AttributeService attributeService) { return new ModifySsaResponseContext(httpRequest, grant, client, appConfiguration, attributeService); diff --git a/jans-auth-server/server/src/main/java/io/jans/as/server/ssa/ws/rs/SsaJsonService.java b/jans-auth-server/server/src/main/java/io/jans/as/server/ssa/ws/rs/SsaJsonService.java index fb42305883e..b039d21df3e 100644 --- a/jans-auth-server/server/src/main/java/io/jans/as/server/ssa/ws/rs/SsaJsonService.java +++ b/jans-auth-server/server/src/main/java/io/jans/as/server/ssa/ws/rs/SsaJsonService.java @@ -22,6 +22,9 @@ import static io.jans.as.model.ssa.SsaRequestParam.*; +/** + * Provides json utilities for SSA + */ @Stateless @Named public class SsaJsonService { @@ -29,14 +32,39 @@ public class SsaJsonService { @Inject private AppConfiguration appConfiguration; + /** + * Convert to json string from jsonObject. + * + * @param jsonObject Json object to convert + * @return Json string + * @throws JSONException If an error is found when converting. + */ public String jsonObjectToString(JSONObject jsonObject) throws JSONException { return jsonObject.toString(4).replace("\\/", "/"); } + /** + * Convert to json string from jsonArray. + * + * @param jsonArray Json array to convert + * @return Json string + * @throws JSONException If an error is found when converting. + */ public String jsonArrayToString(JSONArray jsonArray) throws JSONException { return jsonArray.toString(4).replace("\\/", "/"); } + /** + * Convert to JSONArray from ssaList with structure SSA. + * + *+ * Method generates the SSA structure to add them to a json array. + *
+ * + * @param ssaList List of SSA + * @return Json array + * @throws JSONException If an error is found when converting. + */ public JSONArray getJSONArray(List+ * Method calls the action where the SSA creation logic is implemented. + *
+ * + * @param requestParams Valid json + * @param httpRequest Http request object + * @return {@link Response} with status {@code 201} (Created) and with body the ssa token (jwt). + */ @Override public Response create(String requestParams, HttpServletRequest httpRequest) { return ssaCreateAction.create(requestParams, httpRequest); } + /** + * Get existing active SSA based on "jti" or "org_id". + *+ * Method calls the action where the SSA get logic is implemented. + *
+ * + * @param jti Unique identifier + * @param orgId Organization ID + * @param httpRequest Http request + * @return {@link Response} with status {@code 200 (Ok)} and with body List of SSA. + */ @Override public Response get(Boolean softwareRoles, String jti, Long orgId, HttpServletRequest httpRequest) { return ssaGetAction.get(softwareRoles, jti, orgId, httpRequest); } + /** + * Validate existing active SSA based on "jti". + *+ * Method calls the action where the SSA validate logic is implemented. + *
+ * + * @param jti Unique identifier + * @return {@link Response} with status {@code 200} (Ok) if SSA has been validated. + */ @Override public Response validate(String jti) { return ssaValidateAction.validate(jti); } + /** + * Revoked existing active SSA based on "jti" or "org_id". + *+ * Method calls the action where the SSA revoke logic is implemented. + *
+ * + * @param jti Unique identifier + * @param orgId Organization ID + * @param httpRequest Http request + * @return {@link Response} with status {@code 200 (Ok)} if SSA has been revoked. + */ @Override public Response revoke(String jti, Long orgId, HttpServletRequest httpRequest) { return ssaRevokeAction.revoke(jti, orgId, httpRequest); diff --git a/jans-auth-server/server/src/main/java/io/jans/as/server/ssa/ws/rs/SsaRestWebServiceValidator.java b/jans-auth-server/server/src/main/java/io/jans/as/server/ssa/ws/rs/SsaRestWebServiceValidator.java index ccf79d94adc..db86919ac82 100644 --- a/jans-auth-server/server/src/main/java/io/jans/as/server/ssa/ws/rs/SsaRestWebServiceValidator.java +++ b/jans-auth-server/server/src/main/java/io/jans/as/server/ssa/ws/rs/SsaRestWebServiceValidator.java @@ -15,6 +15,7 @@ import jakarta.ejb.Stateless; import jakarta.inject.Inject; import jakarta.inject.Named; +import jakarta.ws.rs.WebApplicationException; import jakarta.ws.rs.core.Response; import org.slf4j.Logger; @@ -22,6 +23,9 @@ import java.util.List; import java.util.stream.Collectors; +/** + * Provides methods to validate different params about SSA. + */ @Named @Stateless public class SsaRestWebServiceValidator { @@ -38,7 +42,14 @@ public class SsaRestWebServiceValidator { @Inject private ScopeService scopeService; - public Client getClientFromSession() { + /** + * Get client from session + * + * @return {@link Client} if obtained. + * @throws WebApplicationException with status {@code 401} and key INVALID_CLIENT if the client cannot + * be obtained. + */ + public Client getClientFromSession() throws WebApplicationException { SessionClient sessionClient = identity.getSessionClient(); if (sessionClient != null) { log.debug("Client: {}, obtained from session", sessionClient.getClient().getClientId()); @@ -47,13 +58,27 @@ public Client getClientFromSession() { throw errorResponseFactory.createBadRequestException(SsaErrorResponseType.INVALID_CLIENT, "Invalid client"); } - public void checkScopesPolicy(Client client, String scope) { + /** + * Check if the client has the given scope. + * + * @param client Client to check scope + * @param scope Scope to validate + * @throws WebApplicationException with status {@code 401} and key UNAUTHORIZED_CLIENT if you don't have the scope. + */ + public void checkScopesPolicy(Client client, String scope) throws WebApplicationException { List+ * Method returns null if the SSA is not found. + *
+ * + * @param jti Unique identifier + * @return {@link Ssa} found + */ public Ssa findSsaByJti(String jti) { try { return persistenceEntryManager.find(Ssa.class, getDnForSsa(jti)); @@ -67,6 +89,19 @@ public Ssa findSsaByJti(String jti) { } } + /** + * Get list of SSAs based on "jti", "org_id" or "status" filters + *+ * If the client only has ssa.portal scope, then it is filtered by the client that created the SSA + *
+ * + * @param jti Unique identifier + * @param orgId Organization ID + * @param status Status + * @param clientId Client ID + * @param scopes List of scope + * @return List of SSA + */ public List+ * Method throws an {@link RuntimeException} if it fails to create the jwt + *
+ *+ * Method executes a postProcessor in case it has been sent in the execution context parameter. + *
+ * + * @param ssa Ssa + * @param executionContext Execution context + * @param webKeysConfiguration Web keys configuration + * @param cryptoProvider Crypto provider + * @return Jwt with SSA structure + */ public Jwt generateJwt(Ssa ssa, ExecutionContext executionContext, WebKeysConfiguration webKeysConfiguration, AbstractCryptoProvider cryptoProvider) { try { SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.fromString(appConfiguration.getSsaConfiguration().getSsaSigningAlg()); @@ -114,14 +164,30 @@ public Jwt generateJwt(Ssa ssa, ExecutionContext executionContext, WebKeysConfig } } + /** + * Create a {@link Response.ResponseBuilder} with status 422 + * + * @return Response builder + */ public Response.ResponseBuilder createUnprocessableEntityResponse() { return Response.status(HttpStatus.SC_UNPROCESSABLE_ENTITY).type(MediaType.APPLICATION_JSON_TYPE); } + /** + * Create a {@link Response.ResponseBuilder} with status 406 + * + * @return Response builder + */ public Response.ResponseBuilder createNotAcceptableResponse() { return Response.status(HttpStatus.SC_NOT_ACCEPTABLE).type(MediaType.APPLICATION_JSON_TYPE); } + /** + * Check if there is only one "ssa.portal" scope + * + * @param scopes List of scope + * @return true if is only one "ssa.portal", or false otherwise + */ private boolean hasPortalScope(List+ * Method will return a {@link WebApplicationException} with status {@code 401} if this functionality is not enabled, + * request has to have at least scope "ssa.admin", + * it will also return a {@link WebApplicationException} with status {@code 500} in case an uncontrolled + * error occurs when processing the method. + *
+ *+ * Response of this method can be modified using the following custom script + * SSA Custom Script, + * method create. + *
+ *+ * SSA returned by this method is stored in the corresponding database, so it can be later retrieved, validated or revoked. + *
+ * + * @param requestParams Valid json request + * @param httpRequest Http request + * @return {@link Response} with status {@code 201} (Created) and response body containing the SSA in JWT format. + */ public Response create(String requestParams, HttpServletRequest httpRequest) { errorResponseFactory.validateFeatureEnabled(FeatureFlagType.SSA); Response.ResponseBuilder builder = Response.status(Response.Status.CREATED); @@ -151,6 +175,15 @@ public Response create(String requestParams, HttpServletRequest httpRequest) { return builder.build(); } + /** + * Get custom attributes from a request, previously configured in SSA global parameters. + *+ * Method prints the warning type in case a request parameter does not exist in the SSA model or SSA global parameter settings. + *
+ * + * @param jsonRequest Valid json request + * @return Map containing all custom attributes where key is the attribute name. + */ private Map+ * Method converts from epoch time to Date or generates a date based on the global SSA setting when the Date field + * of the request is null. + *
+ * + * @param ssaCreateRequest Request of SSA + * @return Respective new Date instance. + */ private Date getExpiration(SsaCreateRequest ssaCreateRequest) { Calendar calendar = GregorianCalendar.getInstance(TimeZone.getTimeZone("UTC")); if (ssaCreateRequest.getExpiration() != null && ssaCreateRequest.getExpiration() > 0) { diff --git a/jans-auth-server/server/src/main/java/io/jans/as/server/ssa/ws/rs/action/SsaGetAction.java b/jans-auth-server/server/src/main/java/io/jans/as/server/ssa/ws/rs/action/SsaGetAction.java index 46c1fce17ee..6667477149d 100644 --- a/jans-auth-server/server/src/main/java/io/jans/as/server/ssa/ws/rs/action/SsaGetAction.java +++ b/jans-auth-server/server/src/main/java/io/jans/as/server/ssa/ws/rs/action/SsaGetAction.java @@ -36,6 +36,9 @@ import java.util.Arrays; import java.util.List; +/** + * Provides the method to get existing SSAs based on certain conditions. + */ @Stateless @Named public class SsaGetAction { @@ -67,6 +70,29 @@ public class SsaGetAction { @Inject private SsaContextBuilder ssaContextBuilder; + /** + * Get existing active SSA based on "jti" or "org_id". + *+ * Method will return a {@link WebApplicationException} with status {@code 401} if this functionality is not enabled, + * request has to have at least scope "ssa.admin" or "ssa.portal", + * it will also return a {@link WebApplicationException} with status {@code 500} in case an uncontrolled + * error occurs when processing the method. + *
+ *+ * Response of this method can be modified using the following custom script + * SSA Custom Script, + * method get. + *
+ *+ * Method also performs the search based on the scope, if the scope is "ssa.admin" it is based on all SSA records, + * but if the scope is "ssa.portal", then it only returns the SSA list corresponding to the same org. + *
+ * + * @param jti Unique identifier + * @param orgId Organization ID + * @param httpRequest Http request + * @return {@link Response} with status {@code 200 (Ok)} and the body containing the list of SSAs. + */ public Response get(Boolean softwareRoles, String jti, Long orgId, HttpServletRequest httpRequest) { log.debug("Attempting to read ssa: softwareRoles = {}, jti = '{}', orgId = {}", softwareRoles, jti, orgId); @@ -100,6 +126,18 @@ public Response get(Boolean softwareRoles, String jti, Long orgId, HttpServletRe return builder.build(); } + /** + * Modify the JSONArray through the custom script. + * + *+ * Method returns the same json array in case the script execution returned false. + *
+ * + * @param jsonArray Json array with list of SSA + * @param context Modify ssa response context + * @param ssaList List of SSA + * @return Modified Json array. + */ private JSONArray modifyGetScript(JSONArray jsonArray, ModifySsaResponseContext context, List+ * Method will return a {@link WebApplicationException} with status {@code 401} if this functionality is not enabled, + * request has to have at least scope "ssa.admin", + * {@link WebApplicationException} with status {@code 406} if "jti" or "org_id" filters are not valid, + * {@link WebApplicationException} with status {@code 422} if the SSA does not exist, has expired or is no longer active, + * it will also return a {@link WebApplicationException} with status code {@code 500} in case an uncontrolled + * error occurs when processing the method. + *
+ *+ * After revoking the SSA, it calls custom script to perform an additional process. + * SSA Custom Script, + * method revoke. + *
+ *+ * Method updates the list of SSA and marks them as REVOKED in the database. + *
+ * + * @param jti Unique identifier + * @param orgId Organization ID + * @param httpRequest Http request + * @return {@link Response} with status {@code 200 (Ok)} if SSA has been revoked. + */ public Response revoke(String jti, Long orgId, HttpServletRequest httpRequest) { log.debug("Attempting to revoke ssa, jti: '{}', orgId: {}", jti, orgId); @@ -105,6 +133,13 @@ public Response revoke(String jti, Long orgId, HttpServletRequest httpRequest) { return builder.build(); } + /** + * Validate "jti" or "org_id" parameters + * + * @param jti Unique identifier + * @param orgId Organization ID + * @return true if the parameters are valid or false otherwise. + */ private boolean isNotValidParam(String jti, Long orgId) { return StringUtils.isBlank(jti) && orgId == null; } diff --git a/jans-auth-server/server/src/main/java/io/jans/as/server/ssa/ws/rs/action/SsaValidateAction.java b/jans-auth-server/server/src/main/java/io/jans/as/server/ssa/ws/rs/action/SsaValidateAction.java index 547b2b5890c..18ec93e01d6 100644 --- a/jans-auth-server/server/src/main/java/io/jans/as/server/ssa/ws/rs/action/SsaValidateAction.java +++ b/jans-auth-server/server/src/main/java/io/jans/as/server/ssa/ws/rs/action/SsaValidateAction.java @@ -17,6 +17,7 @@ import jakarta.ejb.Stateless; import jakarta.inject.Inject; import jakarta.inject.Named; +import jakarta.ws.rs.WebApplicationException; import jakarta.ws.rs.core.MediaType; import jakarta.ws.rs.core.Response; import org.slf4j.Logger; @@ -24,6 +25,9 @@ import java.util.Calendar; import java.util.TimeZone; +/** + * Provides the method to validate an existing SSA considering certain conditions. + */ @Stateless @Named public class SsaValidateAction { @@ -37,6 +41,19 @@ public class SsaValidateAction { @Inject private SsaService ssaService; + /** + * Validates an existing SSA for a given "jti". + * + *+ * Method will return a {@link WebApplicationException} with status {@code 422} if the SSA does not exist, + * has been expired or is no longer active, + * it will also return a {@link WebApplicationException} with status {@code 500} in case an uncontrolled + * error occurs when processing the method. + *
+ * + * @param jti Unique identifier + * @return {@link Response} with status {@code 200} (Ok) if SSA has been validated. + */ public Response validate(String jti) { log.debug("Attempting to validate ssa jti: '{}'", jti);