diff options
Diffstat (limited to 'id/server/modules/moa-id-module-sl20_authentication')
2 files changed, 349 insertions, 332 deletions
diff --git a/id/server/modules/moa-id-module-sl20_authentication/pom.xml b/id/server/modules/moa-id-module-sl20_authentication/pom.xml index 0dccba648..d3a2cc94e 100644 --- a/id/server/modules/moa-id-module-sl20_authentication/pom.xml +++ b/id/server/modules/moa-id-module-sl20_authentication/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>MOA.id.server.modules</groupId> <artifactId>moa-id-modules</artifactId> - <version>4.1.5</version> + <version>4.2.0</version> </parent> <artifactId>moa-id-module-sl20_authentication</artifactId> <name>moa-id-module-sl20_authentication</name> @@ -53,20 +53,19 @@ <dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson</artifactId> - <version>2.8.2</version> + <version>2.8.9</version> </dependency> <dependency> <groupId>org.bitbucket.b_c</groupId> <artifactId>jose4j</artifactId> - <version>0.6.3</version> + <version>0.7.9</version> </dependency> - <dependency> - <groupId>org.bouncycastle</groupId> - <artifactId>bcprov-jdk15on</artifactId> - <version>1.52</version> - <!-- <scope>provided</scope> --> -</dependency> + <dependency> + <groupId>org.bouncycastle</groupId> + <artifactId>bcprov-jdk15on</artifactId> + <version>1.70</version> + </dependency> <!-- Dependencies for testing --> diff --git a/id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/sl20_auth/sl20/SL20JSONExtractorUtils.java b/id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/sl20_auth/sl20/SL20JSONExtractorUtils.java index 759d9c838..6bf297a4e 100644 --- a/id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/sl20_auth/sl20/SL20JSONExtractorUtils.java +++ b/id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/sl20_auth/sl20/SL20JSONExtractorUtils.java @@ -13,7 +13,6 @@ import org.apache.http.Header; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.client.utils.URIBuilder; -import org.apache.log4j.Logger; import org.jose4j.base64url.Base64Url; import com.google.gson.JsonElement; @@ -23,328 +22,347 @@ import com.google.gson.JsonParser; import at.gv.egovernment.moa.id.auth.modules.sl20_auth.data.VerificationResult; import at.gv.egovernment.moa.id.auth.modules.sl20_auth.exceptions.SL20Exception; import at.gv.egovernment.moa.id.auth.modules.sl20_auth.exceptions.SLCommandoParserException; +import lombok.extern.slf4j.Slf4j; +@Slf4j public class SL20JSONExtractorUtils { - private static final Logger log = Logger.getLogger(SL20JSONExtractorUtils.class); - - /** - * Extract String value from JSON - * - * @param input - * @param keyID - * @param isRequired - * @return - * @throws SLCommandoParserException - */ - public static String getStringValue(JsonObject input, String keyID, boolean isRequired) throws SLCommandoParserException { - try { - JsonElement internal = getAndCheck(input, keyID, isRequired); - - if (internal != null) - return internal.getAsString(); - else - return null; - - } catch (SLCommandoParserException e) { - throw e; - - } catch (Exception e) { - throw new SLCommandoParserException("Can not extract String value with keyId: " + keyID, e); - - } - } - - /** - * Extract Boolean value from JSON - * - * @param input - * @param keyID - * @param isRequired - * @return - * @throws SLCommandoParserException - */ - public static boolean getBooleanValue(JsonObject input, String keyID, boolean isRequired, boolean defaultValue) throws SLCommandoParserException { - try { - JsonElement internal = getAndCheck(input, keyID, isRequired); - - if (internal != null) - return internal.getAsBoolean(); - else - return defaultValue; - - } catch (SLCommandoParserException e) { - throw e; - - } catch (Exception e) { - throw new SLCommandoParserException("Can not extract Boolean value with keyId: " + keyID, e); - - } - } - - /** - * Extract JSONObject value from JSON - * - * @param input - * @param keyID - * @param isRequired - * @return - * @throws SLCommandoParserException - */ - public static JsonObject getJSONObjectValue(JsonObject input, String keyID, boolean isRequired) throws SLCommandoParserException { - try { - JsonElement internal = getAndCheck(input, keyID, isRequired); - - if (internal != null) - return internal.getAsJsonObject(); - else - return null; - - } catch (SLCommandoParserException e) { - throw e; - - } catch (Exception e) { - throw new SLCommandoParserException("Can not extract Boolean value with keyId: " + keyID, e); - - } - } - - /** - * Extract a List of String elements from a JSON element - * - * @param input - * @return - * @throws SLCommandoParserException - */ - public static List<String> getListOfStringElements(JsonElement input) throws SLCommandoParserException { - List<String> result = new ArrayList<String>(); - if (input != null) { - if (input.isJsonArray()) { - Iterator<JsonElement> arrayIterator = input.getAsJsonArray().iterator(); - while(arrayIterator.hasNext()) { - JsonElement next = arrayIterator.next(); - if (next.isJsonPrimitive()) - result.add(next.getAsString()); - } - - } else if (input.isJsonPrimitive()) { - result.add(input.getAsString()); - - } else { - log.warn("JSON Element IS NOT a JSON array or a JSON Primitive"); - throw new SLCommandoParserException("JSON Element IS NOT a JSON array or a JSON Primitive"); - - } - } - - return result; - } - - /** - * Extract Map of Key/Value pairs from a JSON Element - * - * @param input parent JSON object - * @param keyID KeyId of the child that should be parsed - * @param isRequired - * @return - * @throws SLCommandoParserException - */ - public static Map<String, String> getMapOfStringElements(JsonObject input, String keyID, boolean isRequired) throws SLCommandoParserException { - JsonElement internal = getAndCheck(input, keyID, isRequired); - return getMapOfStringElements(internal); - - } - - /** - * Extract Map of Key/Value pairs from a JSON Element - * - * @param input - * @return - * @throws SLCommandoParserException - */ - public static Map<String, String> getMapOfStringElements(JsonElement input) throws SLCommandoParserException { - Map<String, String> result = new HashMap<String, String>(); - - if (input != null) { - if (input.isJsonArray()) { - Iterator<JsonElement> arrayIterator = input.getAsJsonArray().iterator(); - while(arrayIterator.hasNext()) { - JsonElement next = arrayIterator.next(); - Iterator<Entry<String, JsonElement>> entry = next.getAsJsonObject().entrySet().iterator(); - entitySetToMap(result, entry); - - } - - } else if (input.isJsonObject()) { - Iterator<Entry<String, JsonElement>> objectKeys = input.getAsJsonObject().entrySet().iterator(); - entitySetToMap(result, objectKeys); - - } else - throw new SLCommandoParserException("JSON Element IS NOT a JSON array or a JSON object"); - - } - - return result; - } - - private static void entitySetToMap(Map<String, String> result, Iterator<Entry<String, JsonElement>> entry) { - while (entry.hasNext()) { - Entry<String, JsonElement> el = entry.next(); - if (result.containsKey(el.getKey())) - log.info("Attr. Map already contains Element with Key: " + el.getKey() + ". Overwrite element ... "); - - result.put(el.getKey(), el.getValue().getAsString()); - - } - - } - - - public static JsonElement extractSL20Result(JsonObject command, IJOSETools decrypter, boolean mustBeEncrypted) throws SL20Exception { - JsonElement result = command.get(SL20Constants.SL20_COMMAND_CONTAINER_RESULT); - JsonElement encryptedResult = command.get(SL20Constants.SL20_COMMAND_CONTAINER_ENCRYPTEDRESULT); - - if (result == null && encryptedResult == null) - throw new SLCommandoParserException("NO result OR encryptedResult FOUND."); - - else if (encryptedResult == null && mustBeEncrypted) - throw new SLCommandoParserException("result MUST be signed."); - - else if (encryptedResult != null && encryptedResult.isJsonPrimitive()) { - try { - return decrypter.decryptPayload(encryptedResult.getAsString()); - - } catch (Exception e) { - log.info("Can NOT decrypt SL20 result. Reason:" + e.getMessage()); - if (!mustBeEncrypted) { - log.warn("Decrypted results are disabled by configuration. Parse result in plain if it is possible"); - - //dummy code - try { - String[] signedPayload = encryptedResult.toString().split("\\."); - JsonElement payLoad = new JsonParser().parse(new String(Base64.getUrlDecoder().decode(signedPayload[1]))); - return payLoad; - - } catch (Exception e1) { - log.debug("DummyCode FAILED, Reason: " + e1.getMessage() + " Ignore it ..."); - throw new SL20Exception(e.getMessage(), null, e); - - } - - } else - throw e; - - } - - } else if (result != null) { - return result; - - } else - throw new SLCommandoParserException("Internal build error"); - - - } - - /** - * Extract payLoad from generic transport container - * - * @param container - * @param joseTools - * @return - * @throws SLCommandoParserException - */ - public static VerificationResult extractSL20PayLoad(JsonObject container, IJOSETools joseTools, boolean mustBeSigned) throws SL20Exception { - - JsonElement sl20Payload = container.get(SL20Constants.SL20_PAYLOAD); - JsonElement sl20SignedPayload = container.get(SL20Constants.SL20_SIGNEDPAYLOAD); - - if (mustBeSigned && joseTools == null) - throw new SLCommandoParserException("'joseTools' MUST be set if 'mustBeSigned' is 'true'"); - - if (sl20Payload == null && sl20SignedPayload == null) - throw new SLCommandoParserException("NO payLoad OR signedPayload FOUND."); - - else if (sl20SignedPayload == null && mustBeSigned) - throw new SLCommandoParserException("payLoad MUST be signed."); - - else if (joseTools != null && sl20SignedPayload != null && sl20SignedPayload.isJsonPrimitive()) { - return joseTools.validateSignature(sl20SignedPayload.getAsString()); - - } else if (sl20Payload != null) - return new VerificationResult(sl20Payload.getAsJsonObject()); - - else - throw new SLCommandoParserException("Internal build error"); - - - } - - - /** - * Extract generic transport container from httpResponse - * - * @param httpResp - * @return - * @throws SLCommandoParserException - */ - public static JsonObject getSL20ContainerFromResponse(HttpResponse httpResp) throws SLCommandoParserException { - try { - JsonObject sl20Resp = null; - if (httpResp.getStatusLine().getStatusCode() == 307) { - Header[] locationHeader = httpResp.getHeaders("Location"); - if (locationHeader == null) - throw new SLCommandoParserException("Find Redirect statuscode but not Location header"); - - String sl20RespString = new URIBuilder(locationHeader[0].getValue()).getQueryParams().get(0).getValue(); - sl20Resp = new JsonParser().parse(Base64Url.encode((sl20RespString.getBytes()))).getAsJsonObject(); - - } else if (httpResp.getStatusLine().getStatusCode() == 200) { - if (!httpResp.getEntity().getContentType().getValue().startsWith("application/json")) - throw new SLCommandoParserException("SL20 response with a wrong ContentType: " + httpResp.getEntity().getContentType().getValue()); - sl20Resp = parseSL20ResultFromResponse(httpResp.getEntity()); - - } else if ( (httpResp.getStatusLine().getStatusCode() == 500) || - (httpResp.getStatusLine().getStatusCode() == 401) || - (httpResp.getStatusLine().getStatusCode() == 400) ) { - log.info("SL20 response with http-code: " + httpResp.getStatusLine().getStatusCode() - + ". Search for error message"); - sl20Resp = parseSL20ResultFromResponse(httpResp.getEntity()); - - - } else - throw new SLCommandoParserException("SL20 response with http-code: " + httpResp.getStatusLine().getStatusCode()); - - log.info("Find JSON object in http response"); - return sl20Resp; - - } catch (Exception e) { - throw new SLCommandoParserException("SL20 response parsing FAILED! Reason: " + e.getMessage(), e); - - } - } - - private static JsonObject parseSL20ResultFromResponse(HttpEntity resp) throws Exception { - if (resp != null && resp.getContent() != null) { - JsonElement sl20Resp = new JsonParser().parse(new InputStreamReader(resp.getContent())); - if (sl20Resp != null && sl20Resp.isJsonObject()) { - return sl20Resp.getAsJsonObject(); - - } else - throw new SLCommandoParserException("SL2.0 can NOT parse to a JSON object"); - - - } else - throw new SLCommandoParserException("Can NOT find content in http response"); - - } - - - private static JsonElement getAndCheck(JsonObject input, String keyID, boolean isRequired) throws SLCommandoParserException { - JsonElement internal = input.get(keyID); - - if (internal == null && isRequired) - throw new SLCommandoParserException("REQUIRED Element with keyId: " + keyID + " does not exist"); - - return internal; - - } + + /** + * Extract String value from JSON + * + * @param input + * @param keyID + * @param isRequired + * @return + * @throws SLCommandoParserException + */ + public static String getStringValue(JsonObject input, String keyID, boolean isRequired) + throws SLCommandoParserException { + try { + final JsonElement internal = getAndCheck(input, keyID, isRequired); + + if (internal != null) { + return internal.getAsString(); + } else { + return null; + } + + } catch (final SLCommandoParserException e) { + throw e; + + } catch (final Exception e) { + throw new SLCommandoParserException("Can not extract String value with keyId: " + keyID, e); + + } + } + + /** + * Extract Boolean value from JSON + * + * @param input + * @param keyID + * @param isRequired + * @return + * @throws SLCommandoParserException + */ + public static boolean getBooleanValue(JsonObject input, String keyID, boolean isRequired, + boolean defaultValue) throws SLCommandoParserException { + try { + final JsonElement internal = getAndCheck(input, keyID, isRequired); + + if (internal != null) { + return internal.getAsBoolean(); + } else { + return defaultValue; + } + + } catch (final SLCommandoParserException e) { + throw e; + + } catch (final Exception e) { + throw new SLCommandoParserException("Can not extract Boolean value with keyId: " + keyID, e); + + } + } + + /** + * Extract JSONObject value from JSON + * + * @param input + * @param keyID + * @param isRequired + * @return + * @throws SLCommandoParserException + */ + public static JsonObject getJSONObjectValue(JsonObject input, String keyID, boolean isRequired) + throws SLCommandoParserException { + try { + final JsonElement internal = getAndCheck(input, keyID, isRequired); + + if (internal != null) { + return internal.getAsJsonObject(); + } else { + return null; + } + + } catch (final SLCommandoParserException e) { + throw e; + + } catch (final Exception e) { + throw new SLCommandoParserException("Can not extract Boolean value with keyId: " + keyID, e); + + } + } + + /** + * Extract a List of String elements from a JSON element + * + * @param input + * @return + * @throws SLCommandoParserException + */ + public static List<String> getListOfStringElements(JsonElement input) throws SLCommandoParserException { + final List<String> result = new ArrayList<>(); + if (input != null) { + if (input.isJsonArray()) { + final Iterator<JsonElement> arrayIterator = input.getAsJsonArray().iterator(); + while (arrayIterator.hasNext()) { + final JsonElement next = arrayIterator.next(); + if (next.isJsonPrimitive()) { + result.add(next.getAsString()); + } + } + + } else if (input.isJsonPrimitive()) { + result.add(input.getAsString()); + + } else { + log.warn("JSON Element IS NOT a JSON array or a JSON Primitive"); + throw new SLCommandoParserException("JSON Element IS NOT a JSON array or a JSON Primitive"); + + } + } + + return result; + } + + /** + * Extract Map of Key/Value pairs from a JSON Element + * + * @param input parent JSON object + * @param keyID KeyId of the child that should be parsed + * @param isRequired + * @return + * @throws SLCommandoParserException + */ + public static Map<String, String> getMapOfStringElements(JsonObject input, String keyID, boolean isRequired) + throws SLCommandoParserException { + final JsonElement internal = getAndCheck(input, keyID, isRequired); + return getMapOfStringElements(internal); + + } + + /** + * Extract Map of Key/Value pairs from a JSON Element + * + * @param input + * @return + * @throws SLCommandoParserException + */ + public static Map<String, String> getMapOfStringElements(JsonElement input) + throws SLCommandoParserException { + final Map<String, String> result = new HashMap<>(); + + if (input != null) { + if (input.isJsonArray()) { + final Iterator<JsonElement> arrayIterator = input.getAsJsonArray().iterator(); + while (arrayIterator.hasNext()) { + final JsonElement next = arrayIterator.next(); + final Iterator<Entry<String, JsonElement>> entry = next.getAsJsonObject().entrySet().iterator(); + entitySetToMap(result, entry); + + } + + } else if (input.isJsonObject()) { + final Iterator<Entry<String, JsonElement>> objectKeys = input.getAsJsonObject().entrySet().iterator(); + entitySetToMap(result, objectKeys); + + } else { + throw new SLCommandoParserException("JSON Element IS NOT a JSON array or a JSON object"); + } + + } + + return result; + } + + private static void entitySetToMap(Map<String, String> result, Iterator<Entry<String, JsonElement>> entry) { + while (entry.hasNext()) { + final Entry<String, JsonElement> el = entry.next(); + if (result.containsKey(el.getKey())) { + log.info("Attr. Map already contains Element with Key: " + el.getKey() + ". Overwrite element ... "); + } + + result.put(el.getKey(), el.getValue().getAsString()); + + } + + } + + public static JsonElement extractSL20Result(JsonObject command, IJOSETools decrypter, + boolean mustBeEncrypted) throws SL20Exception { + final JsonElement result = command.get(SL20Constants.SL20_COMMAND_CONTAINER_RESULT); + final JsonElement encryptedResult = command.get(SL20Constants.SL20_COMMAND_CONTAINER_ENCRYPTEDRESULT); + + if (result == null && encryptedResult == null) { + throw new SLCommandoParserException("NO result OR encryptedResult FOUND."); + } else if (encryptedResult == null && mustBeEncrypted) { + throw new SLCommandoParserException("result MUST be signed."); + } else if (encryptedResult != null && encryptedResult.isJsonPrimitive()) { + try { + return decrypter.decryptPayload(encryptedResult.getAsString()); + + } catch (final Exception e) { + log.info("Can NOT decrypt SL20 result. Reason:" + e.getMessage()); + if (!mustBeEncrypted) { + log.warn( + "Decrypted results are disabled by configuration. Parse result in plain if it is possible"); + + // dummy code + try { + final String[] signedPayload = encryptedResult.toString().split("\\."); + final JsonElement payLoad = new JsonParser().parse(new String(Base64.getUrlDecoder().decode( + signedPayload[1]))); + return payLoad; + + } catch (final Exception e1) { + log.debug("DummyCode FAILED, Reason: " + e1.getMessage() + " Ignore it ..."); + throw new SL20Exception(e.getMessage(), null, e); + + } + + } else { + throw e; + } + + } + + } else if (result != null) { + return result; + + } else { + throw new SLCommandoParserException("Internal build error"); + } + + } + + /** + * Extract payLoad from generic transport container + * + * @param container + * @param joseTools + * @return + * @throws SLCommandoParserException + */ + public static VerificationResult extractSL20PayLoad(JsonObject container, IJOSETools joseTools, + boolean mustBeSigned) throws SL20Exception { + + final JsonElement sl20Payload = container.get(SL20Constants.SL20_PAYLOAD); + final JsonElement sl20SignedPayload = container.get(SL20Constants.SL20_SIGNEDPAYLOAD); + + if (mustBeSigned && joseTools == null) { + throw new SLCommandoParserException("'joseTools' MUST be set if 'mustBeSigned' is 'true'"); + } + + if (sl20Payload == null && sl20SignedPayload == null) { + throw new SLCommandoParserException("NO payLoad OR signedPayload FOUND."); + } else if (sl20SignedPayload == null && mustBeSigned) { + throw new SLCommandoParserException("payLoad MUST be signed."); + } else if (joseTools != null && sl20SignedPayload != null && sl20SignedPayload.isJsonPrimitive()) { + return joseTools.validateSignature(sl20SignedPayload.getAsString()); + + } else if (sl20Payload != null) { + return new VerificationResult(sl20Payload.getAsJsonObject()); + } else { + throw new SLCommandoParserException("Internal build error"); + } + + } + + /** + * Extract generic transport container from httpResponse + * + * @param httpResp + * @return + * @throws SLCommandoParserException + */ + public static JsonObject getSL20ContainerFromResponse(HttpResponse httpResp) + throws SLCommandoParserException { + try { + JsonObject sl20Resp = null; + if (httpResp.getStatusLine().getStatusCode() == 307) { + final Header[] locationHeader = httpResp.getHeaders("Location"); + if (locationHeader == null) { + throw new SLCommandoParserException("Find Redirect statuscode but not Location header"); + } + + final String sl20RespString = new URIBuilder(locationHeader[0].getValue()).getQueryParams().get(0) + .getValue(); + sl20Resp = new JsonParser().parse(Base64Url.encode(sl20RespString.getBytes())).getAsJsonObject(); + + } else if (httpResp.getStatusLine().getStatusCode() == 200) { + if (!httpResp.getEntity().getContentType().getValue().startsWith("application/json")) { + throw new SLCommandoParserException("SL20 response with a wrong ContentType: " + httpResp + .getEntity().getContentType().getValue()); + } + sl20Resp = parseSL20ResultFromResponse(httpResp.getEntity()); + + } else if (httpResp.getStatusLine().getStatusCode() == 500 || + httpResp.getStatusLine().getStatusCode() == 401 || + httpResp.getStatusLine().getStatusCode() == 400) { + log.info("SL20 response with http-code: " + httpResp.getStatusLine().getStatusCode() + + ". Search for error message"); + sl20Resp = parseSL20ResultFromResponse(httpResp.getEntity()); + + } else { + throw new SLCommandoParserException("SL20 response with http-code: " + httpResp.getStatusLine() + .getStatusCode()); + } + + log.info("Find JSON object in http response"); + return sl20Resp; + + } catch (final Exception e) { + throw new SLCommandoParserException("SL20 response parsing FAILED! Reason: " + e.getMessage(), e); + + } + } + + private static JsonObject parseSL20ResultFromResponse(HttpEntity resp) throws Exception { + if (resp != null && resp.getContent() != null) { + final JsonElement sl20Resp = new JsonParser().parse(new InputStreamReader(resp.getContent())); + if (sl20Resp != null && sl20Resp.isJsonObject()) { + return sl20Resp.getAsJsonObject(); + + } else { + throw new SLCommandoParserException("SL2.0 can NOT parse to a JSON object"); + } + + } else { + throw new SLCommandoParserException("Can NOT find content in http response"); + } + + } + + private static JsonElement getAndCheck(JsonObject input, String keyID, boolean isRequired) + throws SLCommandoParserException { + final JsonElement internal = input.get(keyID); + + if (internal == null && isRequired) { + throw new SLCommandoParserException("REQUIRED Element with keyId: " + keyID + " does not exist"); + } + + return internal; + + } } |