diff --git a/README.md b/README.md index f1fe723d..670cfb5d 100644 --- a/README.md +++ b/README.md @@ -8,12 +8,29 @@ Issuer can configure their respective credential schema for various types of cer - Link to [Stoplight](https://mosip.stoplight.io/docs/inji-certify/25f435617408e-inji-certify) -# Requirements to run it locally (without docker) +# Requirements to run it locally (with docker compose) -- Java SE 21 -- Postgres -- Maven -- Redis, _if an Authorization provider like eSignet is also deployed_ +Instructions [here](./docker-compose/docker-compose-injistack/README.md). + +### Steps to configure postgres-dataprovider-plugin +- Supported versions: 0.3.0 and above +- Download the latest JAR from: + ``` + https://oss.sonatype.org/content/repositories/snapshots/io/mosip/certify/postgres-dataprovider-plugin/0.3.0-SNAPSHOT/ + ``` +- Refer to the documentation of postgres plugin for required configurations: [Postgres Plugin Doc](https://github.com/mosip/digital-credential-plugins/blob/release-0.3.x/postgres-dataprovider-plugin/README.md) + +### For Advanced Users: Create Custom Plugin + +You can create your own plugin by implementing the following interface and refer the below for postgres-dataprovider-plugin implementation: + +Reference Implementation: [postgres-dataprovider-plugin](https://github.com/mosip/digital-credential-plugins/tree/release-0.3.x/postgres-dataprovider-plugin). + +```java +public interface DataProviderPlugin { + // Implement your custom logic here +} +``` ## Databases @@ -23,183 +40,6 @@ Refer to [SQL scripts](db_scripts) and go through it's README The following steps will help you to setup Sunbird RC and Esignet services using Docker compose alongwith Certify. -## Requirements - -* Docker (26.0.0) -* Docker Compose (2.25) -* [Git bash](https://gitforwindows.org/) shell to run the scripts, if on _Windows_ -* [GNU sed](https://formulae.brew.sh/formula/gnu-sed) installed, if on _Mac_ -* A URL to host your DID for verifying VCs, can use [GitHub pages](https://docs.github.com/en/pages/quickstart) here or any other self hosted server which is highly available for use by verifiers. - - -## Pre-requisites - -1. [Postman](https://www.postman.com/) with [postman utility lib](https://github.com/joolfe/postman-util-lib/blob/master/postman/PostmanUtilityLibv21.postman_collection.json) [setup](https://joolfe.github.io/postman-util-lib/) -2. [Git bash](https://gitforwindows.org/) shell to run the scripts, if on _Windows_ -3. [GNU sed](https://formulae.brew.sh/formula/gnu-sed) installed, if on _Mac_. Also replace all instances of `sed ` with `gsed ` in the `setup_vault.sh`. -4. A URL to host your DID for verifying VCs, can use [GitHub pages](https://docs.github.com/en/pages/quickstart) here or any other self hosted server which is highly available for use by verifiers. - -### Steps to setup Mock credential use case - -1. Clone this repository and navigate to its directory: - - NOTE(Apple Silicon Mac users): need to run the containers in linux/amd64 mode; prior to running the script run, `export DOCKER_DEFAULT_PLATFORM=linux/amd64` - - NOTE(windows users only): need to run the commands only in `git bash` shell - - ```bash - cd inji-certify/docker-compose - ``` - -2. Change the variable `active_profile_env` in [esignet](docker-compose/docker-compose-certify/docker-compose.yml#L80) and [certify](docker-compose/docker-compose-certify/docker-compose.yml#L104) to `active_profile_env=default,mock-identity` -3. Esignet and Certify takes the required plugin from artifactory server by default, in case there is a custom use case where plugin is to be added manually should a need arise for trying out their own plugins - * Create a folder with name loader_path [here](docker-compose/docker-compose-certify). - * Add the jar file of Digital Credential Stack(DCS) plugin implementations for eSignet and certify: - * For eSignet: - * In the [docker compose file](docker-compose/docker-compose-certify/docker-compose.yml) comment the line [esignet_wrapper_url_env](docker-compose/docker-compose-certify/docker-compose.yml#L83) - * create a folder with name esignet inside loader_path folder created in the above step and add the jar files inside the folder. - * JAR file for mock identity can be downloaded [here](https://repo1.maven.org/maven2/io/mosip/esignet/mock/mock-esignet-integration-impl/0.9.2/mock-esignet-integration-impl-0.9.2.jar) - * For certify: - * In the [docker compose file](docker-compose/docker-compose-certify/docker-compose.yml) uncomment the [enable_certify_artifactory](docker-compose/docker-compose-certify/docker-compose.yml#L107) and [volume](docker-compose/docker-compose-certify/docker-compose.yml#L114) - * create a folder with name certify inside loader_path folder created in the above step and add the jar file inside the folder. - * The JAR can be built [from source](https://github.com/mosip/digital-credential-plugins/tree/develop/mock-certify-plugin). -4. Execute the installation script located inside the [docker-compose](./docker-compose/) directory to install the Registry & Credentialling Service. - - ```bash - ./install.sh - ``` - -5. During the execution of the `install.sh` script, user will be prompted to select the service to be installed: - - ``` - 1. Sunbird RC - 2. Certify - 0. Exit - Select: - ``` - -6. Select "Certify" from the choices provided. -7. The installation of Certify will encompass the following services: - * [Esignet Service](https://github.com/mosip/esignet) - * [Certify Service](https://github.com/mosip/inji-certify) -8. Download the postman collection and environment for mock use case from [here](docs/postman-collections/mock). -9. Create Client from Create OIDC client API. -10. Create a mock identity with Create Mock Identity API in the Mock Identity System folder. -11. Change the `individualId` variable in environment to the above created mock identity identifier. -12. Perform a Mock Authentication with the API's in `VCI` folder as specified in the Postman collection. - - -### Steps to setup Insurance credential use case - -Execute installation script - -1. Clone the repository and navigate to its directory: - - ```bash - cd inji-certify/docker-compose - ./install.sh - ``` - -2. During the execution of the `install.sh` script, user will be prompted to select the service to be installed: - - ``` - 1. Sunbird RC - 2. Certify - 0. Exit - Select: - ``` - -3. Select "Sunbird RC" as the first step of the installation process. - -4. The installation will encompass the following services: - * [Credential Schema](https://github.com/Sunbird-RC/sunbird-rc-core/tree/main/services/credential-schema) - * [Credential Service](https://github.com/Sunbird-RC/sunbird-rc-core/tree/main/services/credentials-service) - * [Identity Service](https://github.com/Sunbird-RC/sunbird-rc-core/tree/main/services/identity-service) - * [Registry](https://github.com/Sunbird-RC/sunbird-rc-core) -5. Post Sunbird installation, proceed to create an issuer and credential schema. Refer to the API schemas available [here](https://github.com/Sunbird-RC/sunbird-rc-core/tree/main/api-documentation) via this [Postman collection](https://github.com/Sunbird-RC/demo-mosip-rc/blob/main/Demo%20Mosip%20RC.postman_collection.json) or by looking at API schemas. - * Set the individual service URLs of the identity, registry, credential service correctly as per your setup. - * Now generate a DID(POST /did/generate), create a credential schema(POST /credential-schema) and create an issuance registry. - * take note of `$.schema[0].author` and `$.schema[0].id` from the create credential schema request - * host the output of the JSON to the GitHub pages repo created earlier -6. Change the variable `active_profile_env` in [esignet](docker-compose/docker-compose-certify/docker-compose.yml#L80) and [certify](docker-compose/docker-compose-certify/docker-compose.yml#L104) to `active_profile_env=default,sunbird-insurance` -7. Esignet and Certify takes the required plugin from artifactory server by default, in case there is a custom use case where plugin is to be added manually follow the below steps: - * Create a folder with name loader_path [here](docker-compose/docker-compose-certify). - * Add the jar file of Digital Credential Stack(DCS) plugin implementations for eSignet and certify: - * For eSignet: - * In the [docker compose file](docker-compose/docker-compose-certify/docker-compose.yml) comment the line [esignet_wrapper_url_env](docker-compose/docker-compose-certify/docker-compose.yml#L82) - * create a folder with name esignet inside loader_path folder created in the above step and add the jar files inside the folder. - * JAR file for sunbird can be downloaded [here](https://mvnrepository.com/artifact/io.mosip.esignet.sunbirdrc/sunbird-rc-esignet-integration-impl). - * For certify: - * In the [docker compose file](docker-compose/docker-compose-certify/docker-compose.yml) uncomment the [enable_certify_artifactory](docker-compose/docker-compose-certify/docker-compose.yml#L106) and [volume](docker-compose/docker-compose-certify/docker-compose.yml#L113) - * create a folder with name certify inside loader_path folder created in the above step and add the jar file inside the folder. - * The JAR can be built [from source](https://github.com/mosip/digital-credential-plugins/tree/develop/sunbird-rc-certify-integration-impl). -8. Modify the properties of the Esignet and Certify services located in the [esignet-sunbird-insurance.properties](docker-compose/docker-compose-certify/config/esignet-sunbird-insurance.properties) and [certify-sunbird-insurance.properties](docker-compose/docker-compose-certify/config/certify-sunbird-insurance.properties) files respectively. - - Include Issuer ID and credential schema ID for the following properties: - - esignet-default-properties: - - `mosip.esignet.vciplugin.sunbird-rc.credential-type.{credential type}.static-value-map.issuerId`. - - `mosip.esignet.vciplugin.sunbird-rc.credential-type.{credential-type}.cred-schema-id`. - - certify-default.properties: - - `mosip.certify.vciplugin.sunbird-rc.credential-type.{credential type}.static-value-map.issuerId`. - - `mosip.certify.vciplugin.sunbird-rc.credential-type.{credential-type}.cred-schema-id`. - - The `$.schema[0].author` DID goes to the config ending in issuerId and `$.schema[0].id` DID goes to the config ending in `cred-schema-id`. -9. Once the Esignet and Certify properties are configured, proceed to select **Certify** from the option provided in the installation steps while running `install.sh` again. -10. The installation of Certify will encompass the following services: - * [Esignet Service](https://github.com/mosip/esignet) - * [Certify Service](https://github.com/mosip/inji-certify) -11. Download the postman collection and environment for sunbird use case from [here](docs/postman-collections/sunbird). - * Change `aud` variable in environment to the token endpoint of your Authorization service which is 'http://localhost:8088/v1/esignet/oauth/v2/token' if eSignet is setup locally and set `audUrl` to the URL of Certify container which is http://localhost:8090 if setup locally. -12. Create Client from Create OIDC client API, and set redirect-url to 'http://localhost:3001' or the URL of OIDC-UI service, set auth-factor 'mosip:idp:acr:knowledge' to the request body. -13. Perform a Knowledge based authentication(KBA) as specified in the Postman collection. - * perform the authorize callback request - * in the /authorization/authenticate request update the challenge to a **URL-safe base64 encoded string** with the KBA details such as `{"fullName":"Abhishek Gangwar","dob":"1967-10-24"}`, one can use an [online base64 encoding service](https://base64encode.org) for the same. - - -## Properties for custom use case - -- Sample schemas for Insurance registry are provided [here](docker-compose/docker-compose-sunbird/schemas), change it according to use case. -- Change these properties for different use case `mosip.esignet.authenticator.sunbird-rc.auth-factor.kba.field-details`,`mosip.esignet.authenticator.sunbird-rc.auth-factor.kba.individual-id-field` -- Add the Sunbird registry URL for these properties: `mosip.esignet.vciplugin.sunbird-rc.issue-credential-url`,`mosip.esignet.authenticator.sunbird-rc.auth-factor.kba.registry-search-url`. -- Specify the list of supported credential types for these properties: - - esignet-default-properties: - - `mosip.esignet.vciplugin.sunbird-rc.supported-credential-types`. - - certify-default.properties: - - `mosip.certify.vciplugin.sunbird-rc.supported-credential-types`. -- For each supported credential type change the below properties. Sample properties are provided in the [eSignet default properties](docker-compose/docker-compose-certify/config/esignet-default.properties) and [Certify default properties](docker-compose/docker-compose-certify/config/certify-default.properties). - * esignet-default-properties: - * Issuer id `mosip.esignet.vciplugin.sunbird-rc.credential-type.{credential type}.static-value-map.issuerId` - * Credential schema id `mosip.esignet.vciplugin.sunbird-rc.credential-type.{credential type}.cred-schema-id` - * Registry Url `mosip.esignet.vciplugin.sunbird-rc.credential-type.{credential type}.registry-get-url` - * Template Url `mosip.esignet.vciplugin.sunbird-rc.credential-type.{credential type}.template-url` - * Credential schema version `mosip.esignet.vciplugin.sunbird-rc.credential-type.{credential type}.cred-schema-version` - * Define the list of supported scopes using: `mosip.esignet.supported.credential.scopes`, and for each scope, map the resource accordingly at `mosip.esignet.credential.scope-resource-mapping`. - * Change these properties for different credential types supported `mosip.esignet.vci.key-values` based on OID4VCI version. - * certify-default-properties: - * Issuer id `mosip.certify.vciplugin.sunbird-rc.credential-type.{credential type}.static-value-map.issuerId` - * Credential schema id `mosip.certify.vciplugin.sunbird-rc.credential-type.{credential type}.cred-schema-id` - * Registry Url `mosip.certify.vciplugin.sunbird-rc.credential-type.{credential type}.registry-get-url` - * Template Url `mosip.certify.vciplugin.sunbird-rc.credential-type.{credential type}.template-url` - * Credential schema version `mosip.certify.vciplugin.sunbird-rc.credential-type.{credential type}.cred-schema-version` - * Change these properties for different credential types supported `mosip.certify.key-values` based on OID4VCI version. - -## Web interface for VC Issuance (optional) - - - To test the Setup from UI we can configure a Client and Issuer in InjiWeb. - * Setup [InjiWeb](https://github.com/mosip/inji-web/blob/qa-develop/README.md) and [Mimoto](https://github.com/mosip/mimoto/blob/release-0.13.x/docker-compose/README.md) in local. - * Add an issuer to mimoto issuer config with `authorization_endpoint`, `credential_endpoint` and `.well-known` properties pointing to eSignet and certify installed above. - * Add the private key from the OIDC client created in eSignet(collection to create a client can be found [here](docker-compose/docker-compose-certify/postman-collections)) to the p12 file in mimoto. - * You will be able to see the newly created issuer in InjiWeb home page to download the credential. - - - For this release Mosip ID and Mock plugins are using eSignet DTO's due to shared redis cache dependency to resolve serialization issues, so eSignet image tag version in docker compose should be in consistent with Mock and Mosip ID pom dependency version.As of now we are using eSignet 1.4.1 in docker compose as well as plugins in artifactory - - [Mosip ID](https://github.com/mosip/digital-credential-plugins/blob/a96fada5b8eefa00282cadab1c698f429223c0b3/mosip-identity-certify-plugin/pom.xml#L148) - - [Mock](https://github.com/mosip/digital-credential-plugins/blob/a96fada5b8eefa00282cadab1c698f429223c0b3/mock-certify-plugin/pom.xml#L75) - - -## Troubleshooting - -- `invalid_proof` error while downloading credentials --> check the `audUrl` value, it should be the hostname of the injicertify instance -- `invalid_assertion` at the token endpoint of eSignet --> check the `aud` env value -- while using Postman do check if an Environment is set for the pre & post request scripts to be able to carry forward & override the variables; and set the correct Hostnames and other entities correctly via the Variables section for a Postman collection - ## Helm Deployments * The links for installation through helm can be found here diff --git a/api-test/pom.xml b/api-test/pom.xml index cb66871a..77658562 100644 --- a/api-test/pom.xml +++ b/api-test/pom.xml @@ -2,13 +2,13 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - io.mosip.injicertify + io.mosip.certify apitest-injicertify jar apitest-injicertify Parent project of apitest-injicertify https://github.com/mosip/inji-certify - 0.9.0-SNAPSHOT + 0.10.0-SNAPSHOT @@ -51,7 +51,7 @@ 2.2.1 3.0.1 - apitest-injicertify-0.9.0-SNAPSHOT-jar-with-dependencies + apitest-injicertify-0.10.0-SNAPSHOT-jar-with-dependencies diff --git a/api-test/src/main/java/io/mosip/testrig/apirig/injicertify/testrunner/MosipTestRunner.java b/api-test/src/main/java/io/mosip/testrig/apirig/injicertify/testrunner/MosipTestRunner.java index e7ff7b56..99a28d4a 100644 --- a/api-test/src/main/java/io/mosip/testrig/apirig/injicertify/testrunner/MosipTestRunner.java +++ b/api-test/src/main/java/io/mosip/testrig/apirig/injicertify/testrunner/MosipTestRunner.java @@ -10,7 +10,6 @@ import java.security.PublicKey; import java.security.interfaces.RSAPublicKey; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.Properties; @@ -27,7 +26,6 @@ import io.mosip.testrig.apirig.dbaccess.DBManager; import io.mosip.testrig.apirig.injicertify.utils.InjiCertifyConfigManager; import io.mosip.testrig.apirig.injicertify.utils.InjiCertifyUtil; -import io.mosip.testrig.apirig.report.EmailableReport; import io.mosip.testrig.apirig.testrunner.BaseTestCase; import io.mosip.testrig.apirig.testrunner.ExtractResource; import io.mosip.testrig.apirig.testrunner.HealthChecker; diff --git a/api-test/src/main/java/io/mosip/testrig/apirig/injicertify/utils/InjiCertifyUtil.java b/api-test/src/main/java/io/mosip/testrig/apirig/injicertify/utils/InjiCertifyUtil.java index 8e2e689b..49250bfd 100644 --- a/api-test/src/main/java/io/mosip/testrig/apirig/injicertify/utils/InjiCertifyUtil.java +++ b/api-test/src/main/java/io/mosip/testrig/apirig/injicertify/utils/InjiCertifyUtil.java @@ -637,15 +637,6 @@ public static String getKeyWordFromEndPoint(String endPoint) { return ""; } -// public static String inputstringKeyWordHandeler(String jsonString, String testCaseName) { -// if (jsonString.contains(GlobalConstants.TIMESTAMP)) -// jsonString = replaceKeywordValue(jsonString, GlobalConstants.TIMESTAMP, generateCurrentUTCTimeStamp()); -// -// -// return jsonString; -// -// } - public static String isTestCaseValidForExecution(TestCaseDTO testCaseDTO) { String testCaseName = testCaseDTO.getTestCaseName(); @@ -751,4 +742,4 @@ else if (testCaseName.contains("_Invalid_Exp_")) return proofJWT; } -} \ No newline at end of file +} diff --git a/api-test/src/main/resources/config/injiCertify.properties b/api-test/src/main/resources/config/injiCertify.properties index c067c55a..081b44bc 100644 --- a/api-test/src/main/resources/config/injiCertify.properties +++ b/api-test/src/main/resources/config/injiCertify.properties @@ -13,7 +13,7 @@ signupSettingsEndPoint=/v1/signup/settings actuatorMimotoEndpoint=/residentmobileapp/actuator/env esignetActuatorPropertySection=esignet-default.properties injiCertifyWellKnownEndPoint=/v1/certify/issuance/.well-known/openid-credential-issuer -sunBirdBaseURL=https://registry.dev1.mosip.net +sunBirdBaseURL=https://registry.released.mosip.net # allowed useCaseToExecute values are sunbird,mosipid,mock. useCaseToExecute=sunbird,mosipid,mock #moduleNamePattern=(mimoto|certify|signup|partnermanager|preregistration|resident|residentmobileapp|masterdata|esignet|idgenerator|policymanager|idauthentication|idrepository|auditmanager|authmanager|keymanager|mock-identity-system) \ No newline at end of file diff --git a/api-test/src/main/resources/injicertify/AddIdentityMock/AddIdentity.hbs b/api-test/src/main/resources/injicertify/AddIdentityMock/AddIdentity.hbs index 814dd81f..bbd00cfd 100644 --- a/api-test/src/main/resources/injicertify/AddIdentityMock/AddIdentity.hbs +++ b/api-test/src/main/resources/injicertify/AddIdentityMock/AddIdentity.hbs @@ -5,6 +5,7 @@ "pin": "{{pin}}", "email": "{{email}}", "phone": "{{phone}}", + "password": "{{password}}", "fullName": [ { "language": "fra", diff --git a/certify-core/pom.xml b/certify-core/pom.xml index aa024db5..d0c661b2 100644 --- a/certify-core/pom.xml +++ b/certify-core/pom.xml @@ -53,48 +53,10 @@ org.springframework.boot spring-boot-starter-cache - - - org.apache.velocity - velocity - 1.7 - - - org.apache.velocity.tools - velocity-tools-generic - 3.1 - - - org.slf4j - slf4j-api - - - org.apache.velocity - velocity-engine-core - - - - - org.springframework.data - spring-data-jpa - - - org.springframework.boot - spring-boot-starter-data-jpa - org.springframework.boot spring-boot-test test - - - jakarta.persistence - jakarta.persistence-api - - - org.springframework.data - spring-data-jpa - - \ No newline at end of file + diff --git a/certify-core/src/main/java/io/mosip/certify/core/constants/Constants.java b/certify-core/src/main/java/io/mosip/certify/core/constants/Constants.java index 933ab5ed..8e810dcf 100644 --- a/certify-core/src/main/java/io/mosip/certify/core/constants/Constants.java +++ b/certify-core/src/main/java/io/mosip/certify/core/constants/Constants.java @@ -9,10 +9,20 @@ public class Constants { public static final String UTC_DATETIME_PATTERN = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"; public static final String SPACE = " "; + public static final String APPLICATION_ID = "applicationId"; + public static final String REFERENCE_ID = "referenceId"; public static final String C_NONCE = "c_nonce"; public static final String C_NONCE_EXPIRES_IN = "c_nonce_expires_in"; public static final String CLIENT_ID = "client_id"; public static final String CERTIFY_PARTNER_APP_ID = "CERTIFY_PARTNER"; public static final String CERTIFY_SERVICE_APP_ID = "CERTIFY_SERVICE"; + public static final String CERTIFY_VC_SIGN_RSA = "CERTIFY_VC_SIGN_RSA"; + public static final String CERTIFY_VC_SIGN_ED25519 = "CERTIFY_VC_SIGN_ED25519"; + public static final String ROOT_KEY = "ROOT"; + public static final String EMPTY_REF_ID = ""; + public static final String ED25519_REF_ID = "ED25519_SIGN"; + public static final String TEMPLATE_NAME = "templateName"; + public static final String ISSUER_URI = "issuerURI"; + public static final String RENDERING_TEMPLATE_ID = "renderingTemplateId"; } diff --git a/certify-core/src/main/java/io/mosip/certify/core/constants/ErrorConstants.java b/certify-core/src/main/java/io/mosip/certify/core/constants/ErrorConstants.java index 0d5dfe12..3b178bf4 100644 --- a/certify-core/src/main/java/io/mosip/certify/core/constants/ErrorConstants.java +++ b/certify-core/src/main/java/io/mosip/certify/core/constants/ErrorConstants.java @@ -22,7 +22,12 @@ public class ErrorConstants { public static final String PROOF_HEADER_INVALID_ALG = "proof_header_invalid_alg"; public static final String PROOF_HEADER_INVALID_KEY = "proof_header_invalid_key"; public static final String PROOF_HEADER_AMBIGUOUS_KEY = "proof_header_ambiguous_key"; - public static final String UNSUPPORTED_OPENID_VERSION = "unsupported_openid4vci_draft_version"; + public static final String UNSUPPORTED_OPENID_VERSION = "unsupported_openid4vci_version"; public static final String INVALID_TEMPLATE_ID = "template_with_id_not_found"; public static final String EMPTY_TEMPLATE_CONTENT = "empty_template_content"; + public static final String EXPECTED_TEMPLATE_NOT_FOUND = "expected_template_not_found"; + public static final String UNSUPPORTED_IN_CURRENT_PLUGIN_MODE = "unsupported_in_current_plugin_mode"; + public static final String UNSUPPORTED_ALGORITHM = "unsupported_algorithm"; + public static final String INVALID_CERTIFICATE = "invalid_certificate"; + public static final String VERIFICATION_METHOD_GENERATION_FAILED = "verification_method_generation_failed"; } diff --git a/certify-core/src/main/java/io/mosip/certify/core/constants/SignatureAlg.java b/certify-core/src/main/java/io/mosip/certify/core/constants/SignatureAlg.java index 1bd89988..c2eea183 100644 --- a/certify-core/src/main/java/io/mosip/certify/core/constants/SignatureAlg.java +++ b/certify-core/src/main/java/io/mosip/certify/core/constants/SignatureAlg.java @@ -7,9 +7,9 @@ */ public class SignatureAlg { // LinkedDataSignature Algorithms - public static final String RSA_SIGNATURE_SUITE = "RsaSignature2018"; + public static final String RSA_SIGNATURE_SUITE_2018 = "RsaSignature2018"; - public static final String ED25519_SIGNATURE_SUITE = "Ed25519Signature2018"; + public static final String ED25519_SIGNATURE_SUITE_2018 = "Ed25519Signature2018"; public static final String ED25519_SIGNATURE_SUITE_2020 = "Ed25519Signature2020"; diff --git a/certify-core/src/main/java/io/mosip/certify/core/exception/RenderingTemplateException.java b/certify-core/src/main/java/io/mosip/certify/core/exception/RenderingTemplateException.java new file mode 100644 index 00000000..423d28bc --- /dev/null +++ b/certify-core/src/main/java/io/mosip/certify/core/exception/RenderingTemplateException.java @@ -0,0 +1,14 @@ +package io.mosip.certify.core.exception; + +public class RenderingTemplateException extends RuntimeException { + private String errorCode; + + public RenderingTemplateException(String errorCode) { + super(errorCode); + this.errorCode = errorCode; + } + + public String getErrorCode() { + return errorCode; + } +} diff --git a/certify-core/src/main/java/io/mosip/certify/core/exception/TemplateException.java b/certify-core/src/main/java/io/mosip/certify/core/exception/TemplateException.java deleted file mode 100644 index cf3e9939..00000000 --- a/certify-core/src/main/java/io/mosip/certify/core/exception/TemplateException.java +++ /dev/null @@ -1,21 +0,0 @@ -package io.mosip.certify.core.exception; - -import io.mosip.certify.core.constants.ErrorConstants; - -public class TemplateException extends RuntimeException { - private String errorCode; - - public TemplateException() { - super(ErrorConstants.UNKNOWN_ERROR); - this.errorCode = ErrorConstants.UNKNOWN_ERROR; - } - - public TemplateException(String errorCode) { - super(errorCode); - this.errorCode = errorCode; - } - - public String getErrorCode() { - return errorCode; - } -} diff --git a/certify-core/src/main/java/io/mosip/certify/core/repository/TemplateRepository.java b/certify-core/src/main/java/io/mosip/certify/core/repository/TemplateRepository.java deleted file mode 100644 index bcef3d65..00000000 --- a/certify-core/src/main/java/io/mosip/certify/core/repository/TemplateRepository.java +++ /dev/null @@ -1,15 +0,0 @@ -package io.mosip.certify.core.repository; - -import io.mosip.certify.core.entity.TemplateData; -import io.mosip.certify.core.entity.TemplateId; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.stereotype.Repository; - -import java.util.Optional; - -@Repository -public interface TemplateRepository extends JpaRepository { - Optional findByCredentialTypeAndContext(String credentialType, String context); - // NOTE: best practice? .save() -} - diff --git a/certify-core/src/main/java/io/mosip/certify/core/spi/SvgTemplateService.java b/certify-core/src/main/java/io/mosip/certify/core/spi/RenderingTemplateService.java similarity index 62% rename from certify-core/src/main/java/io/mosip/certify/core/spi/SvgTemplateService.java rename to certify-core/src/main/java/io/mosip/certify/core/spi/RenderingTemplateService.java index 6b1defa6..07b31647 100644 --- a/certify-core/src/main/java/io/mosip/certify/core/spi/SvgTemplateService.java +++ b/certify-core/src/main/java/io/mosip/certify/core/spi/RenderingTemplateService.java @@ -5,10 +5,8 @@ */ package io.mosip.certify.core.spi; -import io.mosip.certify.core.entity.SvgTemplate; +import io.mosip.certify.api.dto.RenderingTemplateDTO; -import java.util.UUID; - -public interface SvgTemplateService { - SvgTemplate getSvgTemplate(UUID id); +public interface RenderingTemplateService { + RenderingTemplateDTO getSvgTemplate(String id); } diff --git a/certify-core/src/main/java/io/mosip/certify/core/spi/VCIssuanceService.java b/certify-core/src/main/java/io/mosip/certify/core/spi/VCIssuanceService.java index 63aedaeb..c7fa2830 100644 --- a/certify-core/src/main/java/io/mosip/certify/core/spi/VCIssuanceService.java +++ b/certify-core/src/main/java/io/mosip/certify/core/spi/VCIssuanceService.java @@ -20,4 +20,6 @@ public interface VCIssuanceService { CredentialResponse getCredential(CredentialRequest credentialRequest); Map getCredentialIssuerMetadata(String version); + + Map getDIDDocument(); } diff --git a/certify-core/src/main/java/io/mosip/certify/core/validators/CredentialRequestValidator.java b/certify-core/src/main/java/io/mosip/certify/core/validators/CredentialRequestValidator.java deleted file mode 100644 index 48911fdb..00000000 --- a/certify-core/src/main/java/io/mosip/certify/core/validators/CredentialRequestValidator.java +++ /dev/null @@ -1,8 +0,0 @@ -package io.mosip.certify.core.validators; - -import io.mosip.certify.core.constants.VCFormats; -import io.mosip.certify.core.dto.CredentialRequest; - -public interface CredentialRequestValidator { - boolean isValidCheck(CredentialRequest credentialRequest); -} diff --git a/certify-core/src/main/java/io/mosip/certify/core/validators/CredentialRequestValidatorFactory.java b/certify-core/src/main/java/io/mosip/certify/core/validators/CredentialRequestValidatorFactory.java deleted file mode 100644 index a9dce6e2..00000000 --- a/certify-core/src/main/java/io/mosip/certify/core/validators/CredentialRequestValidatorFactory.java +++ /dev/null @@ -1,15 +0,0 @@ -package io.mosip.certify.core.validators; - -import io.mosip.certify.core.constants.VCFormats; -import io.mosip.certify.core.dto.CredentialRequest; - -public class CredentialRequestValidatorFactory { - public boolean isValid(CredentialRequest credentialRequest) { - if (credentialRequest.getFormat().equals(VCFormats.LDP_VC)) { - return new LdpVcCredentialRequestValidator().isValidCheck(credentialRequest); - } else if (credentialRequest.getFormat().equals(VCFormats.MSO_MDOC)) { - return new MsoMdocCredentialRequestValidator().isValidCheck(credentialRequest); - } - return false; - } -} diff --git a/certify-core/src/main/java/io/mosip/certify/core/validators/LdpVcCredentialRequestValidator.java b/certify-core/src/main/java/io/mosip/certify/core/validators/LdpVcCredentialRequestValidator.java deleted file mode 100644 index ac7a747a..00000000 --- a/certify-core/src/main/java/io/mosip/certify/core/validators/LdpVcCredentialRequestValidator.java +++ /dev/null @@ -1,10 +0,0 @@ -package io.mosip.certify.core.validators; - -import io.mosip.certify.core.dto.CredentialRequest; - -public class LdpVcCredentialRequestValidator implements CredentialRequestValidator { - @Override - public boolean isValidCheck(CredentialRequest credentialRequest) { - return credentialRequest.getCredential_definition() != null; - } -} diff --git a/certify-core/src/main/java/io/mosip/certify/core/validators/MsoMdocCredentialRequestValidator.java b/certify-core/src/main/java/io/mosip/certify/core/validators/MsoMdocCredentialRequestValidator.java deleted file mode 100644 index a8aca48e..00000000 --- a/certify-core/src/main/java/io/mosip/certify/core/validators/MsoMdocCredentialRequestValidator.java +++ /dev/null @@ -1,15 +0,0 @@ -package io.mosip.certify.core.validators; - -import io.mosip.certify.core.dto.CredentialRequest; - -public class MsoMdocCredentialRequestValidator implements CredentialRequestValidator { - @Override - public boolean isValidCheck(CredentialRequest credentialRequest) { - if (credentialRequest.getDoctype() == null || credentialRequest.getDoctype().isBlank()) { - return false; - } - if (credentialRequest.getClaims() == null || credentialRequest.getClaims().isEmpty()) - return false; - return true; - } -} diff --git a/certify-integration-api/src/main/java/io/mosip/certify/api/dto/RenderingTemplateDTO.java b/certify-integration-api/src/main/java/io/mosip/certify/api/dto/RenderingTemplateDTO.java new file mode 100644 index 00000000..4b720e10 --- /dev/null +++ b/certify-integration-api/src/main/java/io/mosip/certify/api/dto/RenderingTemplateDTO.java @@ -0,0 +1,13 @@ +package io.mosip.certify.api.dto; + +import lombok.Data; + +import java.time.LocalDateTime; + +@Data +public class RenderingTemplateDTO { + private String id; + private String template; + private LocalDateTime createdTimes; + private LocalDateTime updatedTimes; +} diff --git a/certify-integration-api/src/main/java/io/mosip/certify/api/spi/DataProviderPlugin.java b/certify-integration-api/src/main/java/io/mosip/certify/api/spi/DataProviderPlugin.java index 868ac557..239ad7d8 100644 --- a/certify-integration-api/src/main/java/io/mosip/certify/api/spi/DataProviderPlugin.java +++ b/certify-integration-api/src/main/java/io/mosip/certify/api/spi/DataProviderPlugin.java @@ -6,9 +6,10 @@ import java.util.Map; /** - * DataProviderPlugin is implemented by type#2 of identity plugin - * implementors to fetch data for Certify to template into a VC - * format of choice using {@link VCFormatter}. + * DataProviderPlugin is implemented by VC plugin + * implementors who want to make use of the Certify to generate the VC. + * Data is fetched from a Plugin implementation, templated using {@link VCFormatter} + * and then signed using {@link VCSigner}. */ public interface DataProviderPlugin { JSONObject fetchData(Map identityDetails) throws DataProviderExchangeException; diff --git a/certify-integration-api/src/main/java/io/mosip/certify/api/spi/VCFormatter.java b/certify-integration-api/src/main/java/io/mosip/certify/api/spi/VCFormatter.java deleted file mode 100644 index cc4bf5de..00000000 --- a/certify-integration-api/src/main/java/io/mosip/certify/api/spi/VCFormatter.java +++ /dev/null @@ -1,15 +0,0 @@ -package io.mosip.certify.api.spi; - - -import org.json.JSONObject; - -import java.util.Map; -/** - * VCDataModelFormatter is a templating engine which takes @param templateInput and returns a templated VC. - * Some implementations include - * - VC 2.0 data model templating engine - */ -public interface VCFormatter { - // TODO: Should it be changed to JSONObject? - String format(JSONObject templateInput, Map defaultSettings); -} \ No newline at end of file diff --git a/certify-integration-api/src/main/java/io/mosip/certify/api/spi/VCIssuancePlugin.java b/certify-integration-api/src/main/java/io/mosip/certify/api/spi/VCIssuancePlugin.java index 49360a03..26690b8a 100644 --- a/certify-integration-api/src/main/java/io/mosip/certify/api/spi/VCIssuancePlugin.java +++ b/certify-integration-api/src/main/java/io/mosip/certify/api/spi/VCIssuancePlugin.java @@ -11,7 +11,13 @@ import io.mosip.certify.api.exception.VCIExchangeException; import java.util.Map; - +/** + * VCIssuancePlugin is implemented by VC plugin + * implementors who want to make use of an existing VC Issuance Infrastructure + * or want to do everything by themselves to generate the VC from the plugin. + * VC is received by the plugin and sent to Certify and forwarded to the + * client applications. + */ public interface VCIssuancePlugin { /** diff --git a/certify-integration-api/src/main/java/io/mosip/certify/api/spi/VCSigner.java b/certify-integration-api/src/main/java/io/mosip/certify/api/spi/VCSigner.java deleted file mode 100644 index 174105a9..00000000 --- a/certify-integration-api/src/main/java/io/mosip/certify/api/spi/VCSigner.java +++ /dev/null @@ -1,10 +0,0 @@ -package io.mosip.certify.api.spi; - -import io.mosip.certify.api.dto.VCResult; - -/** - * VCSigner can sign any VC provided a vcHash & Signer inputs - */ -public interface VCSigner { - VCResult perform(String templatedVC); -} diff --git a/certify-service/pom.xml b/certify-service/pom.xml index 45fc947f..83d5b3ff 100644 --- a/certify-service/pom.xml +++ b/certify-service/pom.xml @@ -38,7 +38,27 @@ nimbus-jose-jwt 9.41.2 - + + + org.apache.velocity + velocity + 1.7 + + + org.apache.velocity.tools + velocity-tools-generic + 3.1 + + + org.slf4j + slf4j-api + + + org.apache.velocity + velocity-engine-core + + + io.mosip.certify certify-core diff --git a/certify-service/src/main/java/io/mosip/certify/CertifyServiceApplication.java b/certify-service/src/main/java/io/mosip/certify/CertifyServiceApplication.java index 3a7e80e4..134bc317 100644 --- a/certify-service/src/main/java/io/mosip/certify/CertifyServiceApplication.java +++ b/certify-service/src/main/java/io/mosip/certify/CertifyServiceApplication.java @@ -9,13 +9,11 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cache.annotation.EnableCaching; -import org.springframework.data.jpa.repository.config.EnableJpaRepositories; import org.springframework.scheduling.annotation.EnableAsync; @EnableAsync @EnableCaching @SpringBootApplication(scanBasePackages = "io.mosip.certify,"+ - "io.mosip.certify.core.*," + "io.mosip.kernel.crypto," + "io.mosip.kernel.keymanager.hsm," + "io.mosip.kernel.cryptomanager," + diff --git a/certify-service/src/main/java/io/mosip/certify/advice/ExceptionHandlerAdvice.java b/certify-service/src/main/java/io/mosip/certify/advice/ExceptionHandlerAdvice.java index 6d0cdfca..e7ca7539 100644 --- a/certify-service/src/main/java/io/mosip/certify/advice/ExceptionHandlerAdvice.java +++ b/certify-service/src/main/java/io/mosip/certify/advice/ExceptionHandlerAdvice.java @@ -11,7 +11,7 @@ import io.mosip.certify.core.exception.CertifyException; import io.mosip.certify.core.exception.InvalidRequestException; import io.mosip.certify.core.exception.NotAuthenticatedException; -import io.mosip.certify.core.exception.TemplateException; +import io.mosip.certify.core.exception.RenderingTemplateException; import io.mosip.certify.core.util.CommonUtil; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.TypeMismatchException; @@ -131,7 +131,7 @@ private ResponseEntity handleInternalControllerException(Except String errorCode = ((CertifyException) ex).getErrorCode(); return new ResponseEntity(getResponseWrapper(errorCode, getMessage(errorCode)), HttpStatus.OK); } - if(ex instanceof TemplateException) { + if(ex instanceof RenderingTemplateException) { return new ResponseEntity<>(getResponseWrapper(INVALID_REQUEST, ex.getMessage()) ,HttpStatus.NOT_FOUND); } if(ex instanceof AuthenticationCredentialsNotFoundException) { diff --git a/certify-service/src/main/java/io/mosip/certify/config/AppConfig.java b/certify-service/src/main/java/io/mosip/certify/config/AppConfig.java index 62d68efd..c10e1b77 100644 --- a/certify-service/src/main/java/io/mosip/certify/config/AppConfig.java +++ b/certify-service/src/main/java/io/mosip/certify/config/AppConfig.java @@ -10,7 +10,6 @@ import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import com.fasterxml.jackson.module.afterburner.AfterburnerModule; import io.mosip.certify.core.constants.Constants; -import io.mosip.certify.services.KeyManagerConstants; import io.mosip.kernel.keymanagerservice.dto.KeyPairGenerateRequestDto; import io.mosip.kernel.keymanagerservice.service.KeymanagerService; import io.mosip.kernel.keymanagerservice.dto.SymmetricKeyGenerateRequestDto; @@ -31,8 +30,8 @@ import org.springframework.web.client.RestTemplate; @Configuration -@EnableJpaRepositories(basePackages = {"io.mosip.kernel.keymanagerservice.repository", "io.mosip.certify.core.repository"}) -@EntityScan(basePackages = {"io.mosip.kernel.keymanagerservice.entity, io.mosip.certify.core.entity"}) +@EnableJpaRepositories(basePackages = {"io.mosip.kernel.keymanagerservice.repository", "io.mosip.certify.repository"}) +@EntityScan(basePackages = {"io.mosip.kernel.keymanagerservice.entity, io.mosip.certify.entity"}) @Slf4j public class AppConfig implements ApplicationRunner { @@ -48,6 +47,9 @@ public class AppConfig implements ApplicationRunner { @Value("${mosip.certify.cache.security.secretkey.reference-id}") private String cacheSecretKeyRefId; + @Value("${mosip.certify.plugin-mode}") + private String pluginMode; + @Bean public ObjectMapper objectMapper() { @@ -75,7 +77,7 @@ public void run(ApplicationArguments args) throws Exception { log.info("===================== CERTIFY_SERVICE ROOT KEY CHECK ========================"); String objectType = "CSR"; KeyPairGenerateRequestDto rootKeyRequest = new KeyPairGenerateRequestDto(); - rootKeyRequest.setApplicationId(KeyManagerConstants.ROOT_KEY); + rootKeyRequest.setApplicationId(Constants.ROOT_KEY); // Set the reference id to empty string, as keymanager is expecting the same for initialization rootKeyRequest.setReferenceId(org.apache.commons.lang3.StringUtils.EMPTY); keymanagerService.generateMasterKey(objectType, rootKeyRequest); @@ -86,11 +88,6 @@ public void run(ApplicationArguments args) throws Exception { masterKeyRequest.setReferenceId(org.apache.commons.lang3.StringUtils.EMPTY); keymanagerService.generateMasterKey(objectType, masterKeyRequest); // TODO: Generate an EC & ED key via K8s Job(INJICERT-469) - KeyPairGenerateRequestDto rsaKeyRequest = new KeyPairGenerateRequestDto(); - rsaKeyRequest.setApplicationId(KeyManagerConstants.CERTIFY_MOCK_RSA); - rsaKeyRequest.setReferenceId(KeyManagerConstants.EMPTY_REF_ID); - rsaKeyRequest.setForce(false); - keymanagerService.generateMasterKey("certificate", rsaKeyRequest); if(!StringUtils.isEmpty(cacheSecretKeyRefId)) { SymmetricKeyGenerateRequestDto symmetricKeyGenerateRequestDto = new SymmetricKeyGenerateRequestDto(); symmetricKeyGenerateRequestDto.setApplicationId(Constants.CERTIFY_SERVICE_APP_ID); @@ -106,17 +103,27 @@ public void run(ApplicationArguments args) throws Exception { // Set the reference id to empty string, as keymanager is expecting the same for initialization partnerMasterKeyRequest.setReferenceId(org.apache.commons.lang3.StringUtils.EMPTY); keymanagerService.generateMasterKey(objectType, partnerMasterKeyRequest); - // Generate an Ed25519Key: - // 1. Generate a master key first to enable Keymanager to store the key. - KeyPairGenerateRequestDto storeKey = new KeyPairGenerateRequestDto(); - storeKey.setApplicationId(KeyManagerConstants.CERTIFY_MOCK_ED25519); - storeKey.setReferenceId(org.apache.commons.lang3.StringUtils.EMPTY); - keymanagerService.generateMasterKey("certificate", storeKey); - // 2. Generate an Ed25519 key later - KeyPairGenerateRequestDto ed25519Req = new KeyPairGenerateRequestDto(); - ed25519Req.setApplicationId(KeyManagerConstants.CERTIFY_MOCK_ED25519); - ed25519Req.setReferenceId(KeyManagerConstants.ED25519_REF_ID); - keymanagerService.generateECSignKey("certificate", ed25519Req); + if(pluginMode.equals("DataProvider")) { + // Generate RSA Key Certificate + log.info("===================== CERTIFY_VC_SIGN_RSA KEY CHECK ========================"); + KeyPairGenerateRequestDto rsaKeyRequest = new KeyPairGenerateRequestDto(); + rsaKeyRequest.setApplicationId(Constants.CERTIFY_VC_SIGN_RSA); + rsaKeyRequest.setReferenceId(Constants.EMPTY_REF_ID); + rsaKeyRequest.setForce(false); + keymanagerService.generateMasterKey("certificate", rsaKeyRequest); + // Generate an Ed25519Key: + // 1. Generate a master key first to enable Keymanager to store the key. + log.info("===================== CERTIFY_VC_SIGN_ED25519 KEY CHECK ========================"); + KeyPairGenerateRequestDto storeKey = new KeyPairGenerateRequestDto(); + storeKey.setApplicationId(Constants.CERTIFY_VC_SIGN_ED25519); + storeKey.setReferenceId(Constants.EMPTY_REF_ID); + keymanagerService.generateMasterKey("certificate", storeKey); + // 2. Generate an Ed25519 key later + KeyPairGenerateRequestDto ed25519Req = new KeyPairGenerateRequestDto(); + ed25519Req.setApplicationId(Constants.CERTIFY_VC_SIGN_ED25519); + ed25519Req.setReferenceId(Constants.ED25519_REF_ID); + keymanagerService.generateECSignKey("certificate", ed25519Req); + } log.info("===================== CERTIFY KEY SETUP COMPLETED ========================"); } } diff --git a/certify-service/src/main/java/io/mosip/certify/config/TemplateConfig.java b/certify-service/src/main/java/io/mosip/certify/config/TemplateConfig.java deleted file mode 100644 index c4b9e406..00000000 --- a/certify-service/src/main/java/io/mosip/certify/config/TemplateConfig.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at https://mozilla.org/MPL/2.0/. - */ - -/* This is for temporary purpose till an API isn’t added to simplify Issuer onboarding. */ - -package io.mosip.certify.config; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import io.mosip.certify.core.entity.SvgTemplate; -import io.mosip.certify.core.exception.CertifyException; -import io.mosip.certify.core.repository.SvgTemplateRepository; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.CommandLineRunner; -import org.springframework.context.annotation.Configuration; -import org.springframework.core.io.ClassPathResource; -import org.springframework.core.io.Resource; -import org.springframework.web.client.RestTemplate; - -import java.io.IOException; -import java.nio.file.Files; -import java.time.LocalDateTime; -import java.util.*; - - -@Configuration -@Slf4j -public class TemplateConfig implements CommandLineRunner { - @Autowired - SvgTemplateRepository svgRenderTemplateRepository; - - @Value("${mosip.certify.svg-templates}") - private String svgTemplateJson; - - @Autowired - private ObjectMapper objectMapper; - - @Autowired - private RestTemplate restTemplate; - - @Override - public void run(String... args) throws Exception { - String svgTemplateContent = ""; - List svgTemplateMap; - - if(svgTemplateJson.startsWith("http")) { - svgTemplateContent = restTemplate.getForObject(svgTemplateJson, String.class); - } else { - Resource resource = new ClassPathResource(svgTemplateJson); - try { - svgTemplateContent = (Files.readString(resource.getFile().toPath())); - } catch (IOException e) { - log.error("Missing local json file for referring svg templates", e); - } - } - - - if(!svgTemplateContent.isEmpty()) { - try { - svgTemplateMap = objectMapper.readValue(svgTemplateContent, List.class); - } catch (JsonProcessingException e) { - throw new CertifyException("Missing configuration for svg template content " + e.getMessage()); - } - - List svgRenderTemplates = svgRenderTemplateRepository.findAll(); - - if(svgRenderTemplates.isEmpty()) { - svgTemplateMap.forEach((value) -> { - SvgTemplate svgRenderTemplate = new SvgTemplate(); - LinkedHashMap valueMap = (LinkedHashMap) value; - UUID id = UUID.fromString(valueMap.get("id").toString()); - svgRenderTemplate.setId(id); - String templateURI = valueMap.get("content").toString(); - if(templateURI.startsWith("http")) { - String templateFromUrl = restTemplate.getForObject(templateURI, String.class); - svgRenderTemplate.setTemplate(templateFromUrl); - } else { - svgRenderTemplate.setTemplate(templateURI); - } - LocalDateTime localDateTime = LocalDateTime.now(); - svgRenderTemplate.setCreatedtimes(localDateTime); - svgRenderTemplate.setUpdatedtimes(localDateTime); - log.info("Template inserted in svg template table."); - svgRenderTemplateRepository.save(svgRenderTemplate); - }); - } - } - log.info("=============== CERTIFY TEMPLATE SETUP COMPLETED ==============="); - } -} diff --git a/certify-service/src/main/java/io/mosip/certify/controller/SvgTemplateController.java b/certify-service/src/main/java/io/mosip/certify/controller/RenderingTemplateController.java similarity index 58% rename from certify-service/src/main/java/io/mosip/certify/controller/SvgTemplateController.java rename to certify-service/src/main/java/io/mosip/certify/controller/RenderingTemplateController.java index 17fefda2..e9c3c4c4 100644 --- a/certify-service/src/main/java/io/mosip/certify/controller/SvgTemplateController.java +++ b/certify-service/src/main/java/io/mosip/certify/controller/RenderingTemplateController.java @@ -5,12 +5,12 @@ */ package io.mosip.certify.controller; -import io.mosip.certify.core.entity.SvgTemplate; -import io.mosip.certify.core.exception.CertifyException; -import io.mosip.certify.core.exception.TemplateException; -import io.mosip.certify.core.spi.SvgTemplateService; +import io.mosip.certify.api.dto.RenderingTemplateDTO; +import io.mosip.certify.core.exception.RenderingTemplateException; +import io.mosip.certify.core.spi.RenderingTemplateService; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; import org.springframework.http.CacheControl; import org.springframework.http.HttpHeaders; import org.springframework.http.ResponseEntity; @@ -20,23 +20,24 @@ import org.springframework.web.bind.annotation.RestController; import java.time.ZoneId; -import java.util.UUID; import java.util.concurrent.TimeUnit; @Slf4j @RestController -@RequestMapping("/public") -public class SvgTemplateController { +@RequestMapping("/rendering-template") +public class RenderingTemplateController { + @Value("${mosip.certify.rendering-template.cache-max-age-days:1}") + Integer maxAgeDays; @Autowired - SvgTemplateService svgTemplateService; + RenderingTemplateService renderingTemplateService; - @GetMapping("/svg-template/{id}") - public ResponseEntity serveSvgTemplate(@PathVariable UUID id) throws TemplateException { - SvgTemplate template = svgTemplateService.getSvgTemplate(id); + @GetMapping("/{id}") + public ResponseEntity serveSvgTemplate(@PathVariable String id) throws RenderingTemplateException { + RenderingTemplateDTO template = renderingTemplateService.getSvgTemplate(id); return ResponseEntity.ok() .header(HttpHeaders.CONTENT_TYPE, "image/svg+xml") - .cacheControl(CacheControl.maxAge(1, TimeUnit.DAYS).cachePublic()) - .lastModified(template.getUpdatedtimes().atZone(ZoneId.systemDefault()).toInstant()) + .cacheControl(CacheControl.maxAge(maxAgeDays, TimeUnit.DAYS).cachePublic()) + .lastModified(template.getUpdatedTimes().atZone(ZoneId.systemDefault()).toInstant()) .body(template.getTemplate()); } } diff --git a/certify-service/src/main/java/io/mosip/certify/controller/VCIssuanceController.java b/certify-service/src/main/java/io/mosip/certify/controller/VCIssuanceController.java index 50185bf2..490d8f2d 100644 --- a/certify-service/src/main/java/io/mosip/certify/controller/VCIssuanceController.java +++ b/certify-service/src/main/java/io/mosip/certify/controller/VCIssuanceController.java @@ -44,7 +44,6 @@ public CredentialResponse getCredential(@Valid @RequestBody CredentialRequest cr } - /** * 1. The credential Endpoint MUST accept Access Tokens * @param credentialRequest VC credential request @@ -81,6 +80,11 @@ public Map getMetadata( return vcIssuanceService.getCredentialIssuerMetadata(version); } + @GetMapping(value = "/.well-known/did.json") + public Map getDIDDocument() { + return vcIssuanceService.getDIDDocument(); + } + @ResponseBody @ExceptionHandler(InvalidNonceException.class) diff --git a/certify-core/src/main/java/io/mosip/certify/core/entity/TemplateData.java b/certify-service/src/main/java/io/mosip/certify/entity/CredentialTemplate.java similarity index 85% rename from certify-core/src/main/java/io/mosip/certify/core/entity/TemplateData.java rename to certify-service/src/main/java/io/mosip/certify/entity/CredentialTemplate.java index 10e592f1..b8b40080 100644 --- a/certify-core/src/main/java/io/mosip/certify/core/entity/TemplateData.java +++ b/certify-service/src/main/java/io/mosip/certify/entity/CredentialTemplate.java @@ -1,4 +1,4 @@ -package io.mosip.certify.core.entity; +package io.mosip.certify.entity; import jakarta.persistence.Entity; @@ -9,8 +9,9 @@ @Entity @NoArgsConstructor +@Table(name = "credential_template") @IdClass(TemplateId.class) -public class TemplateData { +public class CredentialTemplate { @NotBlank(message = "Template is mandatory") @Getter @Setter diff --git a/certify-core/src/main/java/io/mosip/certify/core/entity/SvgTemplate.java b/certify-service/src/main/java/io/mosip/certify/entity/RenderingTemplate.java similarity index 86% rename from certify-core/src/main/java/io/mosip/certify/core/entity/SvgTemplate.java rename to certify-service/src/main/java/io/mosip/certify/entity/RenderingTemplate.java index a94496bf..8a113231 100644 --- a/certify-core/src/main/java/io/mosip/certify/core/entity/SvgTemplate.java +++ b/certify-service/src/main/java/io/mosip/certify/entity/RenderingTemplate.java @@ -3,7 +3,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ -package io.mosip.certify.core.entity; +package io.mosip.certify.entity; import io.mosip.certify.core.constants.ErrorConstants; import jakarta.persistence.*; @@ -13,15 +13,15 @@ import lombok.NoArgsConstructor; import java.time.LocalDateTime; -import java.util.UUID; @Data @Entity @AllArgsConstructor @NoArgsConstructor -public class SvgTemplate { +@Table(name = "rendering_template") +public class RenderingTemplate { @Id - private UUID id; + private String id; @NotBlank(message = ErrorConstants.EMPTY_TEMPLATE_CONTENT) @Column(name = "template") diff --git a/certify-core/src/main/java/io/mosip/certify/core/entity/TemplateId.java b/certify-service/src/main/java/io/mosip/certify/entity/TemplateId.java similarity index 94% rename from certify-core/src/main/java/io/mosip/certify/core/entity/TemplateId.java rename to certify-service/src/main/java/io/mosip/certify/entity/TemplateId.java index ef472d04..7e99274d 100644 --- a/certify-core/src/main/java/io/mosip/certify/core/entity/TemplateId.java +++ b/certify-service/src/main/java/io/mosip/certify/entity/TemplateId.java @@ -1,4 +1,4 @@ -package io.mosip.certify.core.entity; +package io.mosip.certify.entity; import lombok.*; diff --git a/certify-service/src/main/java/io/mosip/certify/services/ldsigner/Ed25519ProofSignature2018.java b/certify-service/src/main/java/io/mosip/certify/proofgenerators/Ed25519Signature2018ProofGenerator.java similarity index 69% rename from certify-service/src/main/java/io/mosip/certify/services/ldsigner/Ed25519ProofSignature2018.java rename to certify-service/src/main/java/io/mosip/certify/proofgenerators/Ed25519Signature2018ProofGenerator.java index 3594c23b..a191490f 100644 --- a/certify-service/src/main/java/io/mosip/certify/services/ldsigner/Ed25519ProofSignature2018.java +++ b/certify-service/src/main/java/io/mosip/certify/proofgenerators/Ed25519Signature2018ProofGenerator.java @@ -1,11 +1,11 @@ -package io.mosip.certify.services.ldsigner; +package io.mosip.certify.proofgenerators; import com.danubetech.keyformats.jose.JWSAlgorithm; import info.weboftrust.ldsignatures.LdProof; import info.weboftrust.ldsignatures.canonicalizer.Canonicalizer; import info.weboftrust.ldsignatures.canonicalizer.URDNA2015Canonicalizer; +import io.mosip.certify.core.constants.Constants; import io.mosip.certify.core.constants.SignatureAlg; -import io.mosip.certify.services.KeyManagerConstants; import io.mosip.kernel.signature.dto.JWSSignatureRequestDto; import io.mosip.kernel.signature.dto.JWTSignatureResponseDto; import io.mosip.kernel.signature.service.SignatureService; @@ -13,12 +13,14 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.stereotype.Component; +import java.util.Map; + /** * Ed25519SignatureAlgorithm2018 as per https://w3c-ccg.github.io/lds-ed25519-2018/ */ @Component -@ConditionalOnProperty(name = "mosip.certify.issuer.vc-sign-algo", havingValue = SignatureAlg.ED25519_SIGNATURE_SUITE) -public class Ed25519ProofSignature2018 implements ProofSignatureStrategy { +@ConditionalOnProperty(name = "mosip.certify.data-provider-plugin.issuer.vc-sign-algo", havingValue = SignatureAlg.ED25519_SIGNATURE_SUITE_2018) +public class Ed25519Signature2018ProofGenerator implements ProofGenerator { @Autowired SignatureService signatureService; @@ -26,7 +28,7 @@ public class Ed25519ProofSignature2018 implements ProofSignatureStrategy { @Override public String getName() { - return SignatureAlg.ED25519_SIGNATURE_SUITE; + return SignatureAlg.ED25519_SIGNATURE_SUITE_2018; } @Override @@ -35,11 +37,11 @@ public Canonicalizer getCanonicalizer() { } @Override - public String getProof(String vcEncodedHash) { + public LdProof generateProof(LdProof vcLdProof, String vcEncodedHash, Map keyID) { JWSSignatureRequestDto payload = new JWSSignatureRequestDto(); payload.setDataToSign(vcEncodedHash); - payload.setApplicationId(KeyManagerConstants.CERTIFY_MOCK_ED25519); - payload.setReferenceId(KeyManagerConstants.ED25519_REF_ID); // alg, empty = RSA + payload.setApplicationId(keyID.get(Constants.APPLICATION_ID)); + payload.setReferenceId(keyID.get(Constants.REFERENCE_ID)); payload.setIncludePayload(false); payload.setIncludeCertificate(false); payload.setIncludeCertHash(true); @@ -48,12 +50,7 @@ public String getProof(String vcEncodedHash) { payload.setCertificateUrl(""); payload.setSignAlgorithm(JWSAlgorithm.EdDSA); // RSSignature2018 --> RS256, PS256, ES256 JWTSignatureResponseDto jwsSignedData = signatureService.jwsSign(payload); - return jwsSignedData.getJwtSignedData(); - } - - @Override - public LdProof buildProof(LdProof vcLdProof, String sign) { return LdProof.builder().base(vcLdProof).defaultContexts(false) - .jws(sign).build(); + .jws(jwsSignedData.getJwtSignedData()).build(); } } diff --git a/certify-service/src/main/java/io/mosip/certify/services/ldsigner/Ed25519ProofSignature2020.java b/certify-service/src/main/java/io/mosip/certify/proofgenerators/Ed25519Signature2020ProofGenerator.java similarity index 69% rename from certify-service/src/main/java/io/mosip/certify/services/ldsigner/Ed25519ProofSignature2020.java rename to certify-service/src/main/java/io/mosip/certify/proofgenerators/Ed25519Signature2020ProofGenerator.java index f48f4716..ef1122f0 100644 --- a/certify-service/src/main/java/io/mosip/certify/services/ldsigner/Ed25519ProofSignature2020.java +++ b/certify-service/src/main/java/io/mosip/certify/proofgenerators/Ed25519Signature2020ProofGenerator.java @@ -1,11 +1,11 @@ -package io.mosip.certify.services.ldsigner; +package io.mosip.certify.proofgenerators; import com.danubetech.keyformats.jose.JWSAlgorithm; import info.weboftrust.ldsignatures.LdProof; import info.weboftrust.ldsignatures.canonicalizer.Canonicalizer; import info.weboftrust.ldsignatures.canonicalizer.URDNA2015Canonicalizer; +import io.mosip.certify.core.constants.Constants; import io.mosip.certify.core.constants.SignatureAlg; -import io.mosip.certify.services.KeyManagerConstants; import io.mosip.kernel.signature.dto.SignRequestDtoV2; import io.mosip.kernel.signature.dto.SignResponseDto; import io.mosip.kernel.signature.service.SignatureServicev2; @@ -13,13 +13,15 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.stereotype.Component; +import java.util.Map; + /** * Ed25519SignatureAlgorithm2020 as per * https://www.w3.org/community/reports/credentials/CG-FINAL-di-eddsa-2020-20220724/ */ @Component -@ConditionalOnProperty(name = "mosip.certify.issuer.vc-sign-algo", havingValue = SignatureAlg.ED25519_SIGNATURE_SUITE_2020) -public class Ed25519ProofSignature2020 implements ProofSignatureStrategy { +@ConditionalOnProperty(name = "mosip.certify.data-provider-plugin.issuer.vc-sign-algo", havingValue = SignatureAlg.ED25519_SIGNATURE_SUITE_2020) +public class Ed25519Signature2020ProofGenerator implements ProofGenerator { @Autowired SignatureServicev2 signatureService; @@ -37,20 +39,15 @@ public Canonicalizer getCanonicalizer() { } @Override - public String getProof(String vcEncodedHash) { + public LdProof generateProof(LdProof vcLdProof, String vcEncodedHash, Map keyID) { SignRequestDtoV2 srd = new SignRequestDtoV2(); - srd.setApplicationId(KeyManagerConstants.CERTIFY_MOCK_ED25519); - srd.setReferenceId(KeyManagerConstants.ED25519_REF_ID); + srd.setApplicationId(keyID.get(Constants.APPLICATION_ID)); + srd.setReferenceId(keyID.get(Constants.REFERENCE_ID)); srd.setDataToSign(vcEncodedHash); srd.setResponseEncodingFormat("base58btc"); srd.setSignAlgorithm(JWSAlgorithm.EdDSA); SignResponseDto s = signatureService.signv2(srd); - return s.getSignature(); - } - - @Override - public LdProof buildProof(LdProof vcLdProof, String sign) { return LdProof.builder().base(vcLdProof).defaultContexts(false) - .proofValue(sign).build(); + .proofValue(s.getSignature()).build(); } } diff --git a/certify-service/src/main/java/io/mosip/certify/proofgenerators/ProofGenerator.java b/certify-service/src/main/java/io/mosip/certify/proofgenerators/ProofGenerator.java new file mode 100644 index 00000000..e1e03257 --- /dev/null +++ b/certify-service/src/main/java/io/mosip/certify/proofgenerators/ProofGenerator.java @@ -0,0 +1,33 @@ +package io.mosip.certify.proofgenerators; + +import info.weboftrust.ldsignatures.LdProof; +import info.weboftrust.ldsignatures.canonicalizer.Canonicalizer; + +import java.util.Map; + +/** + * ProofGenerator is a helper class for KeymanagerLibSigner + * to better deal with multiple signature algorithms for JSON-LD VCs. + */ +public interface ProofGenerator { + /** + * @return returns the name of the Algorithm + */ + String getName(); + + /** + * @return the Canonicalizer which will be used to Canonicalize the templated VC + */ + Canonicalizer getCanonicalizer(); + + /** + * generateProof takes a canonicalized VC hash generates a proof and + * returns an LdProof object. + * signature: can be a detached JWS, or another proofString based on implementors choice + * + * @param vcLdProof the proof object of the VC + * @param vcHash is the output of the + * @return + */ + LdProof generateProof(LdProof vcLdProof, String vcHash, Map keyID); +} diff --git a/certify-service/src/main/java/io/mosip/certify/services/ldsigner/RsaProofSignature2018.java b/certify-service/src/main/java/io/mosip/certify/proofgenerators/RSASignature2018ProofGenerator.java similarity index 62% rename from certify-service/src/main/java/io/mosip/certify/services/ldsigner/RsaProofSignature2018.java rename to certify-service/src/main/java/io/mosip/certify/proofgenerators/RSASignature2018ProofGenerator.java index f24ef4c4..6b5d41e6 100644 --- a/certify-service/src/main/java/io/mosip/certify/services/ldsigner/RsaProofSignature2018.java +++ b/certify-service/src/main/java/io/mosip/certify/proofgenerators/RSASignature2018ProofGenerator.java @@ -1,11 +1,11 @@ -package io.mosip.certify.services.ldsigner; +package io.mosip.certify.proofgenerators; import com.danubetech.keyformats.jose.JWSAlgorithm; import info.weboftrust.ldsignatures.LdProof; import info.weboftrust.ldsignatures.canonicalizer.Canonicalizer; import info.weboftrust.ldsignatures.canonicalizer.URDNA2015Canonicalizer; +import io.mosip.certify.core.constants.Constants; import io.mosip.certify.core.constants.SignatureAlg; -import io.mosip.certify.services.KeyManagerConstants; import io.mosip.kernel.signature.dto.JWSSignatureRequestDto; import io.mosip.kernel.signature.dto.JWTSignatureResponseDto; import io.mosip.kernel.signature.service.SignatureService; @@ -13,12 +13,11 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.stereotype.Component; -import java.nio.charset.StandardCharsets; -import java.util.Base64; +import java.util.Map; @Component -@ConditionalOnProperty(name = "mosip.certify.issuer.vc-sign-algo", havingValue = SignatureAlg.RSA_SIGNATURE_SUITE) -public class RsaProofSignature2018 implements ProofSignatureStrategy { +@ConditionalOnProperty(name = "mosip.certify.data-provider-plugin.issuer.vc-sign-algo", havingValue = SignatureAlg.RSA_SIGNATURE_SUITE_2018) +public class RSASignature2018ProofGenerator implements ProofGenerator { @Autowired SignatureService signatureService; @@ -26,7 +25,7 @@ public class RsaProofSignature2018 implements ProofSignatureStrategy { @Override public String getName() { - return SignatureAlg.RSA_SIGNATURE_SUITE; + return SignatureAlg.RSA_SIGNATURE_SUITE_2018; } @Override @@ -35,12 +34,11 @@ public Canonicalizer getCanonicalizer() { } @Override - public String getProof(String vcEncodedHash) { - String vcEncodedData = Base64.getUrlEncoder().encodeToString(vcEncodedHash.getBytes(StandardCharsets.UTF_8)); + public LdProof generateProof(LdProof vcLdProof, String vcEncodedHash, Map keyID) { JWSSignatureRequestDto payload = new JWSSignatureRequestDto(); - payload.setDataToSign(vcEncodedData); - payload.setApplicationId(KeyManagerConstants.CERTIFY_MOCK_RSA); - payload.setReferenceId(KeyManagerConstants.EMPTY_REF_ID); // alg, empty = RSA + payload.setDataToSign(vcEncodedHash); + payload.setApplicationId(keyID.get(Constants.APPLICATION_ID)); + payload.setReferenceId(keyID.get(Constants.REFERENCE_ID)); // alg, empty = RSA payload.setIncludePayload(false); payload.setIncludeCertificate(false); payload.setIncludeCertHash(true); @@ -49,12 +47,7 @@ public String getProof(String vcEncodedHash) { payload.setCertificateUrl(""); payload.setSignAlgorithm(JWSAlgorithm.RS256); // RSSignature2018 --> RS256, PS256, ES256 JWTSignatureResponseDto jwsSignedData = signatureService.jwsSign(payload); - return jwsSignedData.getJwtSignedData(); - } - - @Override - public LdProof buildProof(LdProof vcLdProof, String sign) { return LdProof.builder().base(vcLdProof).defaultContexts(false) - .jws(sign).build(); + .jws(jwsSignedData.getJwtSignedData()).build(); } } diff --git a/certify-service/src/main/java/io/mosip/certify/repository/CredentialTemplateRepository.java b/certify-service/src/main/java/io/mosip/certify/repository/CredentialTemplateRepository.java new file mode 100644 index 00000000..d290641a --- /dev/null +++ b/certify-service/src/main/java/io/mosip/certify/repository/CredentialTemplateRepository.java @@ -0,0 +1,15 @@ +package io.mosip.certify.repository; + +import io.mosip.certify.entity.CredentialTemplate; +import io.mosip.certify.entity.TemplateId; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import java.util.Optional; + +@Repository +public interface CredentialTemplateRepository extends JpaRepository { + Optional findByCredentialTypeAndContext(String credentialType, String context); + // NOTE: best practice? .save() +} + diff --git a/certify-core/src/main/java/io/mosip/certify/core/repository/SvgTemplateRepository.java b/certify-service/src/main/java/io/mosip/certify/repository/RenderingTemplateRepository.java similarity index 58% rename from certify-core/src/main/java/io/mosip/certify/core/repository/SvgTemplateRepository.java rename to certify-service/src/main/java/io/mosip/certify/repository/RenderingTemplateRepository.java index dffe7f16..43456a33 100644 --- a/certify-core/src/main/java/io/mosip/certify/core/repository/SvgTemplateRepository.java +++ b/certify-service/src/main/java/io/mosip/certify/repository/RenderingTemplateRepository.java @@ -3,12 +3,10 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ -package io.mosip.certify.core.repository; +package io.mosip.certify.repository; -import io.mosip.certify.core.entity.SvgTemplate; +import io.mosip.certify.entity.RenderingTemplate; import org.springframework.data.jpa.repository.JpaRepository; -import java.util.UUID; - -public interface SvgTemplateRepository extends JpaRepository { +public interface RenderingTemplateRepository extends JpaRepository { } diff --git a/certify-service/src/main/java/io/mosip/certify/services/CertifyIssuanceServiceImpl.java b/certify-service/src/main/java/io/mosip/certify/services/CertifyIssuanceServiceImpl.java index 0e0a8d6a..8b30d2f9 100644 --- a/certify-service/src/main/java/io/mosip/certify/services/CertifyIssuanceServiceImpl.java +++ b/certify-service/src/main/java/io/mosip/certify/services/CertifyIssuanceServiceImpl.java @@ -12,6 +12,7 @@ import io.mosip.certify.api.spi.*; import io.mosip.certify.api.util.Action; import io.mosip.certify.api.util.ActionStatus; +import io.mosip.certify.core.constants.SignatureAlg; import io.mosip.certify.core.constants.VCFormats; import io.mosip.certify.core.dto.CredentialMetadata; import io.mosip.certify.core.dto.CredentialRequest; @@ -26,14 +27,20 @@ import io.mosip.certify.core.spi.VCIssuanceService; import io.mosip.certify.core.util.AuditHelper; import io.mosip.certify.core.util.SecurityHelperService; -import io.mosip.certify.core.validators.CredentialRequestValidatorFactory; +import io.mosip.certify.api.spi.DataProviderPlugin; +import io.mosip.certify.vcformatters.VCFormatter; +import io.mosip.certify.validators.CredentialRequestValidator; import io.mosip.certify.exception.InvalidNonceException; import io.mosip.certify.proof.ProofValidator; import io.mosip.certify.proof.ProofValidatorFactory; -import io.mosip.certify.services.templating.VelocityTemplatingConstants; import io.mosip.certify.utils.CredentialUtils; +import io.mosip.certify.utils.DIDDocumentUtil; +import io.mosip.certify.vcsigners.VCSigner; +import io.mosip.kernel.keymanagerservice.dto.KeyPairGenerateResponseDto; +import io.mosip.kernel.keymanagerservice.service.KeymanagerService; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; +import org.json.JSONException; import org.json.JSONObject; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; @@ -47,9 +54,15 @@ @Slf4j @Service -@ConditionalOnProperty(value = "mosip.certify.issuer", havingValue = "CertifyIssuer") +@ConditionalOnProperty(value = "mosip.certify.plugin-mode", havingValue = "DataProvider") public class CertifyIssuanceServiceImpl implements VCIssuanceService { + public static final Map> keyChooser = Map.of( + SignatureAlg.RSA_SIGNATURE_SUITE_2018, List.of(Constants.CERTIFY_VC_SIGN_RSA, Constants.EMPTY_REF_ID), + SignatureAlg.ED25519_SIGNATURE_SUITE_2018, List.of(Constants.CERTIFY_VC_SIGN_ED25519, Constants.ED25519_REF_ID), + SignatureAlg.ED25519_SIGNATURE_SUITE_2020, List.of(Constants.CERTIFY_VC_SIGN_ED25519, Constants.ED25519_REF_ID)); + @Value("${mosip.certify.data-provider-plugin.issuer.vc-sign-algo:Ed25519Signature2020}") + private String vcSignAlgorithm; @Value("#{${mosip.certify.key-values}}") private LinkedHashMap> issuerMetadata; @@ -66,13 +79,16 @@ public class CertifyIssuanceServiceImpl implements VCIssuanceService { private VCSigner vcSigner; @Autowired - private DataProviderPlugin dataModelService; + private DataProviderPlugin dataProviderPlugin; - @Value("${mosip.certify.issuer.uri}") + @Value("${mosip.certify.data-provider-plugin.issuer-uri}") private String issuerURI; - @Value("${mosip.certify.issuer.svg.template.id}") - private String svg; + @Value("${mosip.certify.data-provider-plugin.issuer-public-key-uri}") + private String issuerPublicKeyURI; + + @Value("${mosip.certify.data-provider-plugin.rendering-template-id:}") + private String renderTemplateId; @Autowired private ProofValidatorFactory proofValidatorFactory; @@ -86,10 +102,15 @@ public class CertifyIssuanceServiceImpl implements VCIssuanceService { @Autowired private AuditPlugin auditWrapper; + @Autowired + private KeymanagerService keymanagerService; + + private Map didDocument; + @Override public CredentialResponse getCredential(CredentialRequest credentialRequest) { // 1. Credential Request validation - boolean isValidCredentialRequest = new CredentialRequestValidatorFactory().isValid(credentialRequest); + boolean isValidCredentialRequest = CredentialRequestValidator.isValid(credentialRequest); if(!isValidCredentialRequest) { throw new InvalidRequestException(ErrorConstants.INVALID_REQUEST); } @@ -130,11 +151,154 @@ public CredentialResponse getCredential(CredentialRequest credentialRequest) { @Override public Map getCredentialIssuerMetadata(String version) { - if(issuerMetadata.containsKey(version)) + if(issuerMetadata.containsKey(version)) { return issuerMetadata.get(version); + } else if(version != null && version.equals("vd12")) { + LinkedHashMap originalIssuerMetadata = new LinkedHashMap<>(issuerMetadata.get("latest")); + Map vd12IssuerMetadata = convertLatestToVd12(originalIssuerMetadata); + issuerMetadata.put("vd12", (LinkedHashMap) vd12IssuerMetadata); + return vd12IssuerMetadata; + } else if(version != null && version.equals("vd11")) { + LinkedHashMap originalIssuerMetadata = new LinkedHashMap<>(issuerMetadata.get("latest")); + Map vd11IssuerMetadata = convertLatestToVd11(originalIssuerMetadata); + issuerMetadata.put("vd11", (LinkedHashMap) vd11IssuerMetadata); + return vd11IssuerMetadata; + } throw new InvalidRequestException(ErrorConstants.UNSUPPORTED_OPENID_VERSION); } + @Override + public Map getDIDDocument() { + if(didDocument != null) + return didDocument; + + KeyPairGenerateResponseDto keyPairGenerateResponseDto = keymanagerService.getCertificate(keyChooser.get(vcSignAlgorithm).getFirst(), Optional.of(keyChooser.get(vcSignAlgorithm).getLast())); + String certificateString = keyPairGenerateResponseDto.getCertificate(); + + didDocument = DIDDocumentUtil.generateDIDDocument(vcSignAlgorithm, certificateString, issuerURI, issuerPublicKeyURI); + return didDocument; + } + + private Map convertLatestToVd11(LinkedHashMap vciMetadata) { + // Create a list to hold the transformed credentials + List> credentialsList = new ArrayList<>(); + + // Check if the original config contains 'credential_configurations_supported' + if (vciMetadata.containsKey("credential_configurations_supported")) { + // Cast the value to a Map + Map originalCredentials = + (Map) vciMetadata.get("credential_configurations_supported"); + + // Iterate through each credential + for (Map.Entry entry : originalCredentials.entrySet()) { + // Cast the credential configuration + Map credConfig = (Map) entry.getValue(); + + // Create a new transformed credential configuration + Map transformedCredential = new HashMap<>(credConfig); + + // Add 'id' field with the original key + transformedCredential.put("id", entry.getKey()); + + // Rename 'credential_signing_alg_values_supported' to 'cryptographic_suites_supported' + if (transformedCredential.containsKey("credential_signing_alg_values_supported")) { + transformedCredential.put("cryptographic_suites_supported", + transformedCredential.remove("credential_signing_alg_values_supported")); + } + + // Modify proof_types_supported + if (transformedCredential.containsKey("proof_types_supported")) { + Map proofTypes = (Map) transformedCredential.get("proof_types_supported"); + transformedCredential.put("proof_types_supported", proofTypes.keySet()); + } + + if(transformedCredential.containsKey("display")) { + List> displayMapList = new ArrayList<>((List>)transformedCredential.get("display")); + List> newDisplayMapList = new ArrayList<>(); + for(Map map : displayMapList) { + Map displayMap = new HashMap<>(map); + displayMap.remove("background_image"); + newDisplayMapList.add(displayMap); + } + transformedCredential.put("display", newDisplayMapList); + } + + // Remove 'order' if it exists + transformedCredential.remove("order"); + + // Add the transformed credential to the list + credentialsList.add(transformedCredential); + } + + // Set the transformed credentials in the new configuration + vciMetadata.put("credentials_supported", credentialsList); + } + + vciMetadata.remove("credential_configurations_supported"); + vciMetadata.remove("authorization_servers"); + vciMetadata.remove("display"); + String endpoint = (String)vciMetadata.get("credential_endpoint"); + int issuanceIndex = endpoint.indexOf("issuance/"); + String newEndPoint = endpoint.substring(0, issuanceIndex+9); + vciMetadata.put("credential_endpoint", newEndPoint + "vd11/credential"); + return vciMetadata; + } + + private Map convertLatestToVd12(LinkedHashMap vciMetadata) { + // Create a new map to store the transformed configuration + if(vciMetadata.containsKey("credential_configurations_supported")) { + LinkedHashMap supportedCredentials = (LinkedHashMap) vciMetadata.get("credential_configurations_supported"); + Map transformedMap = transformCredentialConfiguration(supportedCredentials); + vciMetadata.put("credentials_supported", transformedMap); + } + + vciMetadata.remove("credential_configurations_supported"); + String endpoint = (String)vciMetadata.get("credential_endpoint"); + int issuanceIndex = endpoint.indexOf("issuance/"); + String newEndPoint = endpoint.substring(0, issuanceIndex+9); + vciMetadata.put("credential_endpoint", newEndPoint + "vd12/credential"); + return vciMetadata; + } + + private static Map transformCredentialConfiguration(LinkedHashMap originalConfig) { + Map transformedConfig = new LinkedHashMap<>(); + + for (Map.Entry entry : originalConfig.entrySet()) { + Map credentialDetails = (Map) entry.getValue(); + + // Create a new map to store modified credential details + Map transformedCredential = new LinkedHashMap<>(credentialDetails); + + // Replace 'credential_signing_alg_values_supported' with 'cryptographic_suites_supported' + if (transformedCredential.containsKey("credential_signing_alg_values_supported")) { + Object signingAlgs = transformedCredential.remove("credential_signing_alg_values_supported"); + transformedCredential.put("cryptographic_suites_supported", signingAlgs); + } + + // Modify proof_types_supported + if (transformedCredential.containsKey("proof_types_supported")) { + Map proofTypes = (Map) transformedCredential.get("proof_types_supported"); + transformedCredential.put("proof_types_supported", proofTypes.keySet()); + } + + if(transformedCredential.containsKey("display")) { + List> displayMapList = new ArrayList<>((List>)transformedCredential.get("display")); + List> newDisplayMapList = new ArrayList<>(); + for(Map map : displayMapList) { + Map displayMap = new HashMap<>(map); + displayMap.remove("background_image"); + newDisplayMapList.add(displayMap); + } + transformedCredential.put("display", newDisplayMapList); + } + + // Add the modified credential details to the transformed config + transformedConfig.put(entry.getKey(), transformedCredential); + } + + return transformedConfig; + } + private VCResult getVerifiableCredential(CredentialRequest credentialRequest, CredentialMetadata credentialMetadata, String holderId) { parsedAccessToken.getClaims().put("accessTokenHash", parsedAccessToken.getAccessTokenHash()); @@ -151,17 +315,25 @@ private VCResult getVerifiableCredential(CredentialRequest credentialRequest, validateLdpVcFormatRequest(credentialRequest, credentialMetadata); try { // TODO(multitenancy): later decide which plugin out of n plugins is the correct one - JSONObject jsonObject = dataModelService.fetchData(parsedAccessToken.getClaims()); + JSONObject jsonObject = dataProviderPlugin.fetchData(parsedAccessToken.getClaims()); Map templateParams = new HashMap<>(); - templateParams.put(VelocityTemplatingConstants.TEMPLATE_NAME, CredentialUtils.getTemplateName(vcRequestDto)); - templateParams.put(VelocityTemplatingConstants.ISSUER_URI, issuerURI); - if (!StringUtils.isEmpty(svg)) { - templateParams.put(VelocityTemplatingConstants.SVG_TEMPLATE, svg); + templateParams.put(Constants.TEMPLATE_NAME, CredentialUtils.getTemplateName(vcRequestDto)); + templateParams.put(Constants.ISSUER_URI, issuerURI); + if (!StringUtils.isEmpty(renderTemplateId)) { + templateParams.put(Constants.RENDERING_TEMPLATE_ID, renderTemplateId); } - String templatedVC = vcFormatter.format(jsonObject, templateParams); - vcResult = vcSigner.perform(templatedVC); + jsonObject.put("_holderId", holderId); + String unSignedVC = vcFormatter.format(jsonObject, templateParams); + Map signerSettings = new HashMap<>(); + // NOTE: This is a quasi implementation to add support for multi-tenancy. + signerSettings.put(Constants.APPLICATION_ID, keyChooser.get(vcSignAlgorithm).getFirst()); + signerSettings.put(Constants.REFERENCE_ID, keyChooser.get(vcSignAlgorithm).getLast()); + vcResult = vcSigner.attachSignature(unSignedVC, signerSettings); } catch(DataProviderExchangeException e) { throw new CertifyException(e.getErrorCode()); + } catch (JSONException e) { + log.error(e.getMessage(), e); + throw new CertifyException(ErrorConstants.UNKNOWN_ERROR); } break; default: diff --git a/certify-service/src/main/java/io/mosip/certify/services/SVGRenderUtils.java b/certify-service/src/main/java/io/mosip/certify/services/CredentialUtils.java similarity index 97% rename from certify-service/src/main/java/io/mosip/certify/services/SVGRenderUtils.java rename to certify-service/src/main/java/io/mosip/certify/services/CredentialUtils.java index 205dbf13..2234a1ad 100644 --- a/certify-service/src/main/java/io/mosip/certify/services/SVGRenderUtils.java +++ b/certify-service/src/main/java/io/mosip/certify/services/CredentialUtils.java @@ -6,7 +6,7 @@ import io.ipfs.multibase.Multibase; -public class SVGRenderUtils { +public class CredentialUtils { /** * Generate SVG digest for @param svg image as per spec. * ref: https://w3c-ccg.github.io/vc-render-method/#svgrenderingtemplate diff --git a/certify-service/src/main/java/io/mosip/certify/services/KeyManagerConstants.java b/certify-service/src/main/java/io/mosip/certify/services/KeyManagerConstants.java index 26f26cf1..e57b6948 100644 --- a/certify-service/src/main/java/io/mosip/certify/services/KeyManagerConstants.java +++ b/certify-service/src/main/java/io/mosip/certify/services/KeyManagerConstants.java @@ -6,8 +6,10 @@ package io.mosip.certify.services; public class KeyManagerConstants { - public static final String CERTIFY_MOCK_RSA = "CERTIFY_MOCK_RSA"; - public static final String CERTIFY_MOCK_ED25519 = "CERTIFY_MOCK_ED25519"; + public static final String CERTIFY_PARTNER_APP_ID = "CERTIFY_PARTNER"; + public static final String CERTIFY_SERVICE_APP_ID = "CERTIFY_SERVICE"; + public static final String CERTIFY_VC_SIGN_RSA = "CERTIFY_VC_SIGN_RSA"; + public static final String CERTIFY_VC_SIGN_ED25519 = "CERTIFY_VC_SIGN_ED25519"; public static final String ROOT_KEY = "ROOT"; public static final String EMPTY_REF_ID = ""; public static final String ED25519_REF_ID = "ED25519_SIGN"; diff --git a/certify-service/src/main/java/io/mosip/certify/services/RenderingTemplateServiceImpl.java b/certify-service/src/main/java/io/mosip/certify/services/RenderingTemplateServiceImpl.java new file mode 100644 index 00000000..f2245cd5 --- /dev/null +++ b/certify-service/src/main/java/io/mosip/certify/services/RenderingTemplateServiceImpl.java @@ -0,0 +1,39 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ +package io.mosip.certify.services; + +import io.mosip.certify.api.dto.RenderingTemplateDTO; +import io.mosip.certify.core.constants.ErrorConstants; +import io.mosip.certify.entity.RenderingTemplate; +import io.mosip.certify.core.exception.RenderingTemplateException; +import io.mosip.certify.repository.RenderingTemplateRepository; +import io.mosip.certify.core.spi.RenderingTemplateService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.Optional; + +@Slf4j +@Component +public class RenderingTemplateServiceImpl implements RenderingTemplateService { + @Autowired + RenderingTemplateRepository svgRenderTemplateRepository; + + + @Override + public RenderingTemplateDTO getSvgTemplate(String id) { + Optional optional = svgRenderTemplateRepository.findById(id); + RenderingTemplate renderingTemplate = optional.orElseThrow(() -> new RenderingTemplateException(ErrorConstants.INVALID_TEMPLATE_ID)); + RenderingTemplateDTO renderingTemplateDTO = new RenderingTemplateDTO(); + renderingTemplateDTO.setId(renderingTemplate.getId()); + renderingTemplateDTO.setTemplate(renderingTemplate.getTemplate()); + renderingTemplateDTO.setCreatedTimes(renderingTemplate.getCreatedtimes()); + renderingTemplateDTO.setUpdatedTimes(renderingTemplate.getUpdatedtimes()); + + return renderingTemplateDTO; + } +} diff --git a/certify-service/src/main/java/io/mosip/certify/services/SvgTemplateServiceImpl.java b/certify-service/src/main/java/io/mosip/certify/services/SvgTemplateServiceImpl.java deleted file mode 100644 index 68a2925b..00000000 --- a/certify-service/src/main/java/io/mosip/certify/services/SvgTemplateServiceImpl.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at https://mozilla.org/MPL/2.0/. - */ -package io.mosip.certify.services; - -import io.mosip.certify.core.constants.ErrorConstants; -import io.mosip.certify.core.entity.SvgTemplate; -import io.mosip.certify.core.exception.CertifyException; -import io.mosip.certify.core.exception.TemplateException; -import io.mosip.certify.core.repository.SvgTemplateRepository; -import io.mosip.certify.core.spi.SvgTemplateService; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import java.util.Optional; -import java.util.UUID; - -@Slf4j -@Component -public class SvgTemplateServiceImpl implements SvgTemplateService { - @Autowired - SvgTemplateRepository svgRenderTemplateRepository; - - - @Override - public SvgTemplate getSvgTemplate(UUID id) { - Optional optional = svgRenderTemplateRepository.findById(id); - SvgTemplate svgRenderTemplate = optional.orElseThrow(() -> new TemplateException(ErrorConstants.INVALID_TEMPLATE_ID)); - - return svgRenderTemplate; - - } -} diff --git a/certify-service/src/main/java/io/mosip/certify/services/VCIssuanceServiceImpl.java b/certify-service/src/main/java/io/mosip/certify/services/VCIssuanceServiceImpl.java index e768e6dd..89c3c4e0 100644 --- a/certify-service/src/main/java/io/mosip/certify/services/VCIssuanceServiceImpl.java +++ b/certify-service/src/main/java/io/mosip/certify/services/VCIssuanceServiceImpl.java @@ -28,7 +28,7 @@ import io.mosip.certify.core.spi.VCIssuanceService; import io.mosip.certify.core.util.AuditHelper; import io.mosip.certify.core.util.SecurityHelperService; -import io.mosip.certify.core.validators.CredentialRequestValidatorFactory; +import io.mosip.certify.validators.CredentialRequestValidator; import io.mosip.certify.exception.InvalidNonceException; import io.mosip.certify.proof.ProofValidator; import io.mosip.certify.proof.ProofValidatorFactory; @@ -41,18 +41,13 @@ import java.time.Instant; import java.time.LocalDateTime; import java.time.ZoneOffset; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Optional; +import java.util.*; @Slf4j @Service -@ConditionalOnProperty(value = "mosip.certify.issuer", havingValue = "PluginIssuer") +@ConditionalOnProperty(value = "mosip.certify.plugin-mode", havingValue = "VCIssuance") public class VCIssuanceServiceImpl implements VCIssuanceService { - private static final String TYPE_VERIFIABLE_CREDENTIAL = "VerifiableCredential"; - @Value("#{${mosip.certify.key-values}}") private LinkedHashMap> issuerMetadata; @@ -79,7 +74,7 @@ public class VCIssuanceServiceImpl implements VCIssuanceService { @Override public CredentialResponse getCredential(CredentialRequest credentialRequest) { - boolean isValidCredentialRequest = new CredentialRequestValidatorFactory().isValid(credentialRequest); + boolean isValidCredentialRequest = new CredentialRequestValidator().isValid(credentialRequest); if(!isValidCredentialRequest) { throw new InvalidRequestException(ErrorConstants.INVALID_REQUEST); } @@ -119,11 +114,147 @@ public CredentialResponse getCredential(CredentialRequest credentialRequest) { @Override public Map getCredentialIssuerMetadata(String version) { - if(issuerMetadata.containsKey(version)) + if(issuerMetadata.containsKey(version)) { return issuerMetadata.get(version); + } else if(version != null && version.equals("vd12")) { + LinkedHashMap originalIssuerMetadata = new LinkedHashMap<>(issuerMetadata.get("latest")); + Map vd12IssuerMetadata = convertLatestToVd12(originalIssuerMetadata); + issuerMetadata.put("vd12", (LinkedHashMap) vd12IssuerMetadata); + return vd12IssuerMetadata; + } else if(version != null && version.equals("vd11")) { + LinkedHashMap originalIssuerMetadata = new LinkedHashMap<>(issuerMetadata.get("latest")); + Map vd11IssuerMetadata = convertLatestToVd11(originalIssuerMetadata); + issuerMetadata.put("vd11", (LinkedHashMap) vd11IssuerMetadata); + return vd11IssuerMetadata; + } throw new InvalidRequestException(ErrorConstants.UNSUPPORTED_OPENID_VERSION); } + @Override + public Map getDIDDocument() { + throw new InvalidRequestException(ErrorConstants.UNSUPPORTED_IN_CURRENT_PLUGIN_MODE); + } + + private Map convertLatestToVd11(LinkedHashMap vciMetadata) { + // Create a list to hold the transformed credentials + List> credentialsList = new ArrayList<>(); + + // Check if the original config contains 'credential_configurations_supported' + if (vciMetadata.containsKey("credential_configurations_supported")) { + // Cast the value to a Map + Map originalCredentials = + (Map) vciMetadata.get("credential_configurations_supported"); + + // Iterate through each credential + for (Map.Entry entry : originalCredentials.entrySet()) { + // Cast the credential configuration + Map credConfig = (Map) entry.getValue(); + + // Create a new transformed credential configuration + Map transformedCredential = new HashMap<>(credConfig); + + // Add 'id' field with the original key + transformedCredential.put("id", entry.getKey()); + + // Rename 'credential_signing_alg_values_supported' to 'cryptographic_suites_supported' + if (transformedCredential.containsKey("credential_signing_alg_values_supported")) { + transformedCredential.put("cryptographic_suites_supported", + transformedCredential.remove("credential_signing_alg_values_supported")); + } + + // Modify proof_types_supported + if (transformedCredential.containsKey("proof_types_supported")) { + Map proofTypes = (Map) transformedCredential.get("proof_types_supported"); + transformedCredential.put("proof_types_supported", proofTypes.keySet()); + } + + if(transformedCredential.containsKey("display")) { + List> displayMapList = new ArrayList<>((List>)transformedCredential.get("display")); + List> newDisplayMapList = new ArrayList<>(); + for(Map map : displayMapList) { + Map displayMap = new HashMap<>(map); + displayMap.remove("background_image"); + newDisplayMapList.add(displayMap); + } + transformedCredential.put("display", newDisplayMapList); + } + + // Remove 'order' if it exists + transformedCredential.remove("order"); + + // Add the transformed credential to the list + credentialsList.add(transformedCredential); + } + + // Set the transformed credentials in the new configuration + vciMetadata.put("credentials_supported", credentialsList); + } + + vciMetadata.remove("credential_configurations_supported"); + vciMetadata.remove("authorization_servers"); + vciMetadata.remove("display"); + String endpoint = (String)vciMetadata.get("credential_endpoint"); + int issuanceIndex = endpoint.indexOf("issuance/"); + String newEndPoint = endpoint.substring(0, issuanceIndex+9); + vciMetadata.put("credential_endpoint", newEndPoint + "vd11/credential"); + return vciMetadata; + } + + private Map convertLatestToVd12(LinkedHashMap vciMetadata) { + // Create a new map to store the transformed configuration + if(vciMetadata.containsKey("credential_configurations_supported")) { + LinkedHashMap supportedCredentials = (LinkedHashMap) vciMetadata.get("credential_configurations_supported"); + Map transformedMap = transformCredentialConfiguration(supportedCredentials); + vciMetadata.put("credentials_supported", transformedMap); + } + + vciMetadata.remove("credential_configurations_supported"); + String endpoint = (String)vciMetadata.get("credential_endpoint"); + int issuanceIndex = endpoint.indexOf("issuance/"); + String newEndPoint = endpoint.substring(0, issuanceIndex+9); + vciMetadata.put("credential_endpoint", newEndPoint + "vd12/credential"); + return vciMetadata; + } + + private static Map transformCredentialConfiguration(LinkedHashMap originalConfig) { + Map transformedConfig = new LinkedHashMap<>(); + + for (Map.Entry entry : originalConfig.entrySet()) { + Map credentialDetails = (Map) entry.getValue(); + + // Create a new map to store modified credential details + Map transformedCredential = new LinkedHashMap<>(credentialDetails); + + // Replace 'credential_signing_alg_values_supported' with 'cryptographic_suites_supported' + if (transformedCredential.containsKey("credential_signing_alg_values_supported")) { + Object signingAlgs = transformedCredential.remove("credential_signing_alg_values_supported"); + transformedCredential.put("cryptographic_suites_supported", signingAlgs); + } + + // Modify proof_types_supported + if (transformedCredential.containsKey("proof_types_supported")) { + Map proofTypes = (Map) transformedCredential.get("proof_types_supported"); + transformedCredential.put("proof_types_supported", proofTypes.keySet()); + } + + if(transformedCredential.containsKey("display")) { + List> displayMapList = new ArrayList<>((List>)transformedCredential.get("display")); + List> newDisplayMapList = new ArrayList<>(); + for(Map map : displayMapList) { + Map displayMap = new HashMap<>(map); + displayMap.remove("background_image"); + newDisplayMapList.add(displayMap); + } + transformedCredential.put("display", newDisplayMapList); + } + + // Add the modified credential details to the transformed config + transformedConfig.put(entry.getKey(), transformedCredential); + } + + return transformedConfig; + } + private VCResult getVerifiableCredential(CredentialRequest credentialRequest, CredentialMetadata credentialMetadata, String holderId) { parsedAccessToken.getClaims().put("accessTokenHash", parsedAccessToken.getAccessTokenHash()); diff --git a/certify-service/src/main/java/io/mosip/certify/services/ldsigner/ProofSignatureStrategy.java b/certify-service/src/main/java/io/mosip/certify/services/ldsigner/ProofSignatureStrategy.java deleted file mode 100644 index 3625c1b9..00000000 --- a/certify-service/src/main/java/io/mosip/certify/services/ldsigner/ProofSignatureStrategy.java +++ /dev/null @@ -1,37 +0,0 @@ -package io.mosip.certify.services.ldsigner; - -import info.weboftrust.ldsignatures.LdProof; -import info.weboftrust.ldsignatures.canonicalizer.Canonicalizer; - -import java.util.Map; - -/** - * ProofSignatureStrategy is a helper class for KeymanagerLibSigner - * to better deal with multiple signature algorithms for JSON-LD VCs. - */ -public interface ProofSignatureStrategy { - /** - * @return returns the name of the Algorithm - */ - String getName(); - - /** - * @return the Canonicalizer which will be used to Canonicalize the templated VC - */ - Canonicalizer getCanonicalizer(); - - /** - * getProof takes canonicalized VC hash and returns proof using a competent - * SignatureService implementation - * @param vcEncodedHash - * @return - */ - String getProof(String vcEncodedHash); - /** - * buildProof takes a proof String and attaches it to a proof object as per algorithm - * @param vcLdProof the proof object of the VC - * @param sign should be a string, can be a detached JWS, another proofString based on implementors choice - * @return - */ - LdProof buildProof(LdProof vcLdProof, String sign); -} diff --git a/certify-service/src/main/java/io/mosip/certify/services/templating/VelocityTemplatingConstants.java b/certify-service/src/main/java/io/mosip/certify/services/templating/VelocityTemplatingConstants.java deleted file mode 100644 index 3c33ce94..00000000 --- a/certify-service/src/main/java/io/mosip/certify/services/templating/VelocityTemplatingConstants.java +++ /dev/null @@ -1,7 +0,0 @@ -package io.mosip.certify.services.templating; - -public class VelocityTemplatingConstants { - public static final String TEMPLATE_NAME = "templateName"; - public static final String ISSUER_URI = "issuerURI"; - public static final String SVG_TEMPLATE = "svgTemplate"; -} diff --git a/certify-service/src/main/java/io/mosip/certify/utils/DIDDocumentUtil.java b/certify-service/src/main/java/io/mosip/certify/utils/DIDDocumentUtil.java new file mode 100644 index 00000000..2452ce5e --- /dev/null +++ b/certify-service/src/main/java/io/mosip/certify/utils/DIDDocumentUtil.java @@ -0,0 +1,111 @@ +package io.mosip.certify.utils; + +import java.io.ByteArrayInputStream; +import java.security.PublicKey; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; +import java.security.interfaces.RSAPublicKey; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.HexFormat; +import java.util.Map; + +import org.bouncycastle.jcajce.provider.asymmetric.edec.BCEdDSAPublicKey; +import org.bouncycastle.jce.provider.BouncyCastleProvider; + +import com.nimbusds.jose.jwk.RSAKey; + +import io.ipfs.multibase.Multibase; +import io.mosip.certify.core.constants.ErrorConstants; +import io.mosip.certify.core.constants.SignatureAlg; +import io.mosip.certify.core.exception.CertifyException; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class DIDDocumentUtil { + + private static final String MULTICODEC_PREFIX = "ed01"; + + public static Map generateDIDDocument(String vcSignAlgorithm, String certificateString, String issuerURI, String issuerPublicKeyURI) { + + HashMap didDocument = new HashMap(); + didDocument.put("@context", Collections.singletonList("https://www.w3.org/ns/did/v1")); + didDocument.put("alsoKnownAs", new ArrayList<>()); + didDocument.put("service", new ArrayList<>()); + didDocument.put("id", issuerURI); + didDocument.put("authentication", Collections.singletonList(issuerPublicKeyURI)); + didDocument.put("assertionMethod", Collections.singletonList(issuerPublicKeyURI)); + + Map verificationMethod = null; + PublicKey publicKey = loadPublicKeyFromCertificate(certificateString); + try { + switch (vcSignAlgorithm) { + case SignatureAlg.ED25519_SIGNATURE_SUITE_2018: + verificationMethod = generateEd25519VerificationMethod(publicKey, issuerURI, issuerPublicKeyURI); + break; + case SignatureAlg.ED25519_SIGNATURE_SUITE_2020: + verificationMethod = generateEd25519VerificationMethod(publicKey, issuerURI, issuerPublicKeyURI); + break; + case SignatureAlg.RSA_SIGNATURE_SUITE_2018: + verificationMethod = generateRSAVerificationMethod(publicKey, issuerURI, issuerPublicKeyURI); + break; + default: + log.error("Unsupported signature algorithm provided :" + vcSignAlgorithm); + throw new CertifyException(ErrorConstants.UNSUPPORTED_ALGORITHM); + } + } catch(CertifyException e) { + throw e; + } catch (Exception e) { + log.error("Exception occured while generating verification method for given certificate", e.getMessage(), e); + throw new CertifyException(ErrorConstants.VERIFICATION_METHOD_GENERATION_FAILED); + } + + didDocument.put("verificationMethod", Collections.singletonList(verificationMethod)); + return didDocument; + } + + private static PublicKey loadPublicKeyFromCertificate(String certificateString) { + try { + ByteArrayInputStream fis = new ByteArrayInputStream(certificateString.getBytes()); + CertificateFactory certFactory = CertificateFactory.getInstance("X.509", new BouncyCastleProvider()); + X509Certificate certificate = (X509Certificate) certFactory.generateCertificate(fis); + return certificate.getPublicKey(); + } catch (Exception e) { + log.error("Convertion from certificate to public key failed", e.getMessage(), e); + throw new CertifyException(ErrorConstants.INVALID_CERTIFICATE); + } + } + + private static Map generateEd25519VerificationMethod(PublicKey publicKey, String issuerURI, String issuerPublicKeyURI) throws Exception { + BCEdDSAPublicKey edKey = (BCEdDSAPublicKey) publicKey; + byte[] rawBytes = edKey.getPointEncoding(); + byte[] multicodecBytes = HexFormat.of().parseHex(MULTICODEC_PREFIX); + byte[] finalBytes = new byte[multicodecBytes.length + rawBytes.length]; + System.arraycopy(multicodecBytes, 0, finalBytes, 0, multicodecBytes.length); + System.arraycopy(rawBytes, 0, finalBytes, multicodecBytes.length, rawBytes.length); + String publicKeyMultibase = Multibase.encode(Multibase.Base.Base58BTC, finalBytes); + + Map verificationMethod = new HashMap<>(); + verificationMethod.put("id", issuerPublicKeyURI); + verificationMethod.put("type", "Ed25519VerificationKey2020"); + verificationMethod.put("@context", "https://w3id.org/security/suites/ed25519-2020/v1"); + verificationMethod.put("controller", issuerURI); + verificationMethod.put("publicKeyMultibase", publicKeyMultibase); + return verificationMethod; + } + + private static Map generateRSAVerificationMethod(PublicKey publicKey, String issuerURI, String issuerPublicKeyURI) throws Exception { + RSAKey rsaKey = new RSAKey.Builder((RSAPublicKey) publicKey).build(); + Map publicKeyJwk = rsaKey.toJSONObject(); + + Map verificationMethod = new HashMap<>(); + verificationMethod.put("id", issuerPublicKeyURI); + verificationMethod.put("type", "JsonWebKey2020"); + verificationMethod.put("@context", "https://w3id.org/security/suites/jws-2020/v1"); + verificationMethod.put("controller", issuerURI); + verificationMethod.put("publicKeyJwk", publicKeyJwk); + return verificationMethod; + } + +} diff --git a/certify-service/src/main/java/io/mosip/certify/validators/CredentialRequestValidator.java b/certify-service/src/main/java/io/mosip/certify/validators/CredentialRequestValidator.java new file mode 100644 index 00000000..84872b9e --- /dev/null +++ b/certify-service/src/main/java/io/mosip/certify/validators/CredentialRequestValidator.java @@ -0,0 +1,15 @@ +package io.mosip.certify.validators; + +import io.mosip.certify.core.constants.VCFormats; +import io.mosip.certify.core.dto.CredentialRequest; + +public class CredentialRequestValidator { + public static boolean isValid(CredentialRequest credentialRequest) { + if (credentialRequest.getFormat().equals(VCFormats.LDP_VC)) { + return LdpVcCredentialRequestValidator.isValidCheck(credentialRequest); + } else if (credentialRequest.getFormat().equals(VCFormats.MSO_MDOC)) { + return MsoMdocCredentialRequestValidator.isValidCheck(credentialRequest); + } + return false; + } +} diff --git a/certify-service/src/main/java/io/mosip/certify/validators/LdpVcCredentialRequestValidator.java b/certify-service/src/main/java/io/mosip/certify/validators/LdpVcCredentialRequestValidator.java new file mode 100644 index 00000000..9e5f4ece --- /dev/null +++ b/certify-service/src/main/java/io/mosip/certify/validators/LdpVcCredentialRequestValidator.java @@ -0,0 +1,9 @@ +package io.mosip.certify.validators; + +import io.mosip.certify.core.dto.CredentialRequest; + +public class LdpVcCredentialRequestValidator { + public static boolean isValidCheck(CredentialRequest credentialRequest) { + return credentialRequest.getCredential_definition() != null; + } +} diff --git a/certify-service/src/main/java/io/mosip/certify/validators/MsoMdocCredentialRequestValidator.java b/certify-service/src/main/java/io/mosip/certify/validators/MsoMdocCredentialRequestValidator.java new file mode 100644 index 00000000..0e9d91c1 --- /dev/null +++ b/certify-service/src/main/java/io/mosip/certify/validators/MsoMdocCredentialRequestValidator.java @@ -0,0 +1,12 @@ +package io.mosip.certify.validators; + +import io.mosip.certify.core.dto.CredentialRequest; + +public class MsoMdocCredentialRequestValidator { + public static boolean isValidCheck(CredentialRequest credentialRequest) { + if (credentialRequest.getDoctype() == null || credentialRequest.getDoctype().isBlank()) { + return false; + } + return credentialRequest.getClaims() != null && !credentialRequest.getClaims().isEmpty(); + } +} diff --git a/certify-service/src/main/java/io/mosip/certify/vcformatters/VCFormatter.java b/certify-service/src/main/java/io/mosip/certify/vcformatters/VCFormatter.java new file mode 100644 index 00000000..5acb21ef --- /dev/null +++ b/certify-service/src/main/java/io/mosip/certify/vcformatters/VCFormatter.java @@ -0,0 +1,19 @@ +package io.mosip.certify.vcformatters; + +import java.util.Map; + +import org.json.JSONObject; +/** + * VCDataModelFormatter is a templating engine which takes @param templateInput and returns a templated VC. + * Some implementations include + * - VC 1.0 & 2.0 data model templating engine using Velocity + */ +public interface VCFormatter { + /** + * returns a templated VC as per the data in valueMap & some templateSettings + * @param valueMap data provided by a {@link DataProviderPlugin} implementation. + * @param templateSettings configurable tunables + * @return a templated & unsigned VC + */ + String format(JSONObject valueMap, Map templateSettings); +} \ No newline at end of file diff --git a/certify-service/src/main/java/io/mosip/certify/services/templating/VelocityTemplatingEngineImpl.java b/certify-service/src/main/java/io/mosip/certify/vcformatters/VelocityTemplatingEngineImpl.java similarity index 53% rename from certify-service/src/main/java/io/mosip/certify/services/templating/VelocityTemplatingEngineImpl.java rename to certify-service/src/main/java/io/mosip/certify/vcformatters/VelocityTemplatingEngineImpl.java index 73be64f1..164b9ae1 100644 --- a/certify-service/src/main/java/io/mosip/certify/services/templating/VelocityTemplatingEngineImpl.java +++ b/certify-service/src/main/java/io/mosip/certify/vcformatters/VelocityTemplatingEngineImpl.java @@ -3,22 +3,26 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ -package io.mosip.certify.services.templating; +package io.mosip.certify.vcformatters; import java.io.*; +import java.time.Duration; import java.time.ZoneOffset; import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeParseException; import java.util.*; -import io.mosip.certify.api.spi.VCFormatter; +import io.mosip.certify.core.constants.ErrorConstants; +import io.mosip.certify.core.exception.CertifyException; +import io.mosip.certify.entity.CredentialTemplate; import io.mosip.certify.core.constants.Constants; import io.mosip.certify.core.constants.VCDM2Constants; import io.mosip.certify.core.constants.VCDMConstants; -import io.mosip.certify.core.exception.TemplateException; -import io.mosip.certify.core.repository.TemplateRepository; -import io.mosip.certify.core.spi.SvgTemplateService; -import io.mosip.certify.services.SVGRenderUtils; +import io.mosip.certify.core.exception.RenderingTemplateException; +import io.mosip.certify.repository.CredentialTemplateRepository; +import io.mosip.certify.core.spi.RenderingTemplateService; +import io.mosip.certify.services.CredentialUtils; import jakarta.annotation.PostConstruct; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; @@ -32,23 +36,24 @@ import org.json.JSONObject; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; +import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; -import static io.mosip.certify.services.templating.VelocityTemplatingConstants.*; - @Slf4j @Service public class VelocityTemplatingEngineImpl implements VCFormatter { VelocityEngine engine; public static final String DELIMITER = ":"; - Map templateCache; + public static final String TEMPLATE_CACHE = "templatecache"; @Autowired - TemplateRepository templateRepository; + CredentialTemplateRepository credentialTemplateRepository; @Autowired - SvgTemplateService svgTemplateService; - @Value("${mosip.certify.vcformat.vc.expiry:true}") - boolean shouldHaveDates; - @Value("${mosip.certify.issuer.id.field.prefix.url:}") + RenderingTemplateService renderingTemplateService; + + @Value("${mosip.certify.data-provider-plugin.vc-expiry-duration:P730d}") + String defaultExpiryDuration; + + @Value("${mosip.certify.data-provider-plugin.id-field-prefix-uri:}") String idPrefix; @PostConstruct @@ -56,8 +61,6 @@ public void initialize() { engine = new VelocityEngine(); // TODO: The DataSourceResourceLoader can be used instead if there's a // single primary key column and the table has a last modified date. - templateCache = new HashMap<>(); - templateRepository.findAll().stream().forEach((template -> templateCache.put(String.join(DELIMITER, template.getCredentialType(), template.getContext()), template.getTemplate()))); engine.setProperty(RuntimeConstants.INPUT_ENCODING, "UTF-8"); engine.setProperty(RuntimeConstants.OUTPUT_ENCODING, "UTF-8"); engine.init(); @@ -70,30 +73,31 @@ public void initialize() { * NOTE: the defaultSettings map should have the "templateName" key set to * "${sort(CREDENTIALTYPE1,CREDENTIALTYPE2,CREDENTIALTYPE3...)}:${sort(VC_CONTEXT1,VC_CONTENXT2,VC_CONTEXT3...)}" * - * @param templateInput is the input from the DataProvider plugin - * @param defaultSettings has some sensible defaults from Certify for + * @param valueMap is the input from the DataProvider plugin + * @param templateSettings has some sensible defaults from Certify for * internal work such as locating the appropriate template * @return templated VC as a String */ @SneakyThrows @Override - public String format(JSONObject templateInput, Map defaultSettings) { + public String format(JSONObject valueMap, Map templateSettings) { // TODO: Isn't template name becoming too complex with VC_CONTEXTS & CREDENTIAL_TYPES both? - String templateName = defaultSettings.get(TEMPLATE_NAME).toString(); - String issuer = defaultSettings.get(ISSUER_URI).toString(); - String t = templateCache.get(templateName); + String templateName = templateSettings.get(Constants.TEMPLATE_NAME).toString(); + String template = getTemplate(templateName); + if (template == null) { + log.error("Template {} not found", templateName); + throw new CertifyException(ErrorConstants.EXPECTED_TEMPLATE_NOT_FOUND); + } + String issuer = templateSettings.get(Constants.ISSUER_URI).toString(); StringWriter writer = new StringWriter(); // 1. Prepare map // TODO: Eventually, the credentialSubject from the plugin will be templated as-is Map finalTemplate = new HashMap<>(); - Iterator keys = templateInput.keys(); + Iterator keys = valueMap.keys(); while(keys.hasNext()) { String key = keys.next(); - Object value = templateInput.get(key); + Object value = valueMap.get(key); if (value instanceof List) { - // TODO(problem area): handle field values with unescaped JSON - // reserved literals such as " or , - // (Q) Should Object always be a JSONObject? finalTemplate.put(key, new JSONArray((List) value)); } else if (value.getClass().isArray()) { finalTemplate.put(key, new JSONArray(List.of(value))); @@ -112,26 +116,32 @@ public String format(JSONObject templateInput, Map defaultSettin // Escape: https://velocity.apache.org/tools/3.1/apidocs/org/apache/velocity/tools/generic/EscapeTool.html finalTemplate.put("_esc", new EscapeTool()); // add the issuer value - finalTemplate.put("issuer", issuer); - if (defaultSettings.containsKey(SVG_TEMPLATE) && templateName.contains(VCDM2Constants.URL)) { + finalTemplate.put("_issuer", issuer); + if (templateSettings.containsKey(Constants.RENDERING_TEMPLATE_ID) && templateName.contains(VCDM2Constants.URL)) { try { finalTemplate.put("_renderMethodSVGdigest", - SVGRenderUtils.getDigestMultibase(svgTemplateService.getSvgTemplate( - UUID.fromString((String) defaultSettings.get(SVG_TEMPLATE))).getTemplate())); - } catch (TemplateException e) { - log.error("SVG Template: " + defaultSettings.get(SVG_TEMPLATE) + " not available in DB", e); + CredentialUtils.getDigestMultibase(renderingTemplateService.getSvgTemplate( + (String) templateSettings.get(Constants.RENDERING_TEMPLATE_ID)).getTemplate())); + } catch (RenderingTemplateException e) { + log.error("SVG Template: " + templateSettings.get(Constants.RENDERING_TEMPLATE_ID) + " not available in DB", e); } } - if (shouldHaveDates && !(templateInput.has(VCDM2Constants.VALID_FROM) - && templateInput.has(VCDM2Constants.VALID_UNITL))) { - String time = ZonedDateTime.now(ZoneOffset.UTC).format(DateTimeFormatter.ofPattern(Constants.UTC_DATETIME_PATTERN)); - // hardcoded time - String expiryTime = ZonedDateTime.now(ZoneOffset.UTC).plusYears(2).format(DateTimeFormatter.ofPattern(Constants.UTC_DATETIME_PATTERN)); - finalTemplate.put(VCDM2Constants.VALID_FROM, time); + if (!valueMap.has(VCDM2Constants.VALID_UNITL) && StringUtils.isNotEmpty(defaultExpiryDuration)) { + Duration duration; + try { + duration = Duration.parse(defaultExpiryDuration); + } catch (DateTimeParseException e) { + // set 730days(~2Y) as default VC expiry + duration = Duration.parse("P730D"); + } + String expiryTime = ZonedDateTime.now(ZoneOffset.UTC).plusSeconds(duration.getSeconds()).format(DateTimeFormatter.ofPattern(Constants.UTC_DATETIME_PATTERN)); finalTemplate.put(VCDM2Constants.VALID_UNITL, expiryTime); } + if (!valueMap.has(VCDM2Constants.VALID_FROM)) { + finalTemplate.put(VCDM2Constants.VALID_FROM, ZonedDateTime.now(ZoneOffset.UTC).format(DateTimeFormatter.ofPattern(Constants.UTC_DATETIME_PATTERN))); + } VelocityContext context = new VelocityContext(finalTemplate); - engine.evaluate(context, writer, /*logTag */ templateName,t.toString()); + engine.evaluate(context, writer, /*logTag */ templateName,template.toString()); if (StringUtils.isNotEmpty(idPrefix)) { JSONObject j = new JSONObject(writer.toString()); j.put(VCDMConstants.ID, idPrefix + UUID.randomUUID()); @@ -139,4 +149,24 @@ public String format(JSONObject templateInput, Map defaultSettin } return writer.toString(); } + + /** + * getTemplate fetches the VelocityTemplate from the DB or Spring Cache + * @param key key is a combination of sorted credentialType & sorted + * context separated by a ':'. + * @return + */ + @Cacheable(cacheNames = TEMPLATE_CACHE, key = "#key") + public String getTemplate(String key) { + if (!key.contains(DELIMITER)) { + return null; + } + String credentialType = key.split(DELIMITER)[0]; + String context = key.split(DELIMITER, 2)[1]; + CredentialTemplate template = credentialTemplateRepository.findByCredentialTypeAndContext(credentialType, context).orElse(null); + if (template != null) { + return template.getTemplate(); + } else + return null; + } } diff --git a/certify-service/src/main/java/io/mosip/certify/services/KeymanagerLibSigner.java b/certify-service/src/main/java/io/mosip/certify/vcsigners/JsonLDVCSigner.java similarity index 67% rename from certify-service/src/main/java/io/mosip/certify/services/KeymanagerLibSigner.java rename to certify-service/src/main/java/io/mosip/certify/vcsigners/JsonLDVCSigner.java index f513f223..eb910daa 100644 --- a/certify-service/src/main/java/io/mosip/certify/services/KeymanagerLibSigner.java +++ b/certify-service/src/main/java/io/mosip/certify/vcsigners/JsonLDVCSigner.java @@ -3,17 +3,16 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ -package io.mosip.certify.services; +package io.mosip.certify.vcsigners; import foundation.identity.jsonld.JsonLDException; import foundation.identity.jsonld.JsonLDObject; import info.weboftrust.ldsignatures.LdProof; import info.weboftrust.ldsignatures.canonicalizer.Canonicalizer; import io.mosip.certify.api.dto.VCResult; -import io.mosip.certify.api.spi.VCSigner; import io.mosip.certify.core.constants.*; import io.mosip.certify.core.exception.CertifyException; -import io.mosip.certify.services.ldsigner.ProofSignatureStrategy; +import io.mosip.certify.proofgenerators.ProofGenerator; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; @@ -32,7 +31,7 @@ import java.util.Map; /** - * KeymanagerLibSigner is a VCSigner which uses the Certify embedded + * JsonLDVCSigner is a VCSigner which uses the Certify embedded * keymanager to perform VC signing tasks for JSON LD VCs. * These are the known external requirements: * - the public key must be pre-hosted for the VC & should be available @@ -42,25 +41,25 @@ */ @Slf4j @Service -public class KeymanagerLibSigner implements VCSigner { +public class JsonLDVCSigner implements VCSigner { @Autowired - ProofSignatureStrategy signProps; - @Value("${mosip.certify.issuer.pub.key}") - private String hostedKey; + ProofGenerator proofGenerator; + @Value("${mosip.certify.data-provider-plugin.issuer-public-key-uri}") + private String issuerPublicKeyURI; @Override - public VCResult perform(String templatedVC) { + public VCResult attachSignature(String unSignedVC, Map keyReferenceDetails) { // Can the below lines be done at Templating side itself ? VCResult VC = new VCResult<>(); - JsonLDObject j = JsonLDObject.fromJson(templatedVC); - j.setDocumentLoader(null); + JsonLDObject jsonLDObject = JsonLDObject.fromJson(unSignedVC); + jsonLDObject.setDocumentLoader(null); // NOTE: other aspects can be configured via keyMgrInput map String validFrom; - if (j.getJsonObject().containsKey(VCDM1Constants.ISSUANCE_DATE)) { - validFrom = j.getJsonObject().get(VCDM1Constants.ISSUANCE_DATE).toString(); - } else if (j.getJsonObject().containsKey(VCDM2Constants.VALID_FROM)){ - validFrom = j.getJsonObject().get(VCDM2Constants.VALID_FROM).toString(); + if (jsonLDObject.getJsonObject().containsKey(VCDM1Constants.ISSUANCE_DATE)) { + validFrom = jsonLDObject.getJsonObject().get(VCDM1Constants.ISSUANCE_DATE).toString(); + } else if (jsonLDObject.getJsonObject().containsKey(VCDM2Constants.VALID_FROM)) { + validFrom = jsonLDObject.getJsonObject().get(VCDM2Constants.VALID_FROM).toString(); } else { validFrom = ZonedDateTime.now(ZoneOffset.UTC) .format(DateTimeFormatter.ofPattern(Constants.UTC_DATETIME_PATTERN)); @@ -72,24 +71,23 @@ public VCResult perform(String templatedVC) { .parse(validFrom, DateTimeFormatter.ofPattern(Constants.UTC_DATETIME_PATTERN)) .atZone(ZoneId.systemDefault()).toInstant()); - LdProof vcLdProof = LdProof.builder().defaultContexts(false).defaultTypes(false).type(signProps.getName()) + LdProof vcLdProof = LdProof.builder().defaultContexts(false).defaultTypes(false).type(proofGenerator.getName()) .created(createDate).proofPurpose(VCDMConstants.ASSERTION_METHOD) - .verificationMethod(URI.create(hostedKey)) + .verificationMethod(URI.create(issuerPublicKeyURI)) .build(); // 1. Canonicalize - Canonicalizer canonicalizer = signProps.getCanonicalizer(); - byte[] vcSignBytes = null; + Canonicalizer canonicalizer = proofGenerator.getCanonicalizer(); + byte[] vcHashBytes; try { - vcSignBytes = canonicalizer.canonicalize(vcLdProof, j); + vcHashBytes = canonicalizer.canonicalize(vcLdProof, jsonLDObject); } catch (IOException | GeneralSecurityException | JsonLDException e) { log.error("Error during canonicalization", e.getMessage()); throw new CertifyException("Error during canonicalization"); } - String vcEncodedHash = Base64.getUrlEncoder().encodeToString(vcSignBytes); - String sign = signProps.getProof(vcEncodedHash); - LdProof ldProofWithJWS = signProps.buildProof(vcLdProof, sign); - ldProofWithJWS.addToJsonLDObject(j); - VC.setCredential(j); + String vcEncodedHash = Base64.getUrlEncoder().encodeToString(vcHashBytes); + LdProof ldProofWithJWS = proofGenerator.generateProof(vcLdProof, vcEncodedHash, keyReferenceDetails); + ldProofWithJWS.addToJsonLDObject(jsonLDObject); + VC.setCredential(jsonLDObject); return VC; // MOSIP ref: https://github.com/mosip/id-authentication/blob/master/authentication/authentication-service/src/main/java/io/mosip/authentication/service/kyc/impl/VciServiceImpl.java#L281 } diff --git a/certify-service/src/main/java/io/mosip/certify/vcsigners/VCSigner.java b/certify-service/src/main/java/io/mosip/certify/vcsigners/VCSigner.java new file mode 100644 index 00000000..062c81a6 --- /dev/null +++ b/certify-service/src/main/java/io/mosip/certify/vcsigners/VCSigner.java @@ -0,0 +1,13 @@ +package io.mosip.certify.vcsigners; + +import io.mosip.certify.api.dto.VCResult; + +import java.util.Map; + +/** + * VCSigner can sign any JSON-LD VC provided a vcHash & Signer inputs and + * return a signed VCResult. + */ +public interface VCSigner { + VCResult attachSignature(String unSignedVC, Map keyReferenceDetails); +} diff --git a/certify-service/src/main/resources/application-local.properties b/certify-service/src/main/resources/application-local.properties index bc0d2ac2..19b7705e 100644 --- a/certify-service/src/main/resources/application-local.properties +++ b/certify-service/src/main/resources/application-local.properties @@ -10,7 +10,7 @@ mosip.certify.security.ignore-csrf-urls=**/actuator/**,/favicon.ico,**/error,\ **/issuance/**,**/system-info/** mosip.certify.security.ignore-auth-urls=/actuator/**,**/error,**/swagger-ui/**,\ - **/v3/api-docs/**, **/issuance/**,/system-info/**,/public/** + **/v3/api-docs/**, **/issuance/**,/system-info/**,/rendering-template/** ## ------------------------------------------ Discovery openid-configuration ------------------------------------------- @@ -18,8 +18,8 @@ mosip.certify.domain.url=http://localhost:8090 mosipbox.public.url=https://localhost:8090 mosip.certify.authorization.url=http://localhost:8088 mosip.certify.discovery.issuer-id=${mosip.certify.domain.url}${server.servlet.path} -mosip.certify.issuer.vc-sign-algo=Ed25519Signature2018 -mosip.certify.issuer=CertifyIssuer +mosip.certify.data-provider-plugin.issuer.vc-sign-algo=Ed25519Signature2018 +mosip.certify.plugin-mode=DataProvider ##--------------change this later--------------------------------- mosip.certify.supported.jwt-proof-alg={'RS256','PS256','ES256'} @@ -31,7 +31,6 @@ mosip.certify.authn.filter-urls={ '${server.servlet.path}/issuance/credential', mosip.certify.authn.issuer-uri=http://localhost:8088/v1/esignet mosip.certify.authn.jwk-set-uri=http://localhost:8088/v1/esignet/oauth/.well-known/jwks.json mosip.certify.authn.allowed-audiences={ '${mosip.certify.domain.url}${server.servlet.path}/issuance/credential', 'http://localhost:8088/v1/esignet/vci/credential' } -mosip.certify.dataprovider.types={'MockVerifiableCredential','StudentCredential','UniversityCredential'} mosip.certify.key-values={\ 'vd12' : {\ 'credential_issuer': '${mosip.certify.identifier}', \ @@ -175,7 +174,7 @@ mosip.certify.key-values={\ }}\ }\ } -mosip.certify.svg-templates=svg-template.json +mosip.certify.rendering-templates=svg-template.json ## ------------------------------------------- Integrations ------------------------------------------------------------ #mosip.certify.integration.scan-base-package=io.mosip.certify.sunbirdrc.integration @@ -201,15 +200,24 @@ mosip.certify.vcformat.vc.expiry=true ## ------------------------------------------- Mock ID Integration properties ------------------------------------------------------------ mosip.certify.integration.scan-base-package=io.mosip.certify.mock.integration mosip.certify.integration.audit-plugin=LoggerAuditService -mosip.certify.integration.vci-plugin=MockVCIssuancePlugin +#mosip.certify.integration.vci-plugin=MockVCIssuancePlugin +mosip.certify.integration.data-provider-plugin=MockCSVDataProviderPlugin +mosip.certify.mock.data-provider.csv.identifier-column=id +mosip.certify.mock.data-provider.csv.data-columns=id,name,phoneNumber,dateOfBirth,highestEducation,typeOfHouse,numberOfDependents,works,landArea,landOwnershipType,primaryCropType,secondaryCropType,maritalStatus +mosip.certify.mock.data-provider.csv-registry-uri=https://raw.githubusercontent.com/jainhitesh9998/digital-credential-plugins/refs/heads/develop/mock-certify-plugin/src/test/resources/farmer_identity_data.csv mosip.certify.mock.vciplugin.verification-method=${mosip.certify.authn.jwk-set-uri} mosip.certify.mock.authenticator.get-identity-url=http://localhost:8082/v1/mock-identity-system/identity -#TODO: get the secret for key-cert onboarded for local test -mosip.certify.mock.vciplugin.issuer.key-cert="dummy-issuer-cert" + +## ------------------------------------------- Mock Mdoc Integration properties ------------------------------------------------------------ +# mosip.certify.integration.scan-base-package=io.mosip.certify.mock.integration +# mosip.certify.integration.audit-plugin=LoggerAuditService +# mosip.certify.integration.vci-plugin=MDocMockVCIssuancePlugin +# #Get the secret for key-cert onboarded for local test +# mosip.certify.mock.vciplugin.mdoc.issuer-key-cert= # details of VC issuer's public key & controller for DataProvider plugin -mosip.certify.issuer.pub.key=https://vharsh.github.io/DID/mock-rsa.json -mosip.certify.issuer.uri=https://vharsh.github.io/DID/mock-rsac.json +mosip.certify.data-provider-plugin.issuer-public-key-uri=https://vharsh.github.io/DID/mock-rsa.json +mosip.certify.data-provider-plugin.issuer-uri=https://vharsh.github.io/DID/mock-rsac.json ## ---------------------------------------- Cache configuration -------------------------------------------------------- @@ -224,18 +232,19 @@ mosip.certify.cache.security.algorithm-name=AES/ECB/PKCS5Padding #spring.data.redis.password=redis spring.cache.type=simple -mosip.certify.cache.names=userinfo,vcissuance +mosip.certify.cache.names=userinfo,vcissuance,templatecache spring.cache.cache-names=${mosip.certify.cache.names} management.health.redis.enabled=false mosip.certify.access-token-expire-seconds=86400 - +# VC template cache valid for half day +mosip.certify.templatecache-expire-seconds=43200 # Cache size setup is applicable only for 'simple' cache type. # Cache size configuration will not be considered with 'Redis' cache type -mosip.certify.cache.size={'userinfo': 200, 'vcissuance' : 2000 } +mosip.certify.cache.size={'userinfo': 200, 'vcissuance' : 2000, 'templatecache': 20} # Cache expire in seconds is applicable for both 'simple' and 'Redis' cache type -mosip.certify.cache.expire-in-seconds={'userinfo': ${mosip.certify.access-token-expire-seconds}, 'vcissuance': ${mosip.certify.access-token-expire-seconds}} +mosip.certify.cache.expire-in-seconds={'userinfo': ${mosip.certify.access-token-expire-seconds}, 'vcissuance': ${mosip.certify.access-token-expire-seconds}, 'templatecache': ${mosip.certify.templatecache-expire-seconds}} ##-----------------------------VCI related demo configuration---------------------------------------------## diff --git a/certify-service/src/main/resources/svg-template.json b/certify-service/src/main/resources/svg-template.json deleted file mode 100644 index 26d50c03..00000000 --- a/certify-service/src/main/resources/svg-template.json +++ /dev/null @@ -1,6 +0,0 @@ -[ - { - "id": "5b9c2a12-810a-7388-2dc8-13ee7ad88bac", - "content": "\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n {{credentialSubject/policyName}}\n {{credentialSubject/policyNumber}}\n {{credentialSubject/fullName}}\n {{credentialSubject/gender}}\n {{credentialSubject/email}}\n {{credentialSubject/mobile}}\n\n Policy Issued On\n {{credentialSubject/policyIssuedOn}}\n\n Policy Expires On\n {{credentialSubject/policyExpiresOn}}\n\n Issuance Date On\n {{issuanceDate}}\n\n Expiration Date On\n {{expirationDate}}\n" - } -] \ No newline at end of file diff --git a/certify-service/src/test/java/io/mosip/certify/TestVCIssuanceServiceImpl.java b/certify-service/src/test/java/io/mosip/certify/TestVCIssuanceServiceImpl.java index 7a18a70f..db421af6 100644 --- a/certify-service/src/test/java/io/mosip/certify/TestVCIssuanceServiceImpl.java +++ b/certify-service/src/test/java/io/mosip/certify/TestVCIssuanceServiceImpl.java @@ -1,13 +1,15 @@ package io.mosip.certify; +import io.mosip.certify.core.constants.ErrorConstants; import io.mosip.certify.core.dto.CredentialRequest; import io.mosip.certify.core.dto.CredentialResponse; +import io.mosip.certify.core.exception.InvalidRequestException; import io.mosip.certify.core.spi.VCIssuanceService; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import java.util.Map; -@ConditionalOnProperty(value = "mosip.certify.issuer", havingValue = "TestIssuer") +@ConditionalOnProperty(value = "mosip.certify.plugin-mode", havingValue = "VCIssuance") public class TestVCIssuanceServiceImpl implements VCIssuanceService { @Override public CredentialResponse getCredential(CredentialRequest credentialRequest) { @@ -24,4 +26,9 @@ public CredentialResponse getCredential(CredentialRequest credentialReque public Map getCredentialIssuerMetadata(String version) { return Map.of(); } + + @Override + public Map getDIDDocument() { + throw new InvalidRequestException(ErrorConstants.UNSUPPORTED_IN_CURRENT_PLUGIN_MODE); + } } diff --git a/certify-service/src/test/java/io/mosip/certify/VCICacheServiceTest.java b/certify-service/src/test/java/io/mosip/certify/VCICacheServiceTest.java new file mode 100644 index 00000000..96eb2c85 --- /dev/null +++ b/certify-service/src/test/java/io/mosip/certify/VCICacheServiceTest.java @@ -0,0 +1,59 @@ +package io.mosip.certify; + +import io.mosip.certify.core.dto.VCIssuanceTransaction; +import io.mosip.certify.services.VCICacheService; +import org.junit.Before; +import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; +import org.springframework.cache.Cache; +import org.springframework.cache.CacheManager; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.*; + +@RunWith(MockitoJUnitRunner.class) +public class VCICacheServiceTest { + @Mock + private CacheManager cacheManager; + + @Mock + private Cache cache; + + @InjectMocks + private VCICacheService vciCacheService = new VCICacheService(); + + private static final String TEST_ACCESS_TOKEN_HASH = "testHash123"; + private static final String VCISSUANCE_CACHE = "vcissuance"; + + @Before + public void setup() { + when(cacheManager.getCache(VCISSUANCE_CACHE)).thenReturn(cache); + } + + @Test + public void setVCITransaction_ShouldReturnSameTransaction() { + VCIssuanceTransaction transaction = new VCIssuanceTransaction(); + transaction.setCNonce("test-cnonce"); + VCIssuanceTransaction result = vciCacheService.setVCITransaction(TEST_ACCESS_TOKEN_HASH, transaction); + assertNotNull(result); + assertEquals(transaction, result); + } + + @Test + public void getVCITransaction_WhenTransactionExists_ShouldReturnTransaction() { + VCIssuanceTransaction transaction = new VCIssuanceTransaction(); + transaction.setCNonce("test-cnonce"); + when(cache.get(TEST_ACCESS_TOKEN_HASH, VCIssuanceTransaction.class)).thenReturn(transaction); + VCIssuanceTransaction result = vciCacheService.getVCITransaction(TEST_ACCESS_TOKEN_HASH); + assertEquals(transaction, result); + verify(cacheManager).getCache(VCISSUANCE_CACHE); + verify(cache).get(eq(TEST_ACCESS_TOKEN_HASH), eq(VCIssuanceTransaction.class)); + } + +} diff --git a/certify-service/src/test/java/io/mosip/certify/controller/SvgTemplateControllerTest.java b/certify-service/src/test/java/io/mosip/certify/controller/RenderingTemplateControllerTest.java similarity index 60% rename from certify-service/src/test/java/io/mosip/certify/controller/SvgTemplateControllerTest.java rename to certify-service/src/test/java/io/mosip/certify/controller/RenderingTemplateControllerTest.java index 4d2d2480..879e089b 100644 --- a/certify-service/src/test/java/io/mosip/certify/controller/SvgTemplateControllerTest.java +++ b/certify-service/src/test/java/io/mosip/certify/controller/RenderingTemplateControllerTest.java @@ -1,10 +1,10 @@ package io.mosip.certify.controller; +import io.mosip.certify.api.dto.RenderingTemplateDTO; import io.mosip.certify.core.constants.ErrorConstants; import io.mosip.certify.core.dto.ParsedAccessToken; -import io.mosip.certify.core.entity.SvgTemplate; -import io.mosip.certify.core.exception.TemplateException; -import io.mosip.certify.core.spi.SvgTemplateService; +import io.mosip.certify.core.exception.RenderingTemplateException; +import io.mosip.certify.core.spi.RenderingTemplateService; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mockito; @@ -16,29 +16,24 @@ import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; -import java.net.http.HttpHeaders; import java.time.LocalDateTime; -import java.time.ZoneId; -import java.time.format.DateTimeFormatter; -import java.util.UUID; @RunWith(SpringRunner.class) -@WebMvcTest(value=SvgTemplateController.class) -public class SvgTemplateControllerTest { +@WebMvcTest(value= RenderingTemplateController.class) +public class RenderingTemplateControllerTest { @Autowired MockMvc mockMvc; @MockBean - SvgTemplateService svgTemplateService; + RenderingTemplateService renderingTemplateService; @MockBean ParsedAccessToken parsedAccessToken; @Test public void getSvgTemplate_withValidId_thenPass() throws Exception { - SvgTemplate svgTemplate = new SvgTemplate(); - UUID id = UUID.randomUUID(); - svgTemplate.setId(id); + RenderingTemplateDTO renderingTemplateDTO = new RenderingTemplateDTO(); + renderingTemplateDTO.setId("fake-id"); String template = """ @@ -46,27 +41,26 @@ public void getSvgTemplate_withValidId_thenPass() throws Exception { Hello, SVG! """; - svgTemplate.setTemplate(template); + renderingTemplateDTO.setTemplate(template); LocalDateTime date = LocalDateTime.now(); - svgTemplate.setCreatedtimes(date); - svgTemplate.setUpdatedtimes(date); + renderingTemplateDTO.setCreatedTimes(date); + renderingTemplateDTO.setUpdatedTimes(date); - Mockito.when(svgTemplateService.getSvgTemplate(Mockito.any())).thenReturn(svgTemplate); + Mockito.when(renderingTemplateService.getSvgTemplate(Mockito.any())).thenReturn(renderingTemplateDTO); - mockMvc.perform(get("/public/svg-template/" + id)) + mockMvc.perform(get("/rendering-template/fake-id")) .andExpect(status().isOk()) - .andExpect(content().string(svgTemplate.getTemplate())) + .andExpect(content().string(renderingTemplateDTO.getTemplate())) .andExpect(content().contentType("image/svg+xml")) .andExpect(header().string("Cache-Control", "max-age=86400, public")); } @Test public void getSvgTemplate_withInValidId_thenFail() throws Exception { - TemplateException templateException = new TemplateException(ErrorConstants.INVALID_TEMPLATE_ID); - UUID id = UUID.randomUUID(); - Mockito.when(svgTemplateService.getSvgTemplate(id)).thenThrow(templateException); + RenderingTemplateException templateException = new RenderingTemplateException(ErrorConstants.INVALID_TEMPLATE_ID); + Mockito.when(renderingTemplateService.getSvgTemplate("fake-id")).thenThrow(templateException); - mockMvc.perform(get("/public/svg-template/" + id)) + mockMvc.perform(get("/rendering-template/fake-id")) .andExpect(status().isNotFound()); } } diff --git a/certify-service/src/test/java/io/mosip/certify/filter/AccessTokenValidationFilterTest.java b/certify-service/src/test/java/io/mosip/certify/filter/AccessTokenValidationFilterTest.java new file mode 100644 index 00000000..ed0344ce --- /dev/null +++ b/certify-service/src/test/java/io/mosip/certify/filter/AccessTokenValidationFilterTest.java @@ -0,0 +1,185 @@ +package io.mosip.certify.filter; + +import io.mosip.certify.core.constants.Constants; +import io.mosip.certify.core.dto.ParsedAccessToken; +import io.mosip.certify.core.util.CommonUtil; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.mock.web.MockHttpServletResponse; +import org.springframework.security.oauth2.core.OAuth2Error; +import org.springframework.security.oauth2.jwt.*; +import org.springframework.test.util.ReflectionTestUtils; + +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import java.io.IOException; +import java.time.Clock; +import java.time.Instant; +import java.util.*; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.*; +import static org.junit.jupiter.api.Assertions.*; + +class AccessTokenValidationFilterTest { + + @InjectMocks + private AccessTokenValidationFilter filter; + + @Mock + private ParsedAccessToken parsedAccessToken; + + @Mock + private NimbusJwtDecoder jwtDecoder; + + @Mock + private FilterChain filterChain; + + @Mock + private CommonUtil commonUtil; + + private MockHttpServletRequest request; + private MockHttpServletResponse response; + private static final String TOKEN = "header.payload.signature"; + private static final String TEST_ISSUER = "https://test-issuer.com"; + private static final String TEST_JWK_SET = "https://test-issuer.com/.well-known/jwks.json"; + + @BeforeEach + public void setUp() { + MockitoAnnotations.openMocks(this); + request = new MockHttpServletRequest(); + response = new MockHttpServletResponse(); + + ReflectionTestUtils.setField(filter, "issuerUri", TEST_ISSUER); + ReflectionTestUtils.setField(filter, "jwkSetUri", TEST_JWK_SET); + ReflectionTestUtils.setField(filter, "allowedAudiences", Arrays.asList("test-client")); + ReflectionTestUtils.setField(filter, "urlPatterns", Arrays.asList("/api/v1/test", "/api/v1/secured")); + ReflectionTestUtils.setField(filter, "nimbusJwtDecoder", jwtDecoder); + } + + @Test + public void whenNimbusJwtDecoderNull_shouldCreateNewInstance() { + ReflectionTestUtils.setField(filter, "nimbusJwtDecoder", null); + request.addHeader("Authorization", "Bearer " + TOKEN); + + Jwt jwt = mock(Jwt.class); + when(jwt.getClaims()).thenReturn(createValidClaims()); + when(jwtDecoder.decode(anyString())).thenReturn(jwt); + + assertDoesNotThrow(() -> filter.doFilterInternal(request, response, filterChain)); + } + + @ParameterizedTest + @ValueSource(strings = {"/api/v1/test", "/api/v1/secured"}) + public void shouldFilterForConfiguredUrls(String url) throws ServletException { + request.setRequestURI(url); + assertFalse(filter.shouldNotFilter(request)); + } + + @ParameterizedTest + @ValueSource(strings = {"/api/v1/public", "/health", "/random"}) + public void shouldNotFilterForNonConfiguredUrls(String url) throws ServletException { + request.setRequestURI(url); + assertTrue(filter.shouldNotFilter(request)); + } + + @Test + public void whenValidJwtTokenWithAllClaims_shouldProcessSuccessfully() throws ServletException, IOException { + request.addHeader("Authorization", "Bearer " + TOKEN); + + Jwt jwt = mock(Jwt.class); + Map claims = createValidClaims(); + when(jwt.getClaims()).thenReturn(claims); + when(jwtDecoder.decode(TOKEN)).thenReturn(jwt); + + filter.doFilterInternal(request, response, filterChain); + + verify(parsedAccessToken).setClaims(any()); + verify(parsedAccessToken).setActive(true); + verify(parsedAccessToken).setAccessTokenHash(any()); + verify(filterChain).doFilter(request, response); + } + + @Test + public void whenTokenWithMissingClaims_shouldHandleValidationFailure() throws ServletException, IOException { + request.addHeader("Authorization", "Bearer " + TOKEN); + + when(jwtDecoder.decode(TOKEN)).thenThrow( + new JwtValidationException("Missing claims", + Arrays.asList(new OAuth2Error("invalid_token", "Required claim 'sub' is missing", null))) + ); + + filter.doFilterInternal(request, response, filterChain); + + verify(parsedAccessToken).setActive(false); + verify(filterChain).doFilter(request, response); + } + + @Test + public void whenTokenWithExpiredTimestamp_shouldHandleValidationFailure() throws ServletException, IOException { + request.addHeader("Authorization", "Bearer " + TOKEN); + + when(jwtDecoder.decode(TOKEN)).thenThrow( + new JwtValidationException("Token expired", + Arrays.asList(new OAuth2Error("invalid_token", "Jwt expired at...", null))) + ); + + filter.doFilterInternal(request, response, filterChain); + + verify(parsedAccessToken).setActive(false); + verify(filterChain).doFilter(request, response); + } + + @Test + public void whenTokenWithInvalidSignature_shouldHandleValidationFailure() throws ServletException, IOException { + request.addHeader("Authorization", "Bearer " + TOKEN); + + when(jwtDecoder.decode(TOKEN)).thenThrow( + new JwtValidationException("Invalid signature", + Arrays.asList(new OAuth2Error("invalid_token", "Jwt signature invalid", null))) + ); + + filter.doFilterInternal(request, response, filterChain); + + verify(parsedAccessToken).setActive(false); + verify(filterChain).doFilter(request, response); + } + + @Test + public void whenMalformedJwt_shouldHandleException() throws ServletException, IOException { + request.addHeader("Authorization", "Bearer malformed.jwt"); + + when(jwtDecoder.decode(anyString())).thenThrow(new BadJwtException("Malformed JWT")); + + filter.doFilterInternal(request, response, filterChain); + + verify(parsedAccessToken).setActive(false); + verify(filterChain).doFilter(request, response); + } + + @Test + public void whenNullAuthorizationHeader_shouldHandleGracefully() throws ServletException, IOException { + filter.doFilterInternal(request, response, filterChain); + + verify(parsedAccessToken).setActive(false); + verify(filterChain).doFilter(request, response); + } + + private Map createValidClaims() { + Map claims = new HashMap<>(); + claims.put(JwtClaimNames.SUB, "test-subject"); + claims.put(JwtClaimNames.AUD, Arrays.asList("test-client")); + claims.put(Constants.CLIENT_ID, "test-client"); + claims.put(JwtClaimNames.ISS, TEST_ISSUER); + claims.put(JwtClaimNames.IAT, Instant.now().minusSeconds(60)); + claims.put(JwtClaimNames.EXP, Instant.now().plusSeconds(300)); + return claims; + } +} \ No newline at end of file diff --git a/certify-service/src/test/java/io/mosip/certify/proof/JwtProofValidatorTest.java b/certify-service/src/test/java/io/mosip/certify/proof/JwtProofValidatorTest.java index 0dbafbfe..9058161f 100644 --- a/certify-service/src/test/java/io/mosip/certify/proof/JwtProofValidatorTest.java +++ b/certify-service/src/test/java/io/mosip/certify/proof/JwtProofValidatorTest.java @@ -1,18 +1,30 @@ package io.mosip.certify.proof; -import com.nimbusds.jose.JWSAlgorithm; +import com.nimbusds.jose.*; +import com.nimbusds.jose.crypto.ECDSASigner; +import com.nimbusds.jose.crypto.Ed25519Signer; +import com.nimbusds.jose.crypto.RSASSASigner; +import com.nimbusds.jose.jwk.*; +import com.nimbusds.jose.jwk.gen.ECKeyGenerator; +import com.nimbusds.jose.jwk.gen.OctetKeyPairGenerator; +import com.nimbusds.jose.jwk.gen.RSAKeyGenerator; +import com.nimbusds.jwt.JWTClaimsSet; import com.nimbusds.jwt.SignedJWT; -import com.nimbusds.jose.JWSHeader; -import com.nimbusds.jose.jwk.JWK; import io.mosip.certify.core.dto.CredentialProof; +import io.mosip.certify.core.exception.InvalidRequestException; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import java.lang.reflect.Method; +import java.nio.charset.StandardCharsets; +import java.text.ParseException; +import java.util.*; + import org.mockito.Mock; import org.mockito.MockitoAnnotations; +import org.springframework.test.util.ReflectionTestUtils; - +import static org.junit.Assert.*; import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.Mockito.*; class JwtProofValidatorTest { @@ -26,6 +38,8 @@ class JwtProofValidatorTest { void setUp() { MockitoAnnotations.openMocks(this); jwtProofValidator = new JwtProofValidator(); + ReflectionTestUtils.setField(jwtProofValidator, "supportedAlgorithms", List.of("RS256", "ES256K", "Ed25519")); + ReflectionTestUtils.setField(jwtProofValidator, "credentialIdentifier", "test-credential-id"); } @Test @@ -52,4 +66,346 @@ void testValidateWithBlankJwt() { assertFalse(result, "Expected validation to fail for blank JWT"); } + @Test + void getProofType () { + String proofType = jwtProofValidator.getProofType(); + assertNotNull(proofType); + assertEquals("jwt", proofType); + } + + @Test + void testValidate_ValidJWT() throws Exception { + String jwt = createValidJWT(); + CredentialProof credentialProof = new CredentialProof(); + credentialProof.setJwt(jwt); + + boolean result = jwtProofValidator.validate("test-client", "test-nonce", credentialProof); + + assertTrue(result, "JWT should be valid"); + } + + @Test + void testValidate_InvalidJWT() { + CredentialProof credentialProof = new CredentialProof(); + credentialProof.setJwt("invalid.jwt.token"); + + boolean result = jwtProofValidator.validate("test-client", "test-nonce", credentialProof); + + assertFalse(result, "Invalid JWT should fail validation"); + } + + @Test + void testGetKeyMaterial_ValidJWT() throws Exception { + String jwt = createValidJWT(); + CredentialProof credentialProof = new CredentialProof(); + credentialProof.setJwt(jwt); + + String keyMaterial = jwtProofValidator.getKeyMaterial(credentialProof); + assertNotNull(keyMaterial); + assertTrue(keyMaterial.startsWith("did:jwk:"), "Key material should be prefixed with did:jwk"); + } + + @Test + void testGetKeyMaterial_InvalidJWT() { + CredentialProof credentialProof = new CredentialProof(); + credentialProof.setJwt("invalid.jwt.token"); + + assertThrows(InvalidRequestException.class, () -> jwtProofValidator.getKeyMaterial(credentialProof)); + } + + private String createValidJWT() throws Exception { + // Generate a 2048-bit RSA key pair + RSAKey rsaJWK = new RSAKeyGenerator(2048) + .keyID(UUID.randomUUID().toString()) + .generate(); + + // Extract public key for embedding in the JWT header + RSAKey rsaPublicJWK = rsaJWK.toPublicJWK(); + + JWSHeader header = new JWSHeader.Builder(JWSAlgorithm.RS256) + .type(new JOSEObjectType("openid4vci-proof+jwt")) + .jwk(rsaPublicJWK) // Embed the public JWK + .build(); + + // Build JWT claims + SignedJWT jwt = new SignedJWT(header, new com.nimbusds.jwt.JWTClaimsSet.Builder() + .audience("test-credential-id") + .issuer("test-client") + .claim("nonce", "test-nonce") + .issueTime(new Date()) + .expirationTime(new Date(System.currentTimeMillis() + 60000)) // 1 min expiration + .build()); + + // Sign JWT using private key + JWSSigner signer = new RSASSASigner(rsaJWK); + jwt.sign(signer); + + return jwt.serialize(); + } + + @Test + public void testValidate_InvalidJwt_MissingClaims() throws ParseException, JOSEException { + RSAKey rsaJWK = new RSAKeyGenerator(2048) + .keyID(UUID.randomUUID().toString()) + .generate(); + + // Extract public key for embedding in the JWT header + RSAKey rsaPublicJWK = rsaJWK.toPublicJWK(); + + JWSHeader header = new JWSHeader.Builder(JWSAlgorithm.RS256) + .type(new JOSEObjectType("openid4vci-proof+jwt")) + .jwk(rsaPublicJWK) // Embed the public JWK + .build(); + + // Build JWT claims + SignedJWT jwt = new SignedJWT(header, new com.nimbusds.jwt.JWTClaimsSet.Builder() + .audience("test-credential-id") + .issuer("test-client") + .claim("nonce", "test-nonce") + .expirationTime(new Date(System.currentTimeMillis() + 60000)) // 1 min expiration + .build()); + + // Sign JWT using private key + JWSSigner signer = new RSASSASigner(rsaJWK); + jwt.sign(signer); + + String jwtStr = jwt.serialize(); + CredentialProof credentialProof = new CredentialProof(); + credentialProof.setJwt(jwtStr); + + boolean result = jwtProofValidator.validate("test-client", "test-nonce", credentialProof); + + assertFalse(result, "Missing iat from jwt claims"); + } + + @Test + public void testValidate_Es256_InvalidAlgException() throws ParseException, JOSEException { + // Generate a valid ECKey with ES256 + ECKey ecJWK = new ECKeyGenerator(Curve.P_256) + .keyUse(KeyUse.SIGNATURE) + .keyID(UUID.randomUUID().toString()) + .generate(); + + // Create a public JWK from the private JWK + JWK publicJwk = ecJWK.toPublicJWK(); + + // Create JWS Header with public JWK + JWSHeader header = new JWSHeader.Builder(JWSAlgorithm.ES256) + .jwk(publicJwk) + .type(new JOSEObjectType("openid4vci-proof+jwt")) + .build(); + + // Build JWT Claims + JWTClaimsSet claims = new JWTClaimsSet.Builder() + .audience("test-credential-id") + .issuer("clientId") + .claim("nonce", "someNonce") + .issueTime(new Date()) + .expirationTime(new Date(System.currentTimeMillis() + 3600000)) // 1 hour from now + .build(); + + // Create and sign the JWT with the private EC key + SignedJWT signedJWT = new SignedJWT(header, claims); + JWSSigner signer = new ECDSASigner(ecJWK); + signedJWT.sign(signer); + + // Serialize JWT + String jwt = signedJWT.serialize(); + + // Prepare CredentialProof object + CredentialProof credentialProof = new CredentialProof(); + credentialProof.setJwt(jwt); + + // Validate JWT + boolean result = jwtProofValidator.validate("clientId", "someNonce", credentialProof); + + assertFalse(result, "No algorithm found exception"); + } + + @Test + void testValidate_Es256WithNullHeaderType_InvalidAlgException() throws ParseException, JOSEException { + // Generate a valid ECKey with ES256 + ECKey ecJWK = new ECKeyGenerator(Curve.P_256) + .keyUse(KeyUse.SIGNATURE) + .keyID(UUID.randomUUID().toString()) + .generate(); + + // Create a public JWK from the private JWK + JWK publicJwk = ecJWK.toPublicJWK(); + + // Create JWS Header with public JWK + JWSHeader header = new JWSHeader.Builder(JWSAlgorithm.ES256) + .jwk(publicJwk) + .type(null) + .build(); + + // Build JWT Claims + JWTClaimsSet claims = new JWTClaimsSet.Builder() + .audience("test-credential-id") + .issuer("clientId") + .claim("nonce", "someNonce") + .issueTime(new Date()) + .expirationTime(new Date(System.currentTimeMillis() + 3600000)) // 1 hour from now + .build(); + + // Create and sign the JWT with the private EC key + SignedJWT signedJWT = new SignedJWT(header, claims); + JWSSigner signer = new ECDSASigner(ecJWK); + signedJWT.sign(signer); + + // Serialize JWT + String jwt = signedJWT.serialize(); + + // Prepare CredentialProof object + CredentialProof credentialProof = new CredentialProof(); + credentialProof.setJwt(jwt); + + // Validate JWT + boolean result = jwtProofValidator.validate("clientId", "someNonce", credentialProof); + + assertFalse(result, "No algorithm found exception"); + } + + @Test + void testValidate_Es256WithInvalidKeyId_InvalidAlgException() throws ParseException, JOSEException { + ReflectionTestUtils.setField(jwtProofValidator, "supportedAlgorithms", List.of("RS256", "ES256", "Ed25519")); + // Generate a valid ECKey with ES256 + ECKey ecJWK = new ECKeyGenerator(Curve.P_256) + .keyUse(KeyUse.SIGNATURE) + .keyID(UUID.randomUUID().toString()) + .generate(); + + // Create JWS Header with public JWK + JWSHeader header = new JWSHeader.Builder(JWSAlgorithm.ES256) + .jwk(null) + .keyID(null) + .type(new JOSEObjectType("openid4vci-proof+jwt")) + .build(); + + // Build JWT Claims + JWTClaimsSet claims = new JWTClaimsSet.Builder() + .audience("test-credential-id") + .issuer("clientId") + .claim("nonce", "someNonce") + .issueTime(new Date()) + .expirationTime(new Date(System.currentTimeMillis() + 3600000)) // 1 hour from now + .build(); + + // Create and sign the JWT with the private EC key + SignedJWT signedJWT = new SignedJWT(header, claims); + JWSSigner signer = new ECDSASigner(ecJWK); + signedJWT.sign(signer); + + // Serialize JWT + String jwt = signedJWT.serialize(); + + // Prepare CredentialProof object + CredentialProof credentialProof = new CredentialProof(); + credentialProof.setJwt(jwt); + + // Validate JWT + boolean result = jwtProofValidator.validate("clientId", "someNonce", credentialProof); + + assertFalse(result, "No algorithm found exception"); + } + + @Test + void testValidate_Es256WithNonNullHeaderJwkAndKeyId_InvalidAlgException() throws ParseException, JOSEException { + ReflectionTestUtils.setField(jwtProofValidator, "supportedAlgorithms", List.of("RS256", "ES256", "Ed25519")); + // Generate a valid ECKey with ES256 + ECKey ecJWK = new ECKeyGenerator(Curve.P_256) + .keyUse(KeyUse.SIGNATURE) + .keyID(UUID.randomUUID().toString()) + .generate(); + + // Create a public JWK from the private JWK + JWK publicJwk = ecJWK.toPublicJWK(); + + // Create JWS Header with public JWK + JWSHeader header = new JWSHeader.Builder(JWSAlgorithm.ES256) + .jwk(publicJwk) + .keyID(UUID.randomUUID().toString()) + .type(new JOSEObjectType("openid4vci-proof+jwt")) + .build(); + + // Build JWT Claims + JWTClaimsSet claims = new JWTClaimsSet.Builder() + .audience("test-credential-id") + .issuer("clientId") + .claim("nonce", "someNonce") + .issueTime(new Date()) + .expirationTime(new Date(System.currentTimeMillis() + 3600000)) // 1 hour from now + .build(); + + // Create and sign the JWT with the private EC key + SignedJWT signedJWT = new SignedJWT(header, claims); + JWSSigner signer = new ECDSASigner(ecJWK); + signedJWT.sign(signer); + + // Serialize JWT + String jwt = signedJWT.serialize(); + + // Prepare CredentialProof object + CredentialProof credentialProof = new CredentialProof(); + credentialProof.setJwt(jwt); + + // Validate JWT + boolean result = jwtProofValidator.validate("clientId", "someNonce", credentialProof); + + assertFalse(result, "No algorithm found exception"); + } + + @Test + void testValidate_ValidEd25519JWT() throws Exception { + String keyId = "did:jwk:"; + String jwt = createValidEd25519JWT(keyId); + + CredentialProof credentialProof = new CredentialProof(); + credentialProof.setJwt(jwt); + + boolean result = jwtProofValidator.validate("test-client", "test-nonce", credentialProof); + + assertTrue(result, "Ed25519 JWT should be valid"); + } + + private String createValidEd25519JWT(String keyId) throws Exception { + // Generate Ed25519 key pair + OctetKeyPair edJWK = new OctetKeyPairGenerator(Curve.Ed25519) + .keyID(UUID.randomUUID().toString()) // Use unique key ID + .generate(); + + // Create JWT header with Ed25519 algorithm and JWK + JWSHeader header = new JWSHeader.Builder(JWSAlgorithm.Ed25519) + .type(new JOSEObjectType("openid4vci-proof+jwt")) + .keyID(keyId + Base64.getUrlEncoder().withoutPadding().encodeToString(edJWK.toPublicJWK().toJSONString().getBytes(StandardCharsets.UTF_8))) + .build(); + + // Create JWT claims + JWTClaimsSet claims = new JWTClaimsSet.Builder() + .audience("test-credential-id") + .issuer("test-client") + .claim("nonce", "test-nonce") + .issueTime(new Date()) + .expirationTime(new Date(System.currentTimeMillis() + 60000)) + .build(); + + // Sign JWT with Ed25519 + SignedJWT jwt = new SignedJWT(header, claims); + JWSSigner signer = new Ed25519Signer(edJWK); + jwt.sign(signer); + + return jwt.serialize(); + } + + @Test + void testValidate_Ed25519JWT_IllegalArgumentException() throws Exception { + String signedJwt = createValidEd25519JWT("did:jwk: "); + + CredentialProof credentialProof = new CredentialProof(); + credentialProof.setJwt(signedJwt); + + boolean result = jwtProofValidator.validate("test-client", "test-nonce", credentialProof); + + assertFalse(result, "Invalid base64 encoded ID"); + } } diff --git a/certify-service/src/test/java/io/mosip/certify/proof/ProofValidatorFactoryTest.java b/certify-service/src/test/java/io/mosip/certify/proof/ProofValidatorFactoryTest.java new file mode 100644 index 00000000..4bece7d1 --- /dev/null +++ b/certify-service/src/test/java/io/mosip/certify/proof/ProofValidatorFactoryTest.java @@ -0,0 +1,66 @@ +package io.mosip.certify.proof; + +import io.mosip.certify.core.constants.ErrorConstants; +import io.mosip.certify.core.exception.CertifyException; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.springframework.test.util.ReflectionTestUtils; + +import java.util.Arrays; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +class ProofValidatorFactoryTest { + + @InjectMocks + private ProofValidatorFactory proofValidatorFactory; + + @Mock + private ProofValidator jwtProofValidator; + + @Mock + private ProofValidator anotherProofValidator; + + @BeforeEach + void setUp() { + MockitoAnnotations.openMocks(this); + proofValidatorFactory = new ProofValidatorFactory(); + ReflectionTestUtils.setField(proofValidatorFactory, "proofValidators", Arrays.asList(jwtProofValidator, anotherProofValidator)); + } + + @Test + void testGetProofValidator_ValidProofType() { + // Arrange + String validProofType = "jwt"; // Assuming "jwt" is a valid proof type + when(jwtProofValidator.getProofType()).thenReturn("jwt"); + when(anotherProofValidator.getProofType()).thenReturn("another-proof"); + + // Act + ProofValidator result = proofValidatorFactory.getProofValidator(validProofType); + + // Assert + assertNotNull(result, "The proof validator should not be null."); + assertEquals(jwtProofValidator, result, "The correct proof validator should be returned."); + } + + @Test + void testGetProofValidator_InvalidProofType() { + // Arrange + String invalidProofType = "invalid-proof"; // Invalid proof type + when(jwtProofValidator.getProofType()).thenReturn("jwt"); + when(anotherProofValidator.getProofType()).thenReturn("another-proof"); + + // Act and Assert + CertifyException thrown = assertThrows(CertifyException.class, () -> + proofValidatorFactory.getProofValidator(invalidProofType), + "Expected CertifyException to be thrown for invalid proof type." + ); + + assertEquals(ErrorConstants.UNSUPPORTED_PROOF_TYPE, thrown.getErrorCode(), + "The error code should be the correct unsupported proof type error."); + } +} diff --git a/certify-service/src/test/java/io/mosip/certify/proofgenerators/Ed25519Signature2018ProofGeneratorTest.java b/certify-service/src/test/java/io/mosip/certify/proofgenerators/Ed25519Signature2018ProofGeneratorTest.java new file mode 100644 index 00000000..b4198c0f --- /dev/null +++ b/certify-service/src/test/java/io/mosip/certify/proofgenerators/Ed25519Signature2018ProofGeneratorTest.java @@ -0,0 +1,108 @@ +package io.mosip.certify.proofgenerators; + +import info.weboftrust.ldsignatures.LdProof; +import info.weboftrust.ldsignatures.canonicalizer.Canonicalizer; +import info.weboftrust.ldsignatures.canonicalizer.URDNA2015Canonicalizer; +import io.mosip.certify.core.constants.Constants; +import io.mosip.certify.core.constants.SignatureAlg; +import io.mosip.kernel.signature.dto.JWSSignatureRequestDto; +import io.mosip.kernel.signature.dto.JWTSignatureResponseDto; +import io.mosip.kernel.signature.exception.RequestException; +import io.mosip.kernel.signature.service.SignatureService; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; + +import java.util.HashMap; +import java.util.Map; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +@ConditionalOnProperty(name = "mosip.certify.data-provider-plugin.issuer.vc-sign-algo", havingValue = SignatureAlg.ED25519_SIGNATURE_SUITE_2018) +class Ed25519Signature2018ProofGeneratorTest { + + @InjectMocks + private Ed25519Signature2018ProofGenerator proofGenerator; + + @Mock + private SignatureService signatureService; + + private Map keyID; + + @BeforeEach + void setUp() { + MockitoAnnotations.openMocks(this); + keyID = new HashMap<>(); + keyID.put(Constants.APPLICATION_ID, "app123"); + keyID.put(Constants.REFERENCE_ID, "ref456"); + } + + @Test + void testGetName() { + assertEquals("Ed25519Signature2018", proofGenerator.getName()); + } + + @Test + void testGetCanonicalizer() { + Canonicalizer canonicalizer = proofGenerator.getCanonicalizer(); + assertNotNull(canonicalizer); + assertTrue(canonicalizer instanceof URDNA2015Canonicalizer); + } + + @Test + void testGenerateProofSuccess() { + LdProof baseProof = new LdProof(); + String vcEncodedHash = "mockEncodedHash"; + JWTSignatureResponseDto responseDto = new JWTSignatureResponseDto(); + responseDto.setJwtSignedData("mockJwsData"); + + when(signatureService.jwsSign(any(JWSSignatureRequestDto.class))).thenReturn(responseDto); + + LdProof result = proofGenerator.generateProof(baseProof, vcEncodedHash, keyID); + + assertNotNull(result); + assertEquals("mockJwsData", result.getJws()); + verify(signatureService).jwsSign(any(JWSSignatureRequestDto.class)); + } + + @Test + void testGenerateProof_NullProof() { + JWTSignatureResponseDto responseDto = new JWTSignatureResponseDto(); + responseDto.setJwtSignedData("mockJwsData"); + when(signatureService.jwsSign(any(JWSSignatureRequestDto.class))).thenReturn(responseDto); + + LdProof result = proofGenerator.generateProof(null, "mockEncodedHash", keyID); + + assertNotNull(result); + assertEquals("mockJwsData", result.getJws()); + } + + @Test + void testGenerateProof_EmptyKeyID() { + JWTSignatureResponseDto responseDto = new JWTSignatureResponseDto(); + responseDto.setJwtSignedData("mockJwsData"); + when(signatureService.jwsSign(any(JWSSignatureRequestDto.class))).thenReturn(responseDto); + + Map emptyKeyID = new HashMap<>(); + LdProof result = proofGenerator.generateProof(new LdProof(), "mockEncodedHash", emptyKeyID); + + assertNotNull(result); + assertEquals("mockJwsData", result.getJws()); + } + + @Test + void testGenerateProofSignature_ServiceFailure() { + when(signatureService.jwsSign(any(JWSSignatureRequestDto.class))).thenThrow(new RequestException("SIGNATURE_TEST_ERROR","Signature Failed")); + + RequestException exception = assertThrows(RequestException.class, () -> { + proofGenerator.generateProof(new LdProof(), "mockEncodedHash", keyID); + }); + + assertEquals("SIGNATURE_TEST_ERROR", exception.getErrorCode()); + assertEquals("SIGNATURE_TEST_ERROR --> Signature Failed", exception.getMessage()); + } +} diff --git a/certify-service/src/test/java/io/mosip/certify/proofgenerators/Ed25519Signature2020ProofGeneratorTest.java b/certify-service/src/test/java/io/mosip/certify/proofgenerators/Ed25519Signature2020ProofGeneratorTest.java new file mode 100644 index 00000000..5ea71e84 --- /dev/null +++ b/certify-service/src/test/java/io/mosip/certify/proofgenerators/Ed25519Signature2020ProofGeneratorTest.java @@ -0,0 +1,108 @@ +package io.mosip.certify.proofgenerators; + +import info.weboftrust.ldsignatures.LdProof; +import info.weboftrust.ldsignatures.canonicalizer.Canonicalizer; +import info.weboftrust.ldsignatures.canonicalizer.URDNA2015Canonicalizer; +import io.mosip.certify.core.constants.Constants; +import io.mosip.certify.core.constants.SignatureAlg; +import io.mosip.kernel.signature.dto.SignRequestDtoV2; +import io.mosip.kernel.signature.dto.SignResponseDto; +import io.mosip.kernel.signature.exception.RequestException; +import io.mosip.kernel.signature.service.SignatureServicev2; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; + +import java.util.HashMap; +import java.util.Map; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +@ConditionalOnProperty(name = "mosip.certify.data-provider-plugin.issuer.vc-sign-algo", havingValue = SignatureAlg.ED25519_SIGNATURE_SUITE_2020) +class Ed25519Signature2020ProofGeneratorTest { + + @InjectMocks + private Ed25519Signature2020ProofGenerator proofGenerator; + + @Mock + private SignatureServicev2 signatureService; + + private Map keyID; + + @BeforeEach + void setUp() { + MockitoAnnotations.openMocks(this); + keyID = new HashMap<>(); + keyID.put(Constants.APPLICATION_ID, "app123"); + keyID.put(Constants.REFERENCE_ID, "ref456"); + } + + @Test + void testGetName() { + assertEquals("Ed25519Signature2020", proofGenerator.getName()); + } + + @Test + void testGetCanonicalizer() { + Canonicalizer canonicalizer = proofGenerator.getCanonicalizer(); + assertNotNull(canonicalizer); + assertTrue(canonicalizer instanceof URDNA2015Canonicalizer); + } + + @Test + void testGenerateProofSuccess() { + LdProof baseProof = new LdProof(); + String vcEncodedHash = "mockEncodedHash"; + SignResponseDto responseDto = new SignResponseDto(); + responseDto.setSignature("mockSignatureValue"); + + when(signatureService.signv2(any(SignRequestDtoV2.class))).thenReturn(responseDto); + + LdProof result = proofGenerator.generateProof(baseProof, vcEncodedHash, keyID); + + assertNotNull(result); + assertEquals("mockSignatureValue", result.getProofValue()); + verify(signatureService).signv2(any(SignRequestDtoV2.class)); + } + + @Test + void testGenerateProof_NullProof() { + SignResponseDto responseDto = new SignResponseDto(); + responseDto.setSignature("mockSignatureValue"); + when(signatureService.signv2(any(SignRequestDtoV2.class))).thenReturn(responseDto); + + LdProof result = proofGenerator.generateProof(null, "mockEncodedHash", keyID); + + assertNotNull(result); + assertEquals("mockSignatureValue", result.getProofValue()); + } + + @Test + void testGenerateProof_EmptyKeyID() { + SignResponseDto responseDto = new SignResponseDto(); + responseDto.setSignature("mockSignatureValue"); + when(signatureService.signv2(any(SignRequestDtoV2.class))).thenReturn(responseDto); + + Map emptyKeyID = new HashMap<>(); + LdProof result = proofGenerator.generateProof(new LdProof(), "mockEncodedHash", emptyKeyID); + + assertNotNull(result); + assertEquals("mockSignatureValue", result.getProofValue()); + } + + @Test + void testGenerateProofSignature_ServiceFailure() { + when(signatureService.signv2(any(SignRequestDtoV2.class))).thenThrow(new RequestException("SIGNATURE_TEST_ERROR","Signature Failed")); + + RequestException exception = assertThrows(RequestException.class, () -> { + proofGenerator.generateProof(new LdProof(), "mockEncodedHash", keyID); + }); + + assertEquals("SIGNATURE_TEST_ERROR", exception.getErrorCode()); + assertEquals("SIGNATURE_TEST_ERROR --> Signature Failed", exception.getMessage()); + } +} \ No newline at end of file diff --git a/certify-service/src/test/java/io/mosip/certify/proofgenerators/RSASignature2018ProofGeneratorTest.java b/certify-service/src/test/java/io/mosip/certify/proofgenerators/RSASignature2018ProofGeneratorTest.java new file mode 100644 index 00000000..d89fb89e --- /dev/null +++ b/certify-service/src/test/java/io/mosip/certify/proofgenerators/RSASignature2018ProofGeneratorTest.java @@ -0,0 +1,108 @@ +package io.mosip.certify.proofgenerators; + +import info.weboftrust.ldsignatures.LdProof; +import info.weboftrust.ldsignatures.canonicalizer.Canonicalizer; +import info.weboftrust.ldsignatures.canonicalizer.URDNA2015Canonicalizer; +import io.mosip.certify.core.constants.Constants; +import io.mosip.certify.core.constants.SignatureAlg; +import io.mosip.kernel.signature.dto.JWSSignatureRequestDto; +import io.mosip.kernel.signature.dto.JWTSignatureResponseDto; +import io.mosip.kernel.signature.exception.RequestException; +import io.mosip.kernel.signature.service.SignatureService; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; + +import java.util.HashMap; +import java.util.Map; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +@ConditionalOnProperty(name = "mosip.certify.data-provider-plugin.issuer.vc-sign-algo", havingValue = SignatureAlg.RSA_SIGNATURE_SUITE_2018) +class RSASignature2018ProofGeneratorTest { + + @InjectMocks + private RSASignature2018ProofGenerator proofGenerator; + + @Mock + private SignatureService signatureService; + + private Map keyID; + + @BeforeEach + void setUp() { + MockitoAnnotations.openMocks(this); + keyID = new HashMap<>(); + keyID.put(Constants.APPLICATION_ID, "app123"); + keyID.put(Constants.REFERENCE_ID, "ref456"); + } + + @Test + void testGetName() { + assertEquals("RsaSignature2018", proofGenerator.getName()); + } + + @Test + void testGetCanonicalizer() { + Canonicalizer canonicalizer = proofGenerator.getCanonicalizer(); + assertNotNull(canonicalizer); + assertTrue(canonicalizer instanceof URDNA2015Canonicalizer); + } + + @Test + void testGenerateProofSuccess() { + LdProof baseProof = new LdProof(); + String vcEncodedHash = "mockEncodedHash"; + JWTSignatureResponseDto responseDto = new JWTSignatureResponseDto(); + responseDto.setJwtSignedData("mockJwsData"); + + when(signatureService.jwsSign(any(JWSSignatureRequestDto.class))).thenReturn(responseDto); + + LdProof result = proofGenerator.generateProof(baseProof, vcEncodedHash, keyID); + + assertNotNull(result); + assertEquals("mockJwsData", result.getJws()); + verify(signatureService).jwsSign(any(JWSSignatureRequestDto.class)); + } + + @Test + void testGenerateProof_NullProof() { + JWTSignatureResponseDto responseDto = new JWTSignatureResponseDto(); + responseDto.setJwtSignedData("mockJwsData"); + when(signatureService.jwsSign(any(JWSSignatureRequestDto.class))).thenReturn(responseDto); + + LdProof result = proofGenerator.generateProof(null, "mockEncodedHash", keyID); + + assertNotNull(result); + assertEquals("mockJwsData", result.getJws()); + } + + @Test + void testGenerateProof_EmptyKeyID() { + JWTSignatureResponseDto responseDto = new JWTSignatureResponseDto(); + responseDto.setJwtSignedData("mockJwsData"); + when(signatureService.jwsSign(any(JWSSignatureRequestDto.class))).thenReturn(responseDto); + + Map emptyKeyID = new HashMap<>(); + LdProof result = proofGenerator.generateProof(new LdProof(), "mockEncodedHash", emptyKeyID); + + assertNotNull(result); + assertEquals("mockJwsData", result.getJws()); + } + + @Test + void testGenerateProofSignature_ServiceFailure() { + when(signatureService.jwsSign(any(JWSSignatureRequestDto.class))).thenThrow(new RequestException("SIGNATURE_TEST_ERROR","Signature Failed")); + + RequestException exception = assertThrows(RequestException.class, () -> { + proofGenerator.generateProof(new LdProof(), "mockEncodedHash", keyID); + }); + + assertEquals("SIGNATURE_TEST_ERROR", exception.getErrorCode()); + assertEquals("SIGNATURE_TEST_ERROR --> Signature Failed", exception.getMessage()); + } +} diff --git a/certify-service/src/test/java/io/mosip/certify/repository/SvgRenderTemplateRepositoryTest.java b/certify-service/src/test/java/io/mosip/certify/repository/RenderingCredentialTemplateRepositoryTest.java similarity index 60% rename from certify-service/src/test/java/io/mosip/certify/repository/SvgRenderTemplateRepositoryTest.java rename to certify-service/src/test/java/io/mosip/certify/repository/RenderingCredentialTemplateRepositoryTest.java index ea8cbf32..fc141611 100644 --- a/certify-service/src/test/java/io/mosip/certify/repository/SvgRenderTemplateRepositoryTest.java +++ b/certify-service/src/test/java/io/mosip/certify/repository/RenderingCredentialTemplateRepositoryTest.java @@ -1,9 +1,9 @@ package io.mosip.certify.repository; -import io.mosip.certify.core.entity.SvgTemplate; -import io.mosip.certify.core.repository.SvgTemplateRepository; +import io.mosip.certify.entity.RenderingTemplate; import jakarta.validation.ConstraintViolationException; import org.junit.Assert; +import org.junit.Before; import org.junit.Test; import org.junit.jupiter.api.Assertions; import org.junit.runner.RunWith; @@ -13,17 +13,23 @@ import java.time.LocalDateTime; import java.util.Optional; -import java.util.UUID; @RunWith(SpringRunner.class) @DataJpaTest -public class SvgRenderTemplateRepositoryTest { +public class RenderingCredentialTemplateRepositoryTest { @Autowired - private SvgTemplateRepository svgRenderTemplateRepository; + private RenderingTemplateRepository svgRenderTemplateRepository; + + LocalDateTime localDateTime; + + @Before + public void setup() { + localDateTime = LocalDateTime.now(); + } @Test public void insertSvgTemplate_withValidDetail_thenPass() { - SvgTemplate svgRenderTemplate = new SvgTemplate(); + RenderingTemplate svgRenderTemplate = new RenderingTemplate(); String template = """ @@ -31,25 +37,30 @@ public void insertSvgTemplate_withValidDetail_thenPass() { Hello, SVG! """; - UUID id = UUID.randomUUID(); - svgRenderTemplate.setId(id); + svgRenderTemplate.setId("fake-id"); svgRenderTemplate.setTemplate(template); - svgRenderTemplate.setCreatedtimes(LocalDateTime.now()); + svgRenderTemplate.setCreatedtimes(localDateTime); + svgRenderTemplate.setUpdatedtimes(localDateTime); svgRenderTemplate = svgRenderTemplateRepository.saveAndFlush(svgRenderTemplate); Assert.assertNotNull(svgRenderTemplate); - Optional optional = svgRenderTemplateRepository.findById(svgRenderTemplate.getId()); + Optional optional = svgRenderTemplateRepository.findById(svgRenderTemplate.getId()); + Assert.assertTrue(svgRenderTemplate.equals(optional.get())); + Assert.assertTrue(svgRenderTemplate.toString().equals(optional.get().toString())); + Assert.assertEquals(optional.get().hashCode(), svgRenderTemplate.hashCode()); Assert.assertTrue(optional.isPresent()); Assert.assertEquals(svgRenderTemplate.getTemplate(), optional.get().getTemplate()); } @Test public void insertSvgTemplate_withEmptyTemplate_thenFail() { - SvgTemplate svgRenderTemplate = new SvgTemplate(); - svgRenderTemplate.setId(UUID.randomUUID()); + RenderingTemplate svgRenderTemplate = new RenderingTemplate(); + svgRenderTemplate.setId("fake-id"); svgRenderTemplate.setTemplate(""); - svgRenderTemplate.setCreatedtimes(LocalDateTime.now()); + localDateTime = LocalDateTime.now(); + svgRenderTemplate.setCreatedtimes(localDateTime); + svgRenderTemplate.setUpdatedtimes(localDateTime); ConstraintViolationException e = Assertions.assertThrows( ConstraintViolationException.class, () -> svgRenderTemplateRepository.saveAndFlush(svgRenderTemplate) diff --git a/certify-service/src/test/java/io/mosip/certify/services/CertifyIssuanceServiceImplTest.java b/certify-service/src/test/java/io/mosip/certify/services/CertifyIssuanceServiceImplTest.java index 1098a060..ac292424 100644 --- a/certify-service/src/test/java/io/mosip/certify/services/CertifyIssuanceServiceImplTest.java +++ b/certify-service/src/test/java/io/mosip/certify/services/CertifyIssuanceServiceImplTest.java @@ -1,33 +1,45 @@ package io.mosip.certify.services; +import foundation.identity.jsonld.JsonLDObject; +import io.mosip.certify.api.dto.VCResult; +import io.mosip.certify.api.exception.DataProviderExchangeException; +import io.mosip.certify.api.exception.VCIExchangeException; import io.mosip.certify.api.spi.AuditPlugin; import io.mosip.certify.api.spi.DataProviderPlugin; -import io.mosip.certify.api.spi.VCFormatter; -import io.mosip.certify.api.spi.VCSigner; +import io.mosip.certify.core.dto.*; +import io.mosip.certify.core.exception.CertifyException; +import io.mosip.certify.exception.InvalidNonceException; +import io.mosip.certify.proof.ProofValidator; +import io.mosip.certify.vcformatters.VCFormatter; import io.mosip.certify.core.constants.ErrorConstants; import io.mosip.certify.core.constants.VCFormats; -import io.mosip.certify.core.dto.CredentialDefinition; -import io.mosip.certify.core.dto.CredentialRequest; -import io.mosip.certify.core.dto.ParsedAccessToken; import io.mosip.certify.core.exception.InvalidRequestException; import io.mosip.certify.core.exception.NotAuthenticatedException; import io.mosip.certify.core.util.SecurityHelperService; import io.mosip.certify.proof.ProofValidatorFactory; +import io.mosip.certify.vcsigners.VCSigner; +import org.json.JSONObject; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.InjectMocks; import org.mockito.Mock; -import org.mockito.Mockito; import org.mockito.MockitoAnnotations; import org.mockito.junit.MockitoJUnitRunner; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.test.util.ReflectionTestUtils; -import java.util.LinkedHashMap; -import java.util.Map; +import java.time.LocalDateTime; +import java.time.ZoneOffset; +import java.util.*; import static org.junit.Assert.*; +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; @RunWith(MockitoJUnitRunner.class) +@ConditionalOnProperty(value = "mosip.certify.plugin-mode", havingValue = "DataProvider") public class CertifyIssuanceServiceImplTest { @Mock @@ -57,25 +69,215 @@ public class CertifyIssuanceServiceImplTest { @Mock private AuditPlugin auditWrapper; + @Mock + private ProofValidator proofValidator; + @InjectMocks private CertifyIssuanceServiceImpl issuanceService; + private static final String TEST_ACCESS_TOKEN_HASH = "test-token-hash"; + private static final String TEST_CNONCE = "test-cnonce"; + + CredentialRequest request; + VCResult vcResult; + Map claims; + VCIssuanceTransaction transaction; + @Before public void setUp() { MockitoAnnotations.initMocks(this); + + issuerMetadata = new LinkedHashMap<>(); + LinkedHashMap latestMetadata = new LinkedHashMap<>(); + LinkedHashMap credentialConfig = new LinkedHashMap<>(); + LinkedHashMap vcConfig = new LinkedHashMap<>(); + vcConfig.put("format", "ldp_vc"); + vcConfig.put("scope", "test-scope"); + vcConfig.put("credential_signing_alg_values_supported", List.of("Ed25519Signature2020")); + Map proofTypes = Map.of("jwt", Map.of("proof_signing_alg_values_supported", List.of("RS256", "PS256"))); + vcConfig.put("proof_types_supported", proofTypes); + List> displayList = List.of(Map.of("name", "test-cred", "background_image", "https://background-image.png")); + vcConfig.put("display", displayList); + LinkedHashMap credDef = new LinkedHashMap<>(); + credDef.put("type", Arrays.asList("VerifiableCredential", "TestCredential")); + vcConfig.put("credential_definition", credDef); + credentialConfig.put("test-credential", vcConfig); + latestMetadata.put("credential_configurations_supported", credentialConfig); + latestMetadata.put("credential_issuer", "https://localhost:9090"); + latestMetadata.put("credential_endpoint", "https://localhost:9090/v1/certify/issuance/credential"); + issuerMetadata.put("latest", latestMetadata); + + ReflectionTestUtils.setField(issuanceService, "issuerMetadata", issuerMetadata); + ReflectionTestUtils.setField(issuanceService, "vcSignAlgorithm", "Ed25519Signature2020"); + ReflectionTestUtils.setField(issuanceService, "cNonceExpireSeconds", 300); + ReflectionTestUtils.setField(issuanceService, "issuerURI", "https://test.issuer.com"); + + when(parsedAccessToken.getAccessTokenHash()).thenReturn(TEST_ACCESS_TOKEN_HASH); + + request = createValidCredentialRequest(); + claims = new HashMap<>(); + claims.put("scope", "test-scope"); + claims.put("client_id", "test-client"); + request.setClaims(claims); + CredentialDefinition credentialDefinition = new CredentialDefinition(); + credentialDefinition.setContext(List.of("https://example.com")); + credentialDefinition.setType(List.of("VerifiableCredential", "TestCredential")); + request.setCredential_definition(credentialDefinition); + transaction = new VCIssuanceTransaction(); + transaction.setCNonce(TEST_CNONCE); + transaction.setCNonceExpireSeconds(300); + transaction.setCNonceIssuedEpoch(LocalDateTime.now(ZoneOffset.UTC).toEpochSecond(ZoneOffset.UTC)); + vcResult = new VCResult<>(); + JsonLDObject jsonLDObject = new JsonLDObject(); // Create an actual JsonLDObject + vcResult.setCredential(jsonLDObject); + + } + + @Test + public void getCredential_WithValidTransaction_Success() throws DataProviderExchangeException { + when(parsedAccessToken.isActive()).thenReturn(true); + when(parsedAccessToken.getClaims()).thenReturn(claims); + when(vciCacheService.getVCITransaction(TEST_ACCESS_TOKEN_HASH)).thenReturn(transaction); + when(proofValidatorFactory.getProofValidator(any())).thenReturn(proofValidator); + when(proofValidator.validate(any(), eq(TEST_CNONCE), any())).thenReturn(true); + when(dataProviderPlugin.fetchData(any())).thenReturn(new JSONObject()); + when(vcFormatter.format(any(), any())).thenReturn("unsigned-vc"); + when(vcSigner.attachSignature(any(String.class), any(Map.class))).thenReturn(vcResult); + + // Act + CredentialResponse response = issuanceService.getCredential(request); + + // Assert + assertNotNull(response); + verify(auditWrapper).logAudit(any(), any(), any(), any()); } + + @Test + public void getCredential_ValidRequest_NullJSONLD_Fail() throws DataProviderExchangeException { + when(parsedAccessToken.isActive()).thenReturn(true); + when(parsedAccessToken.getClaims()).thenReturn(claims); + when(vciCacheService.getVCITransaction(TEST_ACCESS_TOKEN_HASH)).thenReturn(transaction); + when(proofValidatorFactory.getProofValidator(any())).thenReturn(proofValidator); + when(proofValidator.validate(any(), any(), any())).thenReturn(true); + when(dataProviderPlugin.fetchData(any())).thenReturn(new JSONObject()); + when(vcFormatter.format(any(), any())).thenReturn("unsigned-vc"); + when(vcSigner.attachSignature(anyString(), anyMap())).thenReturn(new VCResult<>()); + + assertThrows(ErrorConstants.VC_ISSUANCE_FAILED, CertifyException.class, () -> issuanceService.getCredential(request)); + } + + @Test + public void getCredential_ValidRequest_DataProviderException_Fail() throws DataProviderExchangeException { + when(parsedAccessToken.isActive()).thenReturn(true); + when(parsedAccessToken.getClaims()).thenReturn(claims); + when(vciCacheService.getVCITransaction(TEST_ACCESS_TOKEN_HASH)).thenReturn(transaction); + when(proofValidatorFactory.getProofValidator(any())).thenReturn(proofValidator); + when(proofValidator.validate(any(), any(), any())).thenReturn(true); + + DataProviderExchangeException e = new DataProviderExchangeException("Failed to fetch data"); + when(dataProviderPlugin.fetchData(any())).thenThrow(e); + assertThrows(CertifyException.class, () -> issuanceService.getCredential(request)); + } + + @Test + public void getCredential_ExpiredNonce_ThrowsInvalidNonceException() { + VCIssuanceTransaction newTransaction = new VCIssuanceTransaction(); + newTransaction.setCNonce("new-cnonce"); + newTransaction.setCNonceExpireSeconds(300); + newTransaction.setCNonceIssuedEpoch(0L); + + when(parsedAccessToken.isActive()).thenReturn(true); + when(parsedAccessToken.getClaims()).thenReturn(claims); + when(vciCacheService.getVCITransaction(TEST_ACCESS_TOKEN_HASH)).thenReturn(newTransaction); + when(securityHelperService.generateSecureRandomString(20)).thenReturn("new-cnonce"); + when(vciCacheService.setVCITransaction(eq(TEST_ACCESS_TOKEN_HASH), any())) + .thenReturn(transaction); + + assertThrows(InvalidNonceException.class, () -> issuanceService.getCredential(request)); + } + + @Test + public void getCredential_NullTransaction_ThrowsInvalidCnonceException() throws VCIExchangeException { + when(parsedAccessToken.isActive()).thenReturn(true); + when(parsedAccessToken.getClaims()).thenReturn(claims); + when(vciCacheService.getVCITransaction(TEST_ACCESS_TOKEN_HASH)).thenReturn(null); + when(vciCacheService.setVCITransaction(any(String.class), any(VCIssuanceTransaction.class))).thenReturn(transaction); + when(proofValidatorFactory.getProofValidator(any())).thenReturn(proofValidator); + + // Act + assertThrows(InvalidNonceException.class, () -> issuanceService.getCredential(request)); + } + + @Test + public void getCredential_ValidRequest_InvalidFormat_Fail() throws DataProviderExchangeException { + request.setFormat("test-vc"); + assertThrows(ErrorConstants.INVALID_REQUEST, CertifyException.class, () -> issuanceService.getCredential(request)); + } + + @Test + public void getCredential_ValidRequest_InvalidScope_Fail() throws DataProviderExchangeException { + claims.put("scope", "test-new-scope"); + when(parsedAccessToken.isActive()).thenReturn(true); + assertThrows(ErrorConstants.INVALID_SCOPE, CertifyException.class, () -> issuanceService.getCredential(request)); + } + + @Test + public void getCredential_ValidRequest_InvalidProof_Fail() throws DataProviderExchangeException { + when(parsedAccessToken.isActive()).thenReturn(true); + when(parsedAccessToken.getClaims()).thenReturn(claims); + when(vciCacheService.getVCITransaction(TEST_ACCESS_TOKEN_HASH)).thenReturn(transaction); + when(proofValidatorFactory.getProofValidator(any())).thenReturn(proofValidator); + when(proofValidator.validate(any(), any(), any())).thenReturn(false); + + assertThrows(ErrorConstants.INVALID_PROOF, CertifyException.class, () -> issuanceService.getCredential(request)); + } + + private CredentialRequest createValidCredentialRequest() { + CredentialRequest request = new CredentialRequest(); + request.setFormat("ldp_vc"); + + CredentialDefinition credDef = new CredentialDefinition(); + credDef.setContext(Arrays.asList("https://www.w3.org/2018/credentials/v1")); + credDef.setType(Arrays.asList("VerifiableCredential", "TestCredential")); + credDef.setCredentialSubject(new HashMap<>()); + request.setCredential_definition(credDef); + + CredentialProof proof = new CredentialProof(); + proof.setProof_type("test-proof"); + proof.setJwt("jwt"); + proof.setCwt("cwt"); + request.setProof(proof); + + return request; + } + @Test public void getCredentialIssuerMetadata_valid() { - Mockito.when(issuerMetadata.containsKey("latest")).thenReturn(true); - Mockito.when(issuerMetadata.get("latest")).thenReturn((new LinkedHashMap())); Map actual = issuanceService.getCredentialIssuerMetadata("latest"); assertNotNull(actual); } + @Test + public void getCredentialIssuerMetadataVD11_valid() { + Map actual = issuanceService.getCredentialIssuerMetadata("vd11"); + assertNotNull(actual); + assertTrue(actual.containsKey("credential_issuer")); + assertTrue(actual.containsKey("credential_endpoint")); + assertEquals("https://localhost:9090/v1/certify/issuance/vd11/credential", actual.get("credential_endpoint")); + } + + @Test + public void getCredentialIssuerMetadataVD12_valid() { + Map actual = issuanceService.getCredentialIssuerMetadata("vd12"); + assertNotNull(actual); + assertTrue(actual.containsKey("credential_issuer")); + assertTrue(actual.containsKey("credential_endpoint")); + assertEquals("https://localhost:9090/v1/certify/issuance/vd12/credential", actual.get("credential_endpoint")); + } + @Test public void getCredentialIssuerMetadata_invalid() { - Mockito.when(issuerMetadata.containsKey("latest")).thenReturn(false); - assertThrows(InvalidRequestException.class, () -> issuanceService.getCredentialIssuerMetadata("latest")); + assertThrows(InvalidRequestException.class, () -> issuanceService.getCredentialIssuerMetadata("latestData")); assertThrows(ErrorConstants.UNSUPPORTED_OPENID_VERSION, InvalidRequestException.class, () -> issuanceService.getCredentialIssuerMetadata(null)); } @@ -92,7 +294,7 @@ public void getVerifiableCredential_invalidScope() { CredentialRequest cr = new CredentialRequest(); cr.setFormat(VCFormats.LDP_VC); cr.setCredential_definition(new CredentialDefinition()); - Mockito.when(parsedAccessToken.isActive()).thenReturn(false); + when(parsedAccessToken.isActive()).thenReturn(false); assertThrows(NotAuthenticatedException.class, () -> issuanceService.getCredential(cr)); } } \ No newline at end of file diff --git a/certify-service/src/test/java/io/mosip/certify/services/RenderUtilsTest.java b/certify-service/src/test/java/io/mosip/certify/services/RenderUtilsTest.java new file mode 100644 index 00000000..7da7f6a1 --- /dev/null +++ b/certify-service/src/test/java/io/mosip/certify/services/RenderUtilsTest.java @@ -0,0 +1,45 @@ +package io.mosip.certify.services; + +import io.ipfs.multibase.Multibase; +import io.mosip.certify.core.constants.ErrorConstants; +import io.mosip.certify.core.exception.InvalidRequestException; +import org.junit.jupiter.api.Test; +import org.junit.runner.RunWith; +import org.mockito.MockedStatic; +import org.mockito.Mockito; +import org.mockito.junit.MockitoJUnitRunner; + +import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +import static org.junit.Assert.assertThrows; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.when; + +@RunWith(MockitoJUnitRunner.class) +class RenderUtilsTest { + + @Test + void getDigestMultibase() { + String svg = """ + + """; + String actual = CredentialUtils.getDigestMultibase(svg); + String expected = "z4po9QkJj1fhMt6cxHSnDnAUat4PEVrerUGGsPHLxJnK5"; + assertEquals(expected, actual); + } + + @Test + public void testNoSuchAlgorithmException() { + // Mock the MessageDigest.getInstance() method to throw NoSuchAlgorithmException + try (MockedStatic mockedMessageDigest = Mockito.mockStatic(MessageDigest.class)) { + mockedMessageDigest.when(() -> MessageDigest.getInstance("SHA-256")).thenThrow(NoSuchAlgorithmException.class); + String svg = ""; + assertThrows(RuntimeException.class, () -> CredentialUtils.getDigestMultibase(svg)); + } + } + +} \ No newline at end of file diff --git a/certify-service/src/test/java/io/mosip/certify/services/SvgRenderTemplateServiceTest.java b/certify-service/src/test/java/io/mosip/certify/services/RenderingTemplateServiceImplTest.java similarity index 65% rename from certify-service/src/test/java/io/mosip/certify/services/SvgRenderTemplateServiceTest.java rename to certify-service/src/test/java/io/mosip/certify/services/RenderingTemplateServiceImplTest.java index d79728f3..62bff034 100644 --- a/certify-service/src/test/java/io/mosip/certify/services/SvgRenderTemplateServiceTest.java +++ b/certify-service/src/test/java/io/mosip/certify/services/RenderingTemplateServiceImplTest.java @@ -1,9 +1,10 @@ package io.mosip.certify.services; +import io.mosip.certify.api.dto.RenderingTemplateDTO; import io.mosip.certify.core.constants.ErrorConstants; -import io.mosip.certify.core.entity.SvgTemplate; -import io.mosip.certify.core.exception.TemplateException; -import io.mosip.certify.core.repository.SvgTemplateRepository; +import io.mosip.certify.core.exception.RenderingTemplateException; +import io.mosip.certify.entity.RenderingTemplate; +import io.mosip.certify.repository.RenderingTemplateRepository; import lombok.extern.slf4j.Slf4j; import org.junit.Assert; import org.junit.Test; @@ -15,22 +16,20 @@ import java.time.LocalDateTime; import java.util.Optional; -import java.util.UUID; @Slf4j @RunWith(MockitoJUnitRunner.class) -public class SvgRenderTemplateServiceTest { +public class RenderingTemplateServiceImplTest { @InjectMocks - SvgTemplateServiceImpl svgRenderTemplateService; + RenderingTemplateServiceImpl renderingTemplateService; @Mock - SvgTemplateRepository svgRenderTemplateRepository; + RenderingTemplateRepository svgRenderTemplateRepository; @Test public void getSvgTemplate_withValidDetail_thenPass() { - SvgTemplate svgRenderTemplate = new SvgTemplate(); - UUID id = UUID.randomUUID(); - svgRenderTemplate.setId(id); + RenderingTemplate svgRenderTemplate = new RenderingTemplate(); + svgRenderTemplate.setId("fake-id"); String svgTemplate = """ @@ -40,9 +39,9 @@ public void getSvgTemplate_withValidDetail_thenPass() { """; svgRenderTemplate.setTemplate(svgTemplate); svgRenderTemplate.setCreatedtimes(LocalDateTime.now()); - Optional optional = Optional.of(svgRenderTemplate); + Optional optional = Optional.of(svgRenderTemplate); Mockito.when(svgRenderTemplateRepository.findById(Mockito.any())).thenReturn(optional); - SvgTemplate svgRenderTemplateResponse = svgRenderTemplateService.getSvgTemplate(UUID.randomUUID()); + RenderingTemplateDTO svgRenderTemplateResponse = renderingTemplateService.getSvgTemplate("fake-id"); Assert.assertNotNull(svgRenderTemplateResponse); Assert.assertEquals(svgRenderTemplate.getId(), svgRenderTemplateResponse.getId()); Assert.assertEquals(svgTemplate, optional.get().getTemplate()); @@ -51,8 +50,8 @@ public void getSvgTemplate_withValidDetail_thenPass() { @Test public void getSvgTemplate_withInvalidId_thenFail() { Mockito.when(svgRenderTemplateRepository.findById(Mockito.any())).thenReturn(Optional.empty()); - TemplateException templateException = Assert.assertThrows(TemplateException.class, () -> { - svgRenderTemplateService.getSvgTemplate(UUID.randomUUID()); + RenderingTemplateException templateException = Assert.assertThrows(RenderingTemplateException.class, () -> { + renderingTemplateService.getSvgTemplate("fake-id"); }); Assert.assertEquals(ErrorConstants.INVALID_TEMPLATE_ID, templateException.getErrorCode()); } diff --git a/certify-service/src/test/java/io/mosip/certify/services/SVGRenderUtilsTest.java b/certify-service/src/test/java/io/mosip/certify/services/SVGRenderUtilsTest.java deleted file mode 100644 index 390d19fc..00000000 --- a/certify-service/src/test/java/io/mosip/certify/services/SVGRenderUtilsTest.java +++ /dev/null @@ -1,19 +0,0 @@ -package io.mosip.certify.services; - -import org.junit.jupiter.api.Test; - -import static org.junit.jupiter.api.Assertions.*; - -class SVGRenderUtilsTest { - - @Test - void getDigestMultibase() { - String svg = """ - - """; - String actual = SVGRenderUtils.getDigestMultibase(svg); - String expected = "z4po9QkJj1fhMt6cxHSnDnAUat4PEVrerUGGsPHLxJnK5"; - assertEquals(expected, actual); - } - -} \ No newline at end of file diff --git a/certify-service/src/test/java/io/mosip/certify/services/VCIssuanceServiceImplTest.java b/certify-service/src/test/java/io/mosip/certify/services/VCIssuanceServiceImplTest.java new file mode 100644 index 00000000..ca43e7a2 --- /dev/null +++ b/certify-service/src/test/java/io/mosip/certify/services/VCIssuanceServiceImplTest.java @@ -0,0 +1,292 @@ +package io.mosip.certify.services; + +import foundation.identity.jsonld.JsonLDObject; +import io.mosip.certify.api.dto.VCRequestDto; +import io.mosip.certify.api.dto.VCResult; +import io.mosip.certify.api.exception.DataProviderExchangeException; +import io.mosip.certify.api.exception.VCIExchangeException; +import io.mosip.certify.api.spi.AuditPlugin; +import io.mosip.certify.api.spi.VCIssuancePlugin; +import io.mosip.certify.core.constants.ErrorConstants; +import io.mosip.certify.core.constants.VCFormats; +import io.mosip.certify.core.dto.*; +import io.mosip.certify.core.exception.CertifyException; +import io.mosip.certify.core.exception.InvalidRequestException; +import io.mosip.certify.core.exception.NotAuthenticatedException; +import io.mosip.certify.core.util.SecurityHelperService; +import io.mosip.certify.exception.InvalidNonceException; +import io.mosip.certify.proof.ProofValidator; +import io.mosip.certify.proof.ProofValidatorFactory; +import org.json.JSONObject; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnitRunner; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.test.util.ReflectionTestUtils; + +import java.time.LocalDateTime; +import java.time.ZoneOffset; +import java.util.*; + +import static org.junit.Assert.*; +import static org.junit.Assert.assertThrows; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@RunWith(MockitoJUnitRunner.class) +@ConditionalOnProperty(value = "mosip.certify.plugin-mode", havingValue = "VCIssuance") +public class VCIssuanceServiceImplTest { + @Mock + private LinkedHashMap> issuerMetadata; + + @Mock + private ParsedAccessToken parsedAccessToken; + + @Mock + private ProofValidatorFactory proofValidatorFactory; + + @Mock + private VCIssuancePlugin vcIssuancePlugin; + + @Mock + private VCICacheService vciCacheService; + + @Mock + private SecurityHelperService securityHelperService; + + @Mock + private AuditPlugin auditWrapper; + + @Mock + private ProofValidator proofValidator; + + @InjectMocks + private VCIssuanceServiceImpl issuanceService; + + private static final String TEST_ACCESS_TOKEN_HASH = "test-token-hash"; + private static final String TEST_CNONCE = "test-cnonce"; + + CredentialRequest request; + VCResult vcResult; + Map claims; + VCIssuanceTransaction transaction; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + + issuerMetadata = new LinkedHashMap<>(); + LinkedHashMap latestMetadata = new LinkedHashMap<>(); + LinkedHashMap credentialConfig = new LinkedHashMap<>(); + LinkedHashMap vcConfig = new LinkedHashMap<>(); + vcConfig.put("format", "ldp_vc"); + vcConfig.put("scope", "test-scope"); + vcConfig.put("credential_signing_alg_values_supported", List.of("Ed25519Signature2020")); + Map proofTypes = Map.of("jwt", Map.of("proof_signing_alg_values_supported", List.of("RS256", "PS256"))); + vcConfig.put("proof_types_supported", proofTypes); + List> displayList = List.of(Map.of("name", "test-cred", "background_image", "https://background-image.png")); + vcConfig.put("display", displayList); + LinkedHashMap credDef = new LinkedHashMap<>(); + credDef.put("type", Arrays.asList("VerifiableCredential", "TestCredential")); + vcConfig.put("credential_definition", credDef); + credentialConfig.put("test-credential", vcConfig); + latestMetadata.put("credential_configurations_supported", credentialConfig); + latestMetadata.put("credential_issuer", "https://localhost:9090"); + latestMetadata.put("credential_endpoint", "https://localhost:9090/v1/certify/issuance/credential"); + issuerMetadata.put("latest", latestMetadata); + + ReflectionTestUtils.setField(issuanceService, "issuerMetadata", issuerMetadata); + ReflectionTestUtils.setField(issuanceService, "cNonceExpireSeconds", 300); + + when(parsedAccessToken.getAccessTokenHash()).thenReturn(TEST_ACCESS_TOKEN_HASH); + + request = createValidCredentialRequest(); + claims = new HashMap<>(); + claims.put("scope", "test-scope"); + claims.put("client_id", "test-client"); + request.setClaims(claims); + CredentialDefinition credentialDefinition = new CredentialDefinition(); + credentialDefinition.setContext(List.of("https://example.com")); + credentialDefinition.setType(List.of("VerifiableCredential", "TestCredential")); + request.setCredential_definition(credentialDefinition); + transaction = new VCIssuanceTransaction(); + transaction.setCNonce(TEST_CNONCE); + transaction.setCNonceExpireSeconds(300); + transaction.setCNonceIssuedEpoch(LocalDateTime.now(ZoneOffset.UTC).toEpochSecond(ZoneOffset.UTC)); + vcResult = new VCResult<>(); + JsonLDObject jsonLDObject = new JsonLDObject(); // Create an actual JsonLDObject + vcResult.setCredential(jsonLDObject); + + } + + @Test + public void getCredential_WithValidTransaction_Success() throws VCIExchangeException { + when(parsedAccessToken.isActive()).thenReturn(true); + when(parsedAccessToken.getClaims()).thenReturn(claims); + when(vciCacheService.getVCITransaction(TEST_ACCESS_TOKEN_HASH)).thenReturn(transaction); + when(proofValidatorFactory.getProofValidator(any())).thenReturn(proofValidator); + when(proofValidator.validate(any(), eq(TEST_CNONCE), any())).thenReturn(true); + when(proofValidator.getKeyMaterial(any())).thenReturn("test_holder_id"); + when(vcIssuancePlugin.getVerifiableCredentialWithLinkedDataProof(any(VCRequestDto.class), any(String.class), any(Map.class))).thenReturn(vcResult); + + // Act + CredentialResponse response = issuanceService.getCredential(request); + + // Assert + assertNotNull(response); + verify(auditWrapper).logAudit(any(), any(), any(), any()); + } + + @Test + public void getCredential_ExpiredNonce_ThrowsInvalidNonceException() { + VCIssuanceTransaction newTransaction = new VCIssuanceTransaction(); + newTransaction.setCNonce("new-cnonce"); + newTransaction.setCNonceExpireSeconds(300); + newTransaction.setCNonceIssuedEpoch(0L); + + when(parsedAccessToken.isActive()).thenReturn(true); + when(parsedAccessToken.getClaims()).thenReturn(claims); + when(vciCacheService.getVCITransaction(TEST_ACCESS_TOKEN_HASH)).thenReturn(newTransaction); + when(securityHelperService.generateSecureRandomString(20)).thenReturn("new-cnonce"); + when(vciCacheService.setVCITransaction(eq(TEST_ACCESS_TOKEN_HASH), any())) + .thenReturn(transaction); + + assertThrows(InvalidNonceException.class, () -> issuanceService.getCredential(request)); + } + + @Test + public void getCredential_NullTransaction_ThrowsInvalidCnonceException() throws VCIExchangeException { + when(parsedAccessToken.isActive()).thenReturn(true); + when(parsedAccessToken.getClaims()).thenReturn(claims); + when(vciCacheService.getVCITransaction(TEST_ACCESS_TOKEN_HASH)).thenReturn(null); + when(vciCacheService.setVCITransaction(any(String.class), any(VCIssuanceTransaction.class))).thenReturn(transaction); + when(proofValidatorFactory.getProofValidator(any())).thenReturn(proofValidator); + + // Act + assertThrows(InvalidNonceException.class, () -> issuanceService.getCredential(request)); + } + + @Test + public void getCredential_ValidRequest_NullJSONLD_Fail() { + when(parsedAccessToken.isActive()).thenReturn(true); + when(parsedAccessToken.getClaims()).thenReturn(claims); + when(vciCacheService.getVCITransaction(TEST_ACCESS_TOKEN_HASH)).thenReturn(transaction); + when(proofValidatorFactory.getProofValidator(any())).thenReturn(proofValidator); + when(proofValidator.validate(any(), any(), any())).thenReturn(true); + assertThrows(ErrorConstants.VC_ISSUANCE_FAILED, CertifyException.class, () -> issuanceService.getCredential(request)); + } + + @Test + public void getCredential_ValidRequest_ValidJMsoMDoc_Success() throws VCIExchangeException { + request.setFormat("mso_mdoc"); + request.setDoctype("mso-mdoc"); + when(parsedAccessToken.isActive()).thenReturn(true); + when(parsedAccessToken.getClaims()).thenReturn(claims); + when(vciCacheService.getVCITransaction(TEST_ACCESS_TOKEN_HASH)).thenReturn(transaction); + when(proofValidatorFactory.getProofValidator(any())).thenReturn(proofValidator); + when(proofValidator.validate(any(), any(), any())).thenReturn(true); + when(proofValidator.getKeyMaterial(any())).thenReturn("test_holder_id"); + VCResult msoMDocVCResult = new VCResult<>(); + msoMDocVCResult.setCredential("test_credential"); + when(vcIssuancePlugin.getVerifiableCredential(any(VCRequestDto.class), any(String.class), any(Map.class))).thenReturn(msoMDocVCResult); + + CredentialResponse response = issuanceService.getCredential(request); + assertNotNull(response); + verify(auditWrapper).logAudit(any(), any(), any(), any()); + } + + @Test + public void getCredential_ValidRequest_InvalidFormat_Fail() { + request.setFormat("test-vc"); + assertThrows(ErrorConstants.INVALID_REQUEST, CertifyException.class, () -> issuanceService.getCredential(request)); + } + + @Test + public void getCredential_ValidRequest_InvalidScope_Fail() { + claims.put("scope", "test-new-scope"); + when(parsedAccessToken.isActive()).thenReturn(true); + assertThrows(ErrorConstants.INVALID_SCOPE, CertifyException.class, () -> issuanceService.getCredential(request)); + } + + @Test + public void getCredential_ValidRequest_InvalidProof_Fail() { + when(parsedAccessToken.isActive()).thenReturn(true); + when(parsedAccessToken.getClaims()).thenReturn(claims); + when(vciCacheService.getVCITransaction(TEST_ACCESS_TOKEN_HASH)).thenReturn(transaction); + when(proofValidatorFactory.getProofValidator(any())).thenReturn(proofValidator); + when(proofValidator.validate(any(), any(), any())).thenReturn(false); + + assertThrows(ErrorConstants.INVALID_PROOF, CertifyException.class, () -> issuanceService.getCredential(request)); + } + + private CredentialRequest createValidCredentialRequest() { + CredentialRequest request = new CredentialRequest(); + request.setFormat("ldp_vc"); + + CredentialDefinition credDef = new CredentialDefinition(); + credDef.setContext(Arrays.asList("https://www.w3.org/2018/credentials/v1")); + credDef.setType(Arrays.asList("VerifiableCredential", "TestCredential")); + credDef.setCredentialSubject(new HashMap<>()); + request.setCredential_definition(credDef); + + CredentialProof proof = new CredentialProof(); + proof.setProof_type("test-proof"); + proof.setJwt("jwt"); + proof.setCwt("cwt"); + request.setProof(proof); + return request; + } + + @Test + public void getCredentialIssuerMetadata_valid() { + Map actual = issuanceService.getCredentialIssuerMetadata("latest"); + assertNotNull(actual); + } + + @Test + public void getCredentialIssuerMetadataVD11_valid() { + Map actual = issuanceService.getCredentialIssuerMetadata("vd11"); + assertNotNull(actual); + assertTrue(actual.containsKey("credential_issuer")); + assertTrue(actual.containsKey("credential_endpoint")); + assertEquals("https://localhost:9090/v1/certify/issuance/vd11/credential", actual.get("credential_endpoint")); + } + + @Test + public void getCredentialIssuerMetadataVD12_valid() { + Map actual = issuanceService.getCredentialIssuerMetadata("vd12"); + assertNotNull(actual); + assertTrue(actual.containsKey("credential_issuer")); + assertTrue(actual.containsKey("credential_endpoint")); + assertEquals("https://localhost:9090/v1/certify/issuance/vd12/credential", actual.get("credential_endpoint")); + } + + @Test + public void getCredentialIssuerMetadata_invalid() { + assertThrows(InvalidRequestException.class, () -> issuanceService.getCredentialIssuerMetadata("latestData")); + assertThrows(ErrorConstants.UNSUPPORTED_OPENID_VERSION, InvalidRequestException.class, () -> issuanceService.getCredentialIssuerMetadata(null)); + } + + @Test + public void getVerifiableCredential_invalidRequest() { + CredentialRequest cr = new CredentialRequest(); + cr.setFormat("fake-format"); + assertThrows(ErrorConstants.INVALID_REQUEST, InvalidRequestException.class, + () -> issuanceService.getCredential(cr)); + } + + @Test + public void getVerifiableCredential_invalidScope() { + CredentialRequest cr = new CredentialRequest(); + cr.setFormat(VCFormats.LDP_VC); + cr.setCredential_definition(new CredentialDefinition()); + when(parsedAccessToken.isActive()).thenReturn(false); + assertThrows(NotAuthenticatedException.class, () -> issuanceService.getCredential(cr)); + } +} diff --git a/certify-service/src/test/java/io/mosip/certify/utils/CredentialUtilsTest.java b/certify-service/src/test/java/io/mosip/certify/utils/CredentialUtilsTest.java index e6c4c0e1..5a283463 100644 --- a/certify-service/src/test/java/io/mosip/certify/utils/CredentialUtilsTest.java +++ b/certify-service/src/test/java/io/mosip/certify/utils/CredentialUtilsTest.java @@ -2,7 +2,6 @@ import io.mosip.certify.api.dto.VCRequestDto; import junit.framework.TestCase; -import org.junit.jupiter.params.provider.ArgumentsSource; import java.util.List; @@ -15,4 +14,11 @@ public void testGetTemplateName() { String expected = "UniversityCredential,VerifiableCredential:https://example.org/Person.json,https://www.w3.org/ns/credentials/v2"; assertEquals(expected, CredentialUtils.getTemplateName(request)); } + + public void testIsVC2_0Request() { + VCRequestDto request = new VCRequestDto(); + request.setContext(List.of("https://www.w3.org/ns/credentials/v2", "https://example.org/Person.json")); + request.setType(List.of("VerifiableCredential", "UniversityCredential")); + assertTrue(CredentialUtils.isVC2_0Request(request)); + } } \ No newline at end of file diff --git a/certify-service/src/test/java/io/mosip/certify/utils/DIDDocumentUtilTest.java b/certify-service/src/test/java/io/mosip/certify/utils/DIDDocumentUtilTest.java new file mode 100644 index 00000000..674869b1 --- /dev/null +++ b/certify-service/src/test/java/io/mosip/certify/utils/DIDDocumentUtilTest.java @@ -0,0 +1,113 @@ +package io.mosip.certify.utils; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import org.junit.jupiter.api.Test; + +import io.mosip.certify.core.constants.SignatureAlg; +import io.mosip.certify.core.exception.CertifyException; + +class DIDDocumentUtilTest { + + + @Test + @SuppressWarnings("unchecked") + void testGenerateDIDDocumentEd25519Signature2020() throws Exception { + String vcSignAlgorithm = SignatureAlg.ED25519_SIGNATURE_SUITE_2020; + String certificateString = "-----BEGIN CERTIFICATE-----\nMIIC2jCCAcKgAwIBAgIInbzaZeSXQqEwDQYJKoZIhvcNAQELBQAwgYsxCzAJBgNV\nBAYTAklOMQswCQYDVQQIDAJLQTESMBAGA1UEBwwJQkFOR0FMT1JFMQ4wDAYDVQQK\nDAVJSUlUQjEXMBUGA1UECwwORVhBTVBMRS1DRU5URVIxMjAwBgNVBAMMKXd3dy5l\neGFtcGxlLmNvbSAoQ0VSVElGWV9WQ19TSUdOX0VEMjU1MTkpMB4XDTI0MTIyOTA4\nNDY1OFoXDTI3MTIyOTA4NDY1OFowgYYxCzAJBgNVBAYTAklOMQswCQYDVQQIDAJL\nQTESMBAGA1UEBwwJQkFOR0FMT1JFMQ4wDAYDVQQKDAVJSUlUQjEXMBUGA1UECwwO\nRVhBTVBMRS1DRU5URVIxLTArBgNVBAMMJENFUlRJRllfVkNfU0lHTl9FRDI1NTE5\nLUVEMjU1MTlfU0lHTjAqMAUGAytlcAMhAOX8AiOEEHfyJRKJsjshaJps736mS4zS\ncZVcdUpZpEbxoz8wPTAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBSVZaEpMbDVgrAy\nZP0ZlwMMXzhS9jAOBgNVHQ8BAf8EBAMCBSAwDQYJKoZIhvcNAQELBQADggEBAAJ4\nPZb+6A5Q5Z2X18B3PLNLs5It2UTu+qL8PhQyoVpEoq44Efl+10qaAiBp7l66sYcf\nsYVhREnJaBACqsEy5cFTZ7j+7Q0GhuepnkYTS9n8DwlOgZgPU0tBBwthbixwFyME\ne2VdtuhyuVnGK8+W6VWMg+lQGyQwPgrzAf6L81bADn+cW6tIVoYd4uuNfoXeM0pL\nTtKMGEyRVdx3Q+wcLEGZXCTYPkUgf+mq8kqf9dCDdDgblPU891msZpg0KGRkLD28\nPF7FPhK0Hq4DzwfhdpiQMe7W19FyH/IXRprJi8LKx4V9Y/rBAvR2loLR0PwVl+VB\nB55c6EluZ6hn9xuwr9w=\n-----END CERTIFICATE-----\n"; + String issuerURI = "did:example:123"; + String issuerPublicKeyURI = "did:example:123#key-0"; + + Map didDocument = DIDDocumentUtil.generateDIDDocument(vcSignAlgorithm, certificateString, issuerURI, issuerPublicKeyURI); + assertEquals(didDocument.get("@context"), Collections.singletonList("https://www.w3.org/ns/did/v1")); + assertEquals(issuerURI, didDocument.get("id")); + assertEquals(Collections.singletonList(issuerPublicKeyURI), didDocument.get("authentication")); + assertEquals(Collections.singletonList(issuerPublicKeyURI), didDocument.get("assertionMethod")); + + Map verificationMethod = ((List>)didDocument.get("verificationMethod")).get(0); + assertEquals(verificationMethod.get("publicKeyMultibase"), "z6Mkuw2HXTbK7fXoVbiuriHdm3NDDcVRYWxRymfzdTE6ZWgQ"); + assertEquals(verificationMethod.get("controller"), issuerURI); + assertEquals(verificationMethod.get("id"), issuerPublicKeyURI); + assertEquals(verificationMethod.get("type"), "Ed25519VerificationKey2020"); + assertEquals(verificationMethod.get("@context"), "https://w3id.org/security/suites/ed25519-2020/v1"); + } + + @Test + @SuppressWarnings("unchecked") + void testGenerateDIDDocumentEd25519Signature2018() throws Exception { + String vcSignAlgorithm = SignatureAlg.ED25519_SIGNATURE_SUITE_2020; + String certificateString = "-----BEGIN CERTIFICATE-----\nMIIC2jCCAcKgAwIBAgIInbzaZeSXQqEwDQYJKoZIhvcNAQELBQAwgYsxCzAJBgNV\nBAYTAklOMQswCQYDVQQIDAJLQTESMBAGA1UEBwwJQkFOR0FMT1JFMQ4wDAYDVQQK\nDAVJSUlUQjEXMBUGA1UECwwORVhBTVBMRS1DRU5URVIxMjAwBgNVBAMMKXd3dy5l\neGFtcGxlLmNvbSAoQ0VSVElGWV9WQ19TSUdOX0VEMjU1MTkpMB4XDTI0MTIyOTA4\nNDY1OFoXDTI3MTIyOTA4NDY1OFowgYYxCzAJBgNVBAYTAklOMQswCQYDVQQIDAJL\nQTESMBAGA1UEBwwJQkFOR0FMT1JFMQ4wDAYDVQQKDAVJSUlUQjEXMBUGA1UECwwO\nRVhBTVBMRS1DRU5URVIxLTArBgNVBAMMJENFUlRJRllfVkNfU0lHTl9FRDI1NTE5\nLUVEMjU1MTlfU0lHTjAqMAUGAytlcAMhAOX8AiOEEHfyJRKJsjshaJps736mS4zS\ncZVcdUpZpEbxoz8wPTAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBSVZaEpMbDVgrAy\nZP0ZlwMMXzhS9jAOBgNVHQ8BAf8EBAMCBSAwDQYJKoZIhvcNAQELBQADggEBAAJ4\nPZb+6A5Q5Z2X18B3PLNLs5It2UTu+qL8PhQyoVpEoq44Efl+10qaAiBp7l66sYcf\nsYVhREnJaBACqsEy5cFTZ7j+7Q0GhuepnkYTS9n8DwlOgZgPU0tBBwthbixwFyME\ne2VdtuhyuVnGK8+W6VWMg+lQGyQwPgrzAf6L81bADn+cW6tIVoYd4uuNfoXeM0pL\nTtKMGEyRVdx3Q+wcLEGZXCTYPkUgf+mq8kqf9dCDdDgblPU891msZpg0KGRkLD28\nPF7FPhK0Hq4DzwfhdpiQMe7W19FyH/IXRprJi8LKx4V9Y/rBAvR2loLR0PwVl+VB\nB55c6EluZ6hn9xuwr9w=\n-----END CERTIFICATE-----\n"; + String issuerURI = "did:example:123"; + String issuerPublicKeyURI = "did:example:123#key-0"; + + Map didDocument = DIDDocumentUtil.generateDIDDocument(vcSignAlgorithm, certificateString, issuerURI, issuerPublicKeyURI); + assertEquals(didDocument.get("@context"), Collections.singletonList("https://www.w3.org/ns/did/v1")); + assertEquals(issuerURI, didDocument.get("id")); + assertEquals(Collections.singletonList(issuerPublicKeyURI), didDocument.get("authentication")); + assertEquals(Collections.singletonList(issuerPublicKeyURI), didDocument.get("assertionMethod")); + + Map verificationMethod = ((List>)didDocument.get("verificationMethod")).get(0); + assertEquals(verificationMethod.get("publicKeyMultibase"), "z6Mkuw2HXTbK7fXoVbiuriHdm3NDDcVRYWxRymfzdTE6ZWgQ"); + assertEquals(verificationMethod.get("controller"), issuerURI); + assertEquals(verificationMethod.get("id"), issuerPublicKeyURI); + assertEquals(verificationMethod.get("type"), "Ed25519VerificationKey2020"); + assertEquals(verificationMethod.get("@context"), "https://w3id.org/security/suites/ed25519-2020/v1"); + } + + @Test + @SuppressWarnings("unchecked") + void testGenerateDIDDocumentRSASignature2018() throws Exception { + String vcSignAlgorithm = SignatureAlg.RSA_SIGNATURE_SUITE_2018; + String certificateString = "-----BEGIN CERTIFICATE-----\nMIIDxzCCAq+gAwIBAgIIgusG+rdZJWgwDQYJKoZIhvcNAQELBQAweDELMAkGA1UE\nBhMCSU4xCzAJBgNVBAgMAktBMRIwEAYDVQQHDAlCQU5HQUxPUkUxDjAMBgNVBAoM\nBUlJSVRCMRcwFQYDVQQLDA5FWEFNUExFLUNFTlRFUjEfMB0GA1UEAwwWd3d3LmV4\nYW1wbGUuY29tIChST09UKTAeFw0yNDEyMjkxMDQ4NDRaFw0yNzEyMjkxMDQ4NDRa\nMIGHMQswCQYDVQQGEwJJTjELMAkGA1UECAwCS0ExEjAQBgNVBAcMCUJBTkdBTE9S\nRTEOMAwGA1UECgwFSUlJVEIxFzAVBgNVBAsMDkVYQU1QTEUtQ0VOVEVSMS4wLAYD\nVQQDDCV3d3cuZXhhbXBsZS5jb20gKENFUlRJRllfVkNfU0lHTl9SU0EpMIIBIjAN\nBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlkO3CPWJ6Jqu9hzm4Eew7EJSbYCX\n7YGBxYAjRHcLuVgsttyRWUZ3DiRYEoN7bG/jCh7E0Gvv4M5ux4VSw3RJlM+9Tfje\nDUkHdZQ0g5A/r69uyy7+zE8MIM2fXcgwEgIZabm/Zb6+T/K6mSsdPQAHnBe1zXoq\ngTuyTT6pVsHbR0+5ULkhN3BuJyhJ7zw8vC1aiFYA2b05nU7H1Rn+axes8+v80mQS\nGR9iJTrGeYtvz8a+gRhvXmK+h8nhUAJaPHJBacCRMErKvgddWkWBtknJZQmnX0RN\n2IC5+egbE8thCVg8BGBcxOoUBHjHYmus0CZNbTMJQIObL62p7caJHnYtHwIDAQAB\no0UwQzASBgNVHRMBAf8ECDAGAQH/AgEBMB0GA1UdDgQWBBSOi5/6I4vvp8eshKNs\nSwr/BtWM/zAOBgNVHQ8BAf8EBAMCAoQwDQYJKoZIhvcNAQELBQADggEBAKHiZu+1\nPjKqvlesbAj4QJkQlpdstz0PgEOnT6+flpcnmyMJj2QvWQbfX8niVWGMIc0HnO+H\ntzc/2oKmO9eQpmdnL4DN7NtuXxbTwTzsGDI934jRZGqHmeCh90j+T7QqSbk+GanC\nOMGFth7aV9j5cDSr7gCIom6N0TEUw/5a3O1+vJCwtQtN29H/+ksro+RYyN4/nbrR\ngix5XRR9VTcsLbM8J8dOxqZxsP+Bgebqp+fqv8QEea4cVYtStEMY6/4M6kKWyL7Q\nsmgwsJ5Vr5w/Y1hOIKaQe9WwWm/T8+byElVgZ/vT5tCYhLxHyBa1vfTgq1FQe5gb\nc6CDSimUO4tcosI=\n-----END CERTIFICATE-----\n"; + String issuerURI = "did:example:123"; + String issuerPublicKeyURI = "did:example:123#key-0"; + + Map didDocument = DIDDocumentUtil.generateDIDDocument(vcSignAlgorithm, certificateString, issuerURI, issuerPublicKeyURI); + assertEquals(didDocument.get("@context"), Collections.singletonList("https://www.w3.org/ns/did/v1")); + assertEquals(issuerURI, didDocument.get("id")); + assertEquals(Collections.singletonList(issuerPublicKeyURI), didDocument.get("authentication")); + assertEquals(Collections.singletonList(issuerPublicKeyURI), didDocument.get("assertionMethod")); + + Map verificationMethod = ((List>)didDocument.get("verificationMethod")).get(0); + assertEquals(((Map)verificationMethod.get("publicKeyJwk")).get("kty"), "RSA"); + assertEquals(((Map)verificationMethod.get("publicKeyJwk")).get("e"), "AQAB"); + assertEquals(((Map)verificationMethod.get("publicKeyJwk")).get("n"), "lkO3CPWJ6Jqu9hzm4Eew7EJSbYCX7YGBxYAjRHcLuVgsttyRWUZ3DiRYEoN7bG_jCh7E0Gvv4M5ux4VSw3RJlM-9TfjeDUkHdZQ0g5A_r69uyy7-zE8MIM2fXcgwEgIZabm_Zb6-T_K6mSsdPQAHnBe1zXoqgTuyTT6pVsHbR0-5ULkhN3BuJyhJ7zw8vC1aiFYA2b05nU7H1Rn-axes8-v80mQSGR9iJTrGeYtvz8a-gRhvXmK-h8nhUAJaPHJBacCRMErKvgddWkWBtknJZQmnX0RN2IC5-egbE8thCVg8BGBcxOoUBHjHYmus0CZNbTMJQIObL62p7caJHnYtHw"); + assertEquals(verificationMethod.get("controller"), issuerURI); + assertEquals(verificationMethod.get("id"), issuerPublicKeyURI); + assertEquals(verificationMethod.get("type"), "JsonWebKey2020"); + assertEquals(verificationMethod.get("@context"), "https://w3id.org/security/suites/jws-2020/v1"); + } + + @Test + void testGenerateDIDDocumentUnsupportedAlgorithm() { + String vcSignAlgorithm = "UnsupportedAlgorithm"; + String certificateString = "-----BEGIN CERTIFICATE-----\nMIIC2jCCAcKgAwIBAgIInbzaZeSXQqEwDQYJKoZIhvcNAQELBQAwgYsxCzAJBgNV\nBAYTAklOMQswCQYDVQQIDAJLQTESMBAGA1UEBwwJQkFOR0FMT1JFMQ4wDAYDVQQK\nDAVJSUlUQjEXMBUGA1UECwwORVhBTVBMRS1DRU5URVIxMjAwBgNVBAMMKXd3dy5l\neGFtcGxlLmNvbSAoQ0VSVElGWV9WQ19TSUdOX0VEMjU1MTkpMB4XDTI0MTIyOTA4\nNDY1OFoXDTI3MTIyOTA4NDY1OFowgYYxCzAJBgNVBAYTAklOMQswCQYDVQQIDAJL\nQTESMBAGA1UEBwwJQkFOR0FMT1JFMQ4wDAYDVQQKDAVJSUlUQjEXMBUGA1UECwwO\nRVhBTVBMRS1DRU5URVIxLTArBgNVBAMMJENFUlRJRllfVkNfU0lHTl9FRDI1NTE5\nLUVEMjU1MTlfU0lHTjAqMAUGAytlcAMhAOX8AiOEEHfyJRKJsjshaJps736mS4zS\ncZVcdUpZpEbxoz8wPTAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBSVZaEpMbDVgrAy\nZP0ZlwMMXzhS9jAOBgNVHQ8BAf8EBAMCBSAwDQYJKoZIhvcNAQELBQADggEBAAJ4\nPZb+6A5Q5Z2X18B3PLNLs5It2UTu+qL8PhQyoVpEoq44Efl+10qaAiBp7l66sYcf\nsYVhREnJaBACqsEy5cFTZ7j+7Q0GhuepnkYTS9n8DwlOgZgPU0tBBwthbixwFyME\ne2VdtuhyuVnGK8+W6VWMg+lQGyQwPgrzAf6L81bADn+cW6tIVoYd4uuNfoXeM0pL\nTtKMGEyRVdx3Q+wcLEGZXCTYPkUgf+mq8kqf9dCDdDgblPU891msZpg0KGRkLD28\nPF7FPhK0Hq4DzwfhdpiQMe7W19FyH/IXRprJi8LKx4V9Y/rBAvR2loLR0PwVl+VB\nB55c6EluZ6hn9xuwr9w=\n-----END CERTIFICATE-----\n"; + String issuerURI = "did:example:123"; + String issuerPublicKeyURI = "did:example:123#key-0"; + + CertifyException exception = assertThrows(CertifyException.class, () -> { + DIDDocumentUtil.generateDIDDocument(vcSignAlgorithm, certificateString, issuerURI, issuerPublicKeyURI); + }); + + assertEquals("unsupported_algorithm", exception.getErrorCode()); + } + + @Test + void testGenerateDIDDocumentWithInvalidCertificateString() { + String invalidCertificateString = "INVALID_CERTIFICATE"; + String vcSignAlgorithm = SignatureAlg.RSA_SIGNATURE_SUITE_2018; + String issuerURI = "did:web:example.com"; + String issuerPublicKeyURI = "did:web:example.com#key-0"; + + CertifyException exception = assertThrows(CertifyException.class, () -> { + DIDDocumentUtil.generateDIDDocument(vcSignAlgorithm, invalidCertificateString, issuerURI, issuerPublicKeyURI); + }); + + assertEquals("invalid_certificate", exception.getErrorCode()); + } + +} diff --git a/certify-core/src/test/java/io/mosip/certify/core/validators/CredentialRequestValidatorFactoryTest.java b/certify-service/src/test/java/io/mosip/certify/validators/CredentialRequestValidatorTest.java similarity index 81% rename from certify-core/src/test/java/io/mosip/certify/core/validators/CredentialRequestValidatorFactoryTest.java rename to certify-service/src/test/java/io/mosip/certify/validators/CredentialRequestValidatorTest.java index c5f6e53d..6af40f8c 100644 --- a/certify-core/src/test/java/io/mosip/certify/core/validators/CredentialRequestValidatorFactoryTest.java +++ b/certify-service/src/test/java/io/mosip/certify/validators/CredentialRequestValidatorTest.java @@ -1,25 +1,18 @@ -package io.mosip.certify.core.validators; +package io.mosip.certify.validators; import io.mosip.certify.core.constants.VCFormats; import io.mosip.certify.core.dto.CredentialDefinition; import io.mosip.certify.core.dto.CredentialRequest; -import org.junit.Before; import org.junit.Test; -import java.util.HashMap; import java.util.List; import java.util.Map; import static org.junit.Assert.*; -public class CredentialRequestValidatorFactoryTest { +public class CredentialRequestValidatorTest { - CredentialRequestValidatorFactory factory; - - @Before - public void setUp() { - factory = new CredentialRequestValidatorFactory(); - } + CredentialRequestValidator factory; @Test public void isValid_invalidFormat() { diff --git a/certify-service/src/test/java/io/mosip/certify/validators/LdpVcCredentialRequestValidatorTest.java b/certify-service/src/test/java/io/mosip/certify/validators/LdpVcCredentialRequestValidatorTest.java new file mode 100644 index 00000000..3cccf7ca --- /dev/null +++ b/certify-service/src/test/java/io/mosip/certify/validators/LdpVcCredentialRequestValidatorTest.java @@ -0,0 +1,32 @@ +package io.mosip.certify.validators; + +import io.mosip.certify.core.constants.VCFormats; +import io.mosip.certify.core.dto.CredentialDefinition; +import io.mosip.certify.core.dto.CredentialRequest; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.junit.MockitoJUnitRunner; + +import java.util.Map; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +@RunWith(MockitoJUnitRunner.class) +public class LdpVcCredentialRequestValidatorTest { + @Test + public void checkLdpVcValidatorWithValidCredentialRequest_thenPass() { + CredentialRequest credentialRequest = new CredentialRequest(); + credentialRequest.setFormat(VCFormats.LDP_VC); + credentialRequest.setCredential_definition(new CredentialDefinition()); + assertTrue(LdpVcCredentialRequestValidator.isValidCheck(credentialRequest)); + } + + @Test + public void checkLdpVcValidatorTestWithInvalidCredentialDefinition_thenFail() { + CredentialRequest credentialRequest = new CredentialRequest(); + credentialRequest.setFormat(VCFormats.LDP_VC); + credentialRequest.setClaims(Map.of("client_id", "test-client-id")); + assertFalse(LdpVcCredentialRequestValidator.isValidCheck(credentialRequest)); + } +} diff --git a/certify-service/src/test/java/io/mosip/certify/validators/MsoMdocCredentialRequestValidatorTest.java b/certify-service/src/test/java/io/mosip/certify/validators/MsoMdocCredentialRequestValidatorTest.java new file mode 100644 index 00000000..bbe62d2c --- /dev/null +++ b/certify-service/src/test/java/io/mosip/certify/validators/MsoMdocCredentialRequestValidatorTest.java @@ -0,0 +1,36 @@ +package io.mosip.certify.validators; + +import io.mosip.certify.core.dto.CredentialRequest; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.junit.MockitoJUnitRunner; + +import java.util.Map; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +@RunWith(MockitoJUnitRunner.class) +public class MsoMdocCredentialRequestValidatorTest { + @Test + public void checkMsoMdocValidatorWithValidCredentialRequest_thenPass() { + CredentialRequest credentialRequest = new CredentialRequest(); + credentialRequest.setDoctype("mdoc-doctype"); + credentialRequest.setClaims(Map.of("client_id", "test-client-id")); + assertTrue(MsoMdocCredentialRequestValidator.isValidCheck(credentialRequest)); + } + + @Test + public void checkMsoMdocValidatorWithInvalidDoctype_thenFail() { + CredentialRequest credentialRequest = new CredentialRequest(); + credentialRequest.setClaims(Map.of("client_id", "test-client-id")); + assertFalse(MsoMdocCredentialRequestValidator.isValidCheck(credentialRequest)); + } + + @Test + public void checkMsoMdocValidatorWithEmptyClaims_thenFail() { + CredentialRequest credentialRequest = new CredentialRequest(); + credentialRequest.setDoctype("mdoc-doctype"); + assertFalse(MsoMdocCredentialRequestValidator.isValidCheck(credentialRequest)); + } +} diff --git a/certify-service/src/test/java/io/mosip/certify/services/templating/VelocityTemplatingEngineImplTest.java b/certify-service/src/test/java/io/mosip/certify/vcformatters/VelocityTemplatingEngineImplTest.java similarity index 67% rename from certify-service/src/test/java/io/mosip/certify/services/templating/VelocityTemplatingEngineImplTest.java rename to certify-service/src/test/java/io/mosip/certify/vcformatters/VelocityTemplatingEngineImplTest.java index 8e3d9225..9ebc4d83 100644 --- a/certify-service/src/test/java/io/mosip/certify/services/templating/VelocityTemplatingEngineImplTest.java +++ b/certify-service/src/test/java/io/mosip/certify/vcformatters/VelocityTemplatingEngineImplTest.java @@ -1,7 +1,8 @@ -package io.mosip.certify.services.templating; +package io.mosip.certify.vcformatters; -import io.mosip.certify.core.entity.TemplateData; -import io.mosip.certify.core.repository.TemplateRepository; +import io.mosip.certify.core.exception.CertifyException; +import io.mosip.certify.entity.CredentialTemplate; +import io.mosip.certify.repository.CredentialTemplateRepository; import junit.framework.TestCase; import lombok.SneakyThrows; import net.javacrumbs.jsonunit.assertj.JsonAssertions; @@ -16,14 +17,11 @@ import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; import org.springframework.stereotype.Service; -import org.springframework.test.util.ReflectionTestUtils; import org.springframework.web.client.RestTemplate; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; +import static org.junit.Assert.assertThrows; import static org.mockito.Mockito.when; @Service @@ -32,17 +30,21 @@ public class VelocityTemplatingEngineImplTest extends TestCase { @InjectMocks private VelocityTemplatingEngineImpl formatter; @Mock - TemplateRepository templateRepository; + CredentialTemplateRepository credentialTemplateRepository; + + private CredentialTemplate vc1; + private CredentialTemplate vc2; + private CredentialTemplate vc3; + private CredentialTemplate vc4; @SneakyThrows @Before public void setUp() { - List templates = new ArrayList<>(); - TemplateData vc1 = initTemplate(""" + vc1 = initTemplate(""" { "@context": [ "https://www.w3.org/2018/credentials/v1"] - "issuer": "${issuer}", + "issuer": "${_issuer}", "type": ["VerifiableCredential", "MockVerifiableCredential"], "issuanceDate": "${validFrom}", "expirationDate": "${validUntil}", @@ -63,11 +65,11 @@ public void setUp() { """, "MockVerifiableCredential,VerifiableCredential", "https://schema.org,https://www.w3.org/2018/credentials/v1"); - TemplateData vc2 = initTemplate(""" + vc2 = initTemplate(""" { "@context": [ "https://www.w3.org/ns/credentials/v2"], - "issuer": "${issuer}", + "issuer": "${_issuer}", "type": ["VerifiableCredential", "MockVerifiableCredential"], "validFrom": "${validFrom}", "validUntil": "${validUntil}", @@ -90,12 +92,12 @@ public void setUp() { "MockVerifiableCredential,VerifiableCredential", "https://example.org/Person.json,https://www.w3.org/ns/credentials/v2" ); - TemplateData vc3 = initTemplate(""" + vc3 = initTemplate(""" { "@context": [ "https://www.w3.org/2018/credentials/v1", "https://vharsh.github.io/DID/mock-context.json"], - "issuer": "${issuer}", + "issuer": "${_issuer}", "type": ["VerifiableCredential", "MockVerifiableCredential"], "issuanceDate": "${validFrom}", "expirationDate": "${validUntil}", @@ -118,8 +120,13 @@ public void setUp() { "MockVerifiableCredential,VerifiableCredential", "https://vharsh.github.io/DID/mock-context.json,https://www.w3.org/2018/credentials/v1" ); - when(templateRepository.findAll()).thenReturn(List.of(vc1, vc2, vc3)); - ReflectionTestUtils.setField(formatter, "shouldHaveDates", true); + vc4 = initTemplate(null, + "TestVerifiableCredential,VerifiableCredential", + "https://vharsh.github.io/DID/mock-context.json,https://www.w3.org/2018/credentials/v1" + ); + //when(templateRepository.findByCredentialTypeAndContext("MockVerifiableCredential,VerifiableCredential", "https://schema.org,https://www.w3.org/2018/credentials/v1")).thenReturn(Optional.of(vc1)); + when(credentialTemplateRepository.findByCredentialTypeAndContext("MockVerifiableCredential,VerifiableCredential", "https://example.org/Person.json,https://www.w3.org/ns/credentials/v2")).thenReturn(Optional.of(vc2)); + //when(templateRepository.findByCredentialTypeAndContext("MockVerifiableCredential,VerifiableCredential", "https://vharsh.github.io/DID/mock-context.json,https://www.w3.org/2018/credentials/v1")).thenReturn(Optional.of(vc3)); formatter.initialize(); // engine = new VelocityEngine(); // engine.setProperty(RuntimeConstants.RESOURCE_LOADER, "classpath"); @@ -130,8 +137,8 @@ public void setUp() { // engine.init(); } - private TemplateData initTemplate(String template, String type, String context) { - TemplateData t = new TemplateData(); + private CredentialTemplate initTemplate(String template, String type, String context) { + CredentialTemplate t = new CredentialTemplate(); t.setTemplate(template); t.setCredentialType(type); t.setContext(context); @@ -168,6 +175,32 @@ public void testTemplating() { JsonAssertions.assertThatJson(actualJSON).isEqualTo(expectedJSON); } + @SneakyThrows + @Test + public void testTemplating_templateNotFound_thenFail() { + JSONObject ret = new JSONObject(); + ret.put("vcVer", "VC-V1"); + // ret.put("issuer", "https://example.com/fake-issuer"); + ret.put("fullName", "Amit Developer"); + ret.put("validFrom", "01/01/2022"); + ret.put("validUntil", "02/02/2122"); + ret.put("gender", "female"); + ret.put("dateOfBirth", "01/01/2022"); + ret.put("email", "amit@fakemail.com"); + ret.put("UIN", 123456); + ret.put("phone", "1234567890"); + // both of the below work + ret.put("addressLine1", List.of("1", "Fake building", "Fake Area", "Fake City", "Near Fake Landmark")); + // ret.put("addressLine1", new String[]{"1", "Fake building", "Fake Area", "Fake City", "Near Fake Landmark"}); + ret.put("province", "Fake Area"); + ret.put("region", "FakeRegion"); + ret.put("postalCode", "123"); + ret.put("face", "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD+wSzIAAAABlBMVEX///+/v7+jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII"); + Map templateMap = Map.of("templateName", "TestVerifiableCredential,VerifiableCredential:https://vharsh.github.io/DID/mock-context.json,https://www.w3.org/2018/credentials/v1", + "issuerURI", "https://example.com/fake-issuer"); + assertThrows(CertifyException.class, () -> formatter.format(ret, templateMap)); + } + @Ignore @Test public void testTemplating_localOnly() { @@ -181,11 +214,32 @@ public void testTemplating_localOnly() { Map templateMap = Map.of("templateName", "MockVerifiableCredential,VerifiableCredential:https://vharsh.github.io/DID/mock-context.json,https://www.w3.org/2018/credentials/v1", "issuerURI", "https://example.com/fake-issuer"); String actualJSON = formatter.format(ret, templateMap); - System.out.println(actualJSON); try { JSONObject j = new JSONObject(actualJSON); } catch (JSONException e) { Assert.fail(e.getMessage()); } } + + @Test + public void getTemplateNameWithValidKey_thenPass() { + String key = "MockVerifiableCredential,VerifiableCredential:https://example.org/Person.json,https://www.w3.org/ns/credentials/v2"; + String template = formatter.getTemplate(key); + Assert.assertNotNull(template); + Assert.assertEquals(vc2.getTemplate(), template); + } + + @Test + public void getTemplateNameWithInvalidKey_thenFail() { + String key = "TestVerifiableCredential,VerifiableCredential;example.org/Person.json,www.w3.org/ns/credentials/v2"; + String template = formatter.getTemplate(key); + Assert.assertNull(template); + } + + @Test + public void getTemplateNameWithNullTemplate_thenFail() { + String key = "TestVerifiableCredential,VerifiableCredential:https://vharsh.github.io/DID/mock-context.json,https://www.w3.org/2018/credentials/v1"; + String template = formatter.getTemplate(key); + Assert.assertNull(template); + } } \ No newline at end of file diff --git a/certify-service/src/test/java/io/mosip/certify/services/KeymanagerLibSignerTest.java b/certify-service/src/test/java/io/mosip/certify/vcsigners/JsonLDVCSignerTest.java similarity index 66% rename from certify-service/src/test/java/io/mosip/certify/services/KeymanagerLibSignerTest.java rename to certify-service/src/test/java/io/mosip/certify/vcsigners/JsonLDVCSignerTest.java index c0fff3fc..b8ae0828 100644 --- a/certify-service/src/test/java/io/mosip/certify/services/KeymanagerLibSignerTest.java +++ b/certify-service/src/test/java/io/mosip/certify/vcsigners/JsonLDVCSignerTest.java @@ -1,12 +1,11 @@ -package io.mosip.certify.services; +package io.mosip.certify.vcsigners; import foundation.identity.jsonld.JsonLDObject; import info.weboftrust.ldsignatures.LdProof; import info.weboftrust.ldsignatures.canonicalizer.URDNA2015Canonicalizer; import io.mosip.certify.api.dto.VCResult; -import io.mosip.certify.core.constants.VCDMConstants; -import io.mosip.certify.services.ldsigner.ProofSignatureStrategy; -import io.mosip.certify.services.ldsigner.RsaProofSignature2018; +import io.mosip.certify.core.constants.Constants; +import io.mosip.certify.proofgenerators.ProofGenerator; import io.mosip.kernel.signature.dto.JWTSignatureResponseDto; import org.junit.Assert; import org.junit.Before; @@ -18,21 +17,19 @@ import org.mockito.junit.MockitoJUnitRunner; import org.springframework.test.util.ReflectionTestUtils; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -import java.sql.Ref; +import java.util.HashMap; import java.util.Map; @RunWith(MockitoJUnitRunner.class) -public class KeymanagerLibSignerTest { +public class JsonLDVCSignerTest { @Mock SignatureService signatureService; @Mock - ProofSignatureStrategy signProps; + ProofGenerator signProps; @InjectMocks - private KeymanagerLibSigner signer; + private JsonLDVCSigner jsonLDVCSigner; private static final String VC_1 = """ { "@context": [ @@ -54,7 +51,22 @@ public class KeymanagerLibSignerTest { "@context": [ "https://www.w3.org/ns/credentials/v2" ], - "validFrom": "2024-09-22T23:06:22.123Z", + "issuanceDate": "2024-09-22T23:06:22.123Z", + "validUntil": "2034-09-22T23:06:22.123Z", + "type": [ + "VerifiableCredential", + "MyPrototypeCredential" + ], + "credentialSubject": { + "mySubjectProperty": "mySubjectValue" + } + }"""; + private static final String VC_3 = """ + { + "@context": [ + "https://www.w3.org/ns/credentials/v2" + ], + "vcIssuanceDate": "2024-09-22T23:06:22.123Z", "validUntil": "2034-09-22T23:06:22.123Z", "type": [ "VerifiableCredential", @@ -67,13 +79,13 @@ public class KeymanagerLibSignerTest { @Before public void setup() { - ReflectionTestUtils.setField(signer, "hostedKey", "https://example.com/sample.pub.key.json/"); + ReflectionTestUtils.setField(jsonLDVCSigner, "issuerPublicKeyURI", "https://example.com/sample.pub.key.json/"); } @Test - public void testPerformSuccess_VC2() { + public void testAttachSignatureSuccess_VC2() { // Mock Templated VC and Key Manager Input - String VCs[] = new String[]{VC_1, VC_2}; + String VCs[] = new String[]{VC_1, VC_2, VC_3}; for (String templatedVC : VCs) { // Prepare a FakeSignature2018 implementation JWTSignatureResponseDto jwsSignedData = new JWTSignatureResponseDto(); @@ -81,12 +93,13 @@ public void testPerformSuccess_VC2() { when(signatureService.jwsSign(any())).thenReturn(jwsSignedData); when(signProps.getName()).thenReturn("FakeSignature2018"); when(signProps.getCanonicalizer()).thenReturn(new URDNA2015Canonicalizer()); - when(signProps.getProof(anyString())).thenReturn("fake-jws-proof"); LdProof l = LdProof.builder().jws("fake-jws-proof").type("FakeSignature2018").proofPurpose("assertionMethod").build(); - when(signProps.buildProof(any(), any())).thenReturn(l); - + when(signProps.generateProof(any(), any(), any())).thenReturn(l); + Map defaultSettings = new HashMap<>(); + defaultSettings.put(Constants.APPLICATION_ID, "fake-application-id"); + defaultSettings.put(Constants.REFERENCE_ID, "fake-reference-id"); // invoke - VCResult vcResult = signer.perform(templatedVC); + VCResult vcResult = jsonLDVCSigner.attachSignature(templatedVC, defaultSettings); // test assert vcResult != null; diff --git a/certify-service/src/test/resources/application-test.properties b/certify-service/src/test/resources/application-test.properties index 0c6aeaa1..64ee7ce1 100644 --- a/certify-service/src/test/resources/application-test.properties +++ b/certify-service/src/test/resources/application-test.properties @@ -3,19 +3,20 @@ # file, You can obtain one at https://mozilla.org/MPL/2.0/. ## ------------------------------------------- Integrations ------------------------------------------------------------ - +mosip.certify.security.ignore-auth-urls=/actuator/**,**/error,**/swagger-ui/**,\ + **/v3/api-docs/**, **/issuance/**,/system-info/**,**/rendering-template/** mosip.certify.integration.scan-base-package=io.mosip.certify mosip.certify.integration.audit-plugin=TestAuditPlugin mosip.certify.integration.vci-plugin=TestVCIPluginImpl -mosip.certify.issuer=PluginIssuer -mosip.certify.issuer.vc-sign-algo=Ed25519Signature2018 -# mosip.certify.issuer.vc-sign-algo:Ed25519Signature2018 for CertifyIssuer test +mosip.certify.plugin-mode=DataProvider +mosip.certify.data-provider-plugin.issuer.vc-sign-algo=Ed25519Signature2018 +# mosip.certify.data-provider-plugin.issuer.vc-sign-algo:Ed25519Signature2018 for CertifyIssuer test ## ------------------------------------------ Discovery openid-configuration ------------------------------------------- mosipbox.public.url=http://localhost:8090 mosip.certify.discovery.issuer-id=${mosipbox.public.url}${server.servlet.path} -mosip.certify.issuer.pub.key=http://localhost/pub.key.json -mosip.certify.issuer.uri=http://localhost/pub.key.json +mosip.certify.data-provider-plugin.issuer-public-key-uri=http://localhost/pub.key.json +mosip.certify.data-provider-plugin.issuer-uri=http://localhost/pub.key.json ##--------------------------------------------------------------------------------------------------------------------- spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration,org.springframework.boot.actuate.autoconfigure.security.servlet.ManagementWebSecurityAutoConfiguration @@ -218,7 +219,6 @@ mosip.certify.key-values={\ }}\ }\ } -mosip.certify.svg-templates=svg-template.json #------------------------------------ Key-manager specific properties -------------------------------------------------- diff --git a/certify-service/src/test/resources/data.sql b/certify-service/src/test/resources/data.sql index 713b5077..f8c17459 100644 --- a/certify-service/src/test/resources/data.sql +++ b/certify-service/src/test/resources/data.sql @@ -1,2 +1,2 @@ -MERGE INTO KEY_POLICY_DEF (APP_ID,KEY_VALIDITY_DURATION,PRE_EXPIRE_DAYS,ACCESS_ALLOWED,IS_ACTIVE,CR_BY,CR_DTIMES) KEY(APP_ID) VALUES ('ROOT', 1095, 50, 'NA', true, 'mosipadmin', now()), ('CERTIFY_SERVICE', 1095, 50, 'NA', true, 'mosipadmin', now()), ('CERTIFY_PARTNER', 1095, 50, 'NA', true, 'mosipadmin', now()), ('CERTIFY_MOCK_RSA', 1095, 50, 'NA', true, 'mosipadmin', now()), ('CERTIFY_MOCK_ED25519', 1095, 50, 'NA', true, 'mosipadmin', now()), ('BASE', 730, 30, 'NA', true, 'mosipadmin', now()); +MERGE INTO KEY_POLICY_DEF (APP_ID,KEY_VALIDITY_DURATION,PRE_EXPIRE_DAYS,ACCESS_ALLOWED,IS_ACTIVE,CR_BY,CR_DTIMES) KEY(APP_ID) VALUES ('ROOT', 1095, 50, 'NA', true, 'mosipadmin', now()), ('CERTIFY_SERVICE', 1095, 50, 'NA', true, 'mosipadmin', now()), ('CERTIFY_PARTNER', 1095, 50, 'NA', true, 'mosipadmin', now()), ('CERTIFY_VC_SIGN_RSA', 1095, 50, 'NA', true, 'mosipadmin', now()), ('CERTIFY_VC_SIGN_ED25519', 1095, 50, 'NA', true, 'mosipadmin', now()), ('BASE', 730, 30, 'NA', true, 'mosipadmin', now()); diff --git a/certify-service/src/test/resources/schema.sql b/certify-service/src/test/resources/schema.sql index a3078f01..a0788d78 100644 --- a/certify-service/src/test/resources/schema.sql +++ b/certify-service/src/test/resources/schema.sql @@ -46,15 +46,38 @@ CREATE TABLE IF NOT EXISTS key_store( CONSTRAINT pk_keystr_id PRIMARY KEY (id) ); -CREATE TABLE IF NOT EXISTS svg_template ( - id VARCHAR NOT NULL, +CREATE TABLE IF NOT EXISTS ca_cert_store( + cert_id character varying(36) NOT NULL, + cert_subject character varying(500) NOT NULL, + cert_issuer character varying(500) NOT NULL, + issuer_id character varying(36) NOT NULL, + cert_not_before timestamp, + cert_not_after timestamp, + crl_uri character varying(120), + cert_data character varying, + cert_thumbprint character varying(100), + cert_serial_no character varying(50), + partner_domain character varying(36), + cr_by character varying(256), + cr_dtimes timestamp, + upd_by character varying(256), + upd_dtimes timestamp, + is_deleted boolean DEFAULT FALSE, + del_dtimes timestamp, + ca_cert_type character varying(25), + CONSTRAINT pk_cacs_id PRIMARY KEY (cert_id), + CONSTRAINT cert_thumbprint_unique UNIQUE (cert_thumbprint,partner_domain) +); + +CREATE TABLE IF NOT EXISTS rendering_template ( + id VARCHAR(128) NOT NULL, template VARCHAR NOT NULL, cr_dtimes timestamp NOT NULL, upd_dtimes timestamp, - CONSTRAINT pk_svgtmp_id PRIMARY KEY (id) + CONSTRAINT pk_rendertmp_id PRIMARY KEY (id) ); -CREATE TABLE IF NOT EXISTS template_data( +CREATE TABLE IF NOT EXISTS credential_template( context character varying(1024) NOT NULL, credential_type character varying(512) NOT NULL, template VARCHAR NOT NULL, diff --git a/certify-service/src/test/resources/svg-template.json b/certify-service/src/test/resources/svg-template.json deleted file mode 100644 index 26d50c03..00000000 --- a/certify-service/src/test/resources/svg-template.json +++ /dev/null @@ -1,6 +0,0 @@ -[ - { - "id": "5b9c2a12-810a-7388-2dc8-13ee7ad88bac", - "content": "\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n {{credentialSubject/policyName}}\n {{credentialSubject/policyNumber}}\n {{credentialSubject/fullName}}\n {{credentialSubject/gender}}\n {{credentialSubject/email}}\n {{credentialSubject/mobile}}\n\n Policy Issued On\n {{credentialSubject/policyIssuedOn}}\n\n Policy Expires On\n {{credentialSubject/policyExpiresOn}}\n\n Issuance Date On\n {{issuanceDate}}\n\n Expiration Date On\n {{expirationDate}}\n" - } -] \ No newline at end of file diff --git a/db_scripts/mosip_certify/ddl.sql b/db_scripts/mosip_certify/ddl.sql index 34a4f0f7..6506c911 100644 --- a/db_scripts/mosip_certify/ddl.sql +++ b/db_scripts/mosip_certify/ddl.sql @@ -3,7 +3,8 @@ \ir ddl/certify-key_alias.sql \ir ddl/certify-key_policy_def.sql \ir ddl/certify-key_store.sql -\ir ddl/certify-svg_template.sql -\ir ddl/template_data.sql +\ir ddl/certify-ca_cert_store.sql +\ir ddl/certify-rendering_template.sql +\ir ddl/certify-credential_template.sql diff --git a/db_scripts/mosip_certify/ddl/certify-ca_cert_store.sql b/db_scripts/mosip_certify/ddl/certify-ca_cert_store.sql new file mode 100644 index 00000000..77a1a4ec --- /dev/null +++ b/db_scripts/mosip_certify/ddl/certify-ca_cert_store.sql @@ -0,0 +1,54 @@ +-- This Source Code Form is subject to the terms of the Mozilla Public +-- License, v. 2.0. If a copy of the MPL was not distributed with this +-- file, You can obtain one at https://mozilla.org/MPL/2.0/. +-- ------------------------------------------------------------------------------------------------- +-- Database Name: inji_certify +-- Table Name : ca_cert_store +-- Purpose : Key Store table +-- +-- +-- Modified Date Modified By Comments / Remarks +-- ------------------------------------------------------------------------------------------ +-- ------------------------------------------------------------------------------------------ +CREATE TABLE ca_cert_store( + cert_id character varying(36) NOT NULL, + cert_subject character varying(500) NOT NULL, + cert_issuer character varying(500) NOT NULL, + issuer_id character varying(36) NOT NULL, + cert_not_before timestamp, + cert_not_after timestamp, + crl_uri character varying(120), + cert_data character varying, + cert_thumbprint character varying(100), + cert_serial_no character varying(50), + partner_domain character varying(36), + cr_by character varying(256), + cr_dtimes timestamp, + upd_by character varying(256), + upd_dtimes timestamp, + is_deleted boolean DEFAULT FALSE, + del_dtimes timestamp, + ca_cert_type character varying(25), + CONSTRAINT pk_cacs_id PRIMARY KEY (cert_id), + CONSTRAINT cert_thumbprint_unique UNIQUE (cert_thumbprint,partner_domain) + +); +COMMENT ON TABLE ca_cert_store IS 'Certificate Authority Certificate Store: Store details of all the certificate provided by certificate authority which will be used by MOSIP'; +COMMENT ON COLUMN ca_cert_store.cert_id IS 'Certificate ID: Unique ID (UUID) will be generated and assigned to the uploaded CA/Sub-CA certificate'; +COMMENT ON COLUMN ca_cert_store.cert_subject IS 'Certificate Subject: Subject DN of the certificate'; +COMMENT ON COLUMN ca_cert_store.cert_issuer IS 'Certificate Issuer: Issuer DN of the certificate'; +COMMENT ON COLUMN ca_cert_store.issuer_id IS 'Issuer UUID of the certificate. (Issuer certificate should be available in the DB)'; +COMMENT ON COLUMN ca_cert_store.cert_not_before IS 'Certificate Start Date: Certificate Interval - Validity Start Date & Time'; +COMMENT ON COLUMN ca_cert_store.cert_not_after IS 'Certificate Validity end Date: Certificate Interval - Validity End Date & Time'; +COMMENT ON COLUMN ca_cert_store.crl_uri IS 'CRL URL: CRL URI of the issuer.'; +COMMENT ON COLUMN ca_cert_store.cert_data IS 'Certificate Data: PEM Encoded actual certificate data.'; +COMMENT ON COLUMN ca_cert_store.cert_thumbprint IS 'Certificate Thumb Print: SHA1 generated certificate thumbprint.'; +COMMENT ON COLUMN ca_cert_store.cert_serial_no IS 'Certificate Serial No: Serial Number of the certificate.'; +COMMENT ON COLUMN ca_cert_store.partner_domain IS 'Partner Domain : To add Partner Domain in CA/Sub-CA certificate chain'; +COMMENT ON COLUMN ca_cert_store.cr_by IS 'Created By : ID or name of the user who create / insert record'; +COMMENT ON COLUMN ca_cert_store.cr_dtimes IS 'Created DateTimestamp : Date and Timestamp when the record is created/inserted'; +COMMENT ON COLUMN ca_cert_store.upd_by IS 'Updated By : ID or name of the user who update the record with new values'; +COMMENT ON COLUMN ca_cert_store.upd_dtimes IS 'Updated DateTimestamp : Date and Timestamp when any of the fields in the record is updated with new values.'; +COMMENT ON COLUMN ca_cert_store.is_deleted IS 'IS_Deleted : Flag to mark whether the record is Soft deleted.'; +COMMENT ON COLUMN ca_cert_store.del_dtimes IS 'Deleted DateTimestamp : Date and Timestamp when the record is soft deleted with is_deleted=TRUE'; +COMMENT ON COLUMN ca_cert_store.ca_cert_type IS 'CA Certificate Type : Indicates if the certificate is a ROOT or INTERMEDIATE CA certificate'; diff --git a/db_scripts/mosip_certify/ddl/template_data.sql b/db_scripts/mosip_certify/ddl/certify-credential_template.sql similarity index 55% rename from db_scripts/mosip_certify/ddl/template_data.sql rename to db_scripts/mosip_certify/ddl/certify-credential_template.sql index 53c56395..c82d07a0 100644 --- a/db_scripts/mosip_certify/ddl/template_data.sql +++ b/db_scripts/mosip_certify/ddl/certify-credential_template.sql @@ -3,7 +3,7 @@ -- file, You can obtain one at https://mozilla.org/MPL/2.0/. -- ------------------------------------------------------------------------------------------------- -- Database Name: inji_certify --- Table Name : template_data +-- Table Name : credential_template -- Purpose : Template Data table -- -- @@ -11,7 +11,7 @@ -- ------------------------------------------------------------------------------------------ -- ------------------------------------------------------------------------------------------ -CREATE TABLE IF NOT EXISTS template_data( +CREATE TABLE IF NOT EXISTS credential_template( context character varying(1024) NOT NULL, credential_type character varying(512) NOT NULL, template VARCHAR NOT NULL, @@ -20,10 +20,10 @@ CREATE TABLE IF NOT EXISTS template_data( CONSTRAINT pk_template PRIMARY KEY (context, credential_type) ); -COMMENT ON TABLE template_data IS 'Template Data: Contains velocity template for VC'; +COMMENT ON TABLE credential_template IS 'Template Data: Contains velocity template for VC'; -COMMENT ON COLUMN svg_template.context IS 'VC Context: Context URL list items separated by comma(,)'; -COMMENT ON COLUMN svg_template.credential_type IS 'Credential Type: Credential type list items separated by comma(,)'; -COMMENT ON COLUMN svg_template.template IS 'Template Content: Velocity Template to generate the VC'; -COMMENT ON COLUMN svg_template.cr_dtimes IS 'Date when the template was inserted in table.'; -COMMENT ON COLUMN svg_template.upd_dtimes IS 'Date when the template was last updated in table.'; +COMMENT ON COLUMN credential_template.context IS 'VC Context: Context URL list items separated by comma(,)'; +COMMENT ON COLUMN credential_template.credential_type IS 'Credential Type: Credential type list items separated by comma(,)'; +COMMENT ON COLUMN credential_template.template IS 'Template Content: Velocity Template to generate the VC'; +COMMENT ON COLUMN credential_template.cr_dtimes IS 'Date when the template was inserted in table.'; +COMMENT ON COLUMN credential_template.upd_dtimes IS 'Date when the template was last updated in table.'; diff --git a/db_scripts/mosip_certify/ddl/certify-svg_template.sql b/db_scripts/mosip_certify/ddl/certify-rendering_template.sql similarity index 52% rename from db_scripts/mosip_certify/ddl/certify-svg_template.sql rename to db_scripts/mosip_certify/ddl/certify-rendering_template.sql index 8ba1730d..5b4e3160 100644 --- a/db_scripts/mosip_certify/ddl/certify-svg_template.sql +++ b/db_scripts/mosip_certify/ddl/certify-rendering_template.sql @@ -3,7 +3,7 @@ -- file, You can obtain one at https://mozilla.org/MPL/2.0/. -- ------------------------------------------------------------------------------------------------- -- Database Name: inji_certify --- Table Name : svg_template +-- Table Name : rendering_template -- Purpose : Svg Template table -- -- @@ -11,17 +11,17 @@ -- ------------------------------------------------------------------------------------------ -- ------------------------------------------------------------------------------------------ -CREATE TABLE svg_template ( - id UUID NOT NULL, +CREATE TABLE rendering_template ( + id VARCHAR(128) NOT NULL, template VARCHAR NOT NULL, cr_dtimes timestamp NOT NULL, upd_dtimes timestamp, - CONSTRAINT pk_svgtmp_id PRIMARY KEY (id) + CONSTRAINT pk_rendertmp_id PRIMARY KEY (id) ); -COMMENT ON TABLE svg_template IS 'SVG Render Template: Contains svg render image for VC.'; +COMMENT ON TABLE rendering_template IS 'SVG Render Template: Contains svg render image for VC.'; -COMMENT ON COLUMN svg_template.id IS 'Template Id: Unique id assigned to save and identify template.'; -COMMENT ON COLUMN svg_template.template IS 'SVG Template Content: SVG Render Image for the VC details.'; -COMMENT ON COLUMN svg_template.cr_dtimes IS 'Date when the template was inserted in table.'; -COMMENT ON COLUMN svg_template.upd_dtimes IS 'Date when the template was last updated in table.'; +COMMENT ON COLUMN rendering_template.id IS 'Template Id: Unique id assigned to save and identify template.'; +COMMENT ON COLUMN rendering_template.template IS 'SVG Template Content: SVG Render Image for the VC details.'; +COMMENT ON COLUMN rendering_template.cr_dtimes IS 'Date when the template was inserted in table.'; +COMMENT ON COLUMN rendering_template.upd_dtimes IS 'Date when the template was last updated in table.'; diff --git a/db_scripts/mosip_certify/dml/certify-key_policy_def.csv b/db_scripts/mosip_certify/dml/certify-key_policy_def.csv index fc01ef11..d7ab96c1 100644 --- a/db_scripts/mosip_certify/dml/certify-key_policy_def.csv +++ b/db_scripts/mosip_certify/dml/certify-key_policy_def.csv @@ -2,5 +2,6 @@ app_id,key_validity_duration,pre_expire_days,access_allowed,is_active,cr_by,cr_d ROOT,2920,1125,NA,TRUE,mosipadmin,now() CERTIFY_SERVICE,1095,60,NA,TRUE,mosipadmin,now() CERTIFY_PARTNER,1095,60,NA,TRUE,mosipadmin,now() -CERTIFY_MOCK_RSA,1095,60,NA,TRUE,mosipadmin,now() -CERTIFY_MOCK_ED25519,1095,60,NA,TRUE,mosipadmin,now() +CERTIFY_VC_SIGN_RSA,1095,60,NA,TRUE,mosipadmin,now() +BASE,730,60,NA,TRUE,mosipadmin,now() +CERTIFY_VC_SIGN_ED25519,1095,60,NA,TRUE,mosipadmin,now() diff --git a/db_upgrade_script/mosip_certify/sql/0.9.1_to_0.10.0_rollback.sql b/db_upgrade_script/mosip_certify/sql/0.9.1_to_0.10.0_rollback.sql new file mode 100644 index 00000000..35ddc7bb --- /dev/null +++ b/db_upgrade_script/mosip_certify/sql/0.9.1_to_0.10.0_rollback.sql @@ -0,0 +1,21 @@ +-- This Source Code Form is subject to the terms of the Mozilla Public +-- License, v. 2.0. If a copy of the MPL was not distributed with this +-- file, You can obtain one at https://mozilla.org/MPL/2.0/. +-- ------------------------------------------------------------------------------------------------- +-- Database Name: inji_certify +-- Table Name : rendering_template,credential_template, ca_cert_store +-- Purpose : To remove Certify v0.10.0 changes and make DB ready for Certify v0.9.1 +-- +-- Create By : Harsh Vardhan +-- Created Date : January-2025 +-- +-- Modified Date Modified By Comments / Remarks +-- ------------------------------------------------------------------------------------------ +-- ------------------------------------------------------------------------------------------ + +drop table rendering_template; +drop table credential_template; +drop table ca_cert_store; + +--- Keymanager policy drop --- +DELETE FROM certify.key_policy_def where APP_ID in ('CERTIFY_VC_SIGN_RSA', 'CERTIFY_VC_SIGN_ED25519', 'BASE'); diff --git a/db_upgrade_script/mosip_certify/sql/0.9.1_to_0.10.0_upgrade.sql b/db_upgrade_script/mosip_certify/sql/0.9.1_to_0.10.0_upgrade.sql new file mode 100644 index 00000000..cfa205d8 --- /dev/null +++ b/db_upgrade_script/mosip_certify/sql/0.9.1_to_0.10.0_upgrade.sql @@ -0,0 +1,97 @@ +-- This Source Code Form is subject to the terms of the Mozilla Public +-- License, v. 2.0. If a copy of the MPL was not distributed with this +-- file, You can obtain one at https://mozilla.org/MPL/2.0/. +-- ------------------------------------------------------------------------------------------------- +-- Database Name: inji_certify +-- Table Name : rendering_template,credential_template, ca_cert_store +-- Purpose : To upgrade Certify v0.10.0 changes and make it compatible with new Keymanager lib +-- +-- Create By : Harsh Vardhan +-- Created Date : January-2025 +-- +-- Modified Date Modified By Comments / Remarks +-- ------------------------------------------------------------------------------------------ +-- ------------------------------------------------------------------------------------------ + +--- keymanager specific DB changes --- +CREATE TABLE ca_cert_store( + cert_id character varying(36) NOT NULL, + cert_subject character varying(500) NOT NULL, + cert_issuer character varying(500) NOT NULL, + issuer_id character varying(36) NOT NULL, + cert_not_before timestamp, + cert_not_after timestamp, + crl_uri character varying(120), + cert_data character varying, + cert_thumbprint character varying(100), + cert_serial_no character varying(50), + partner_domain character varying(36), + cr_by character varying(256), + cr_dtimes timestamp, + upd_by character varying(256), + upd_dtimes timestamp, + is_deleted boolean DEFAULT FALSE, + del_dtimes timestamp, + ca_cert_type character varying(25), + CONSTRAINT pk_cacs_id PRIMARY KEY (cert_id), + CONSTRAINT cert_thumbprint_unique UNIQUE (cert_thumbprint,partner_domain) + +); + +COMMENT ON TABLE ca_cert_store IS 'Certificate Authority Certificate Store: Store details of all the certificate provided by certificate authority which will be used by MOSIP'; +COMMENT ON COLUMN ca_cert_store.cert_id IS 'Certificate ID: Unique ID (UUID) will be generated and assigned to the uploaded CA/Sub-CA certificate'; +COMMENT ON COLUMN ca_cert_store.cert_subject IS 'Certificate Subject: Subject DN of the certificate'; +COMMENT ON COLUMN ca_cert_store.cert_issuer IS 'Certificate Issuer: Issuer DN of the certificate'; +COMMENT ON COLUMN ca_cert_store.issuer_id IS 'Issuer UUID of the certificate. (Issuer certificate should be available in the DB)'; +COMMENT ON COLUMN ca_cert_store.cert_not_before IS 'Certificate Start Date: Certificate Interval - Validity Start Date & Time'; +COMMENT ON COLUMN ca_cert_store.cert_not_after IS 'Certificate Validity end Date: Certificate Interval - Validity End Date & Time'; +COMMENT ON COLUMN ca_cert_store.crl_uri IS 'CRL URL: CRL URI of the issuer.'; +COMMENT ON COLUMN ca_cert_store.cert_data IS 'Certificate Data: PEM Encoded actual certificate data.'; +COMMENT ON COLUMN ca_cert_store.cert_thumbprint IS 'Certificate Thumb Print: SHA1 generated certificate thumbprint.'; +COMMENT ON COLUMN ca_cert_store.cert_serial_no IS 'Certificate Serial No: Serial Number of the certificate.'; +COMMENT ON COLUMN ca_cert_store.partner_domain IS 'Partner Domain : To add Partner Domain in CA/Sub-CA certificate chain'; +COMMENT ON COLUMN ca_cert_store.cr_by IS 'Created By : ID or name of the user who create / insert record'; +COMMENT ON COLUMN ca_cert_store.cr_dtimes IS 'Created DateTimestamp : Date and Timestamp when the record is created/inserted'; +COMMENT ON COLUMN ca_cert_store.upd_by IS 'Updated By : ID or name of the user who update the record with new values'; +COMMENT ON COLUMN ca_cert_store.upd_dtimes IS 'Updated DateTimestamp : Date and Timestamp when any of the fields in the record is updated with new values.'; +COMMENT ON COLUMN ca_cert_store.is_deleted IS 'IS_Deleted : Flag to mark whether the record is Soft deleted.'; +COMMENT ON COLUMN ca_cert_store.del_dtimes IS 'Deleted DateTimestamp : Date and Timestamp when the record is soft deleted with is_deleted=TRUE'; +COMMENT ON COLUMN ca_cert_store.ca_cert_type IS 'CA Certificate Type : Indicates if the certificate is a ROOT or INTERMEDIATE CA certificate'; + +--- Certify specific DB changes --- + +INSERT INTO certify.key_policy_def(APP_ID,KEY_VALIDITY_DURATION,PRE_EXPIRE_DAYS,ACCESS_ALLOWED,IS_ACTIVE,CR_BY,CR_DTIMES) VALUES('CERTIFY_VC_SIGN_RSA', 1095, 60, 'NA', true, 'mosipadmin', now()); +INSERT INTO certify.key_policy_def(APP_ID,KEY_VALIDITY_DURATION,PRE_EXPIRE_DAYS,ACCESS_ALLOWED,IS_ACTIVE,CR_BY,CR_DTIMES) VALUES('CERTIFY_VC_SIGN_ED25519', 1095, 60, 'NA', true, 'mosipadmin', now()); +INSERT INTO certify.key_policy_def(APP_ID,KEY_VALIDITY_DURATION,PRE_EXPIRE_DAYS,ACCESS_ALLOWED,IS_ACTIVE,CR_BY,CR_DTIMES) VALUES('BASE', 1095, 60, 'NA', true, 'mosipadmin', now()); + +CREATE TABLE rendering_template ( + id VARCHAR(128) NOT NULL, + template VARCHAR NOT NULL, + cr_dtimes timestamp NOT NULL, + upd_dtimes timestamp, + CONSTRAINT pk_rendertmp_id PRIMARY KEY (id) +); + +COMMENT ON TABLE rendering_template IS 'SVG Render Template: Contains svg render image for VC.'; + +COMMENT ON COLUMN rendering_template.id IS 'Template Id: Unique id assigned to save and identify template.'; +COMMENT ON COLUMN rendering_template.template IS 'SVG Template Content: SVG Render Image for the VC details.'; +COMMENT ON COLUMN rendering_template.cr_dtimes IS 'Date when the template was inserted in table.'; +COMMENT ON COLUMN rendering_template.upd_dtimes IS 'Date when the template was last updated in table.'; + +CREATE TABLE credential_template( + context character varying(1024) NOT NULL, + credential_type character varying(512) NOT NULL, + template VARCHAR NOT NULL, + cr_dtimes timestamp NOT NULL default now(), + upd_dtimes timestamp, + CONSTRAINT pk_template PRIMARY KEY (context, credential_type) +); + +COMMENT ON TABLE credential_template IS 'Template Data: Contains velocity template for VC'; + +COMMENT ON COLUMN credential_template.context IS 'VC Context: Context URL list items separated by comma(,)'; +COMMENT ON COLUMN credential_template.credential_type IS 'Credential Type: Credential type list items separated by comma(,)'; +COMMENT ON COLUMN credential_template.template IS 'Template Content: Velocity Template to generate the VC'; +COMMENT ON COLUMN credential_template.cr_dtimes IS 'Date when the template was inserted in table.'; +COMMENT ON COLUMN credential_template.upd_dtimes IS 'Date when the template was last updated in table.'; diff --git a/docker-compose/docker-compose-certify/README.md b/docker-compose/docker-compose-certify/README.md deleted file mode 100644 index 3725510f..00000000 --- a/docker-compose/docker-compose-certify/README.md +++ /dev/null @@ -1,56 +0,0 @@ -## Overview - -This is the docker-compose setup to run esignet UI and esignet-service. This is not for production use. - -## What is in the docker-compose setup folder? - -1. "config" folder holds the esignet properties file. -2. "docker-compose.yml" file with esignet setup with other required services -3. "esignet_init.sql" comprises DDL and DMLs required by esignet. -4. "loader_path" this is esignet mount volume from where all the runtime dependencies are loaded to classpath. If any new esignet plugins to be tested -should be placed in this folder and respective plugin configuration should be updated in config/esignet-default.properties. - -```Note: Refer https://docs.esignet.io/integration to know how to create custom plugins to integrate.``` - -## How to run this setup? - -1. Start the docker-compose file - -> docker-compose up - -2. Download the postman script from [here](https://github.com/mosip/esignet/blob/master/docs/postman-collections/esignet-OIDC-flow-with-mock.postman_collection.json) -and its environment from [here](https://github.com/mosip/esignet/blob/master/docs/postman-collections/esignet-OIDC-flow-with-mock.postman_environment.json) - -3. Import the downloaded collection and environment into postman. - -4. To create an OIDC/OAuth client, run the below request from the postman collection "OIDC Client mgmt" folder - * Get CSRF token - * Create OIDC Client - -5. To run the OIDC flow, run the below request(same order) from the postman collection "AuthCode flow with OTP login" folder. - * Get CSRF token - * Authorize / OAuthdetails request - * Send OTP - * Authenticate User - * Authorization Code - * Get Tokens - * Get userInfo - -6. To run the Verifiable Credential Issuance flow, run the below request(same order) from the postman collection "VCI" folder. - * Get CSRF token - * Authorize / OAuthdetails request - * Send OTP - * Authenticate User V2 - * Authorization Code - * Get Tokens V2 - * Get Credential - - -## How to Access esignet UI? - -To invoke the authorize endpoint of esignet UI to start OIDC/VCI flow, use the below URL: - -http://localhost:3000/authorize?nonce=ere973eieljznge2311&state=eree2311&client_id=health-service-client&redirect_uri=https://healthservices.com/callback&scope=openid&response_type=code&acr_values=mosip:idp:acr:generated-code&claims=%7B%22userinfo%22:%7B%22name%22:%7B%22essential%22:false%7D,%22phone_number%22:%7B%22essential%22:true%7D%7D,%22id_token%22:%7B%7D%7D&claims_locales=en&display=page&state=consent&ui_locales=en-IN - -```Note: Change the value of client_id, redirect_uri, acr_values and claims as per your requirement in the above URL.``` - diff --git a/docker-compose/docker-compose-certify/certify_init.sql b/docker-compose/docker-compose-certify/certify_init.sql deleted file mode 100644 index 882de1f1..00000000 --- a/docker-compose/docker-compose-certify/certify_init.sql +++ /dev/null @@ -1,92 +0,0 @@ -CREATE DATABASE inji_certify - ENCODING = 'UTF8' - LC_COLLATE = 'en_US.UTF-8' - LC_CTYPE = 'en_US.UTF-8' - TABLESPACE = pg_default - OWNER = postgres - TEMPLATE = template0; - -COMMENT ON DATABASE inji_certify IS 'certify related data is stored in this database'; - -\c inji_certify postgres - -DROP SCHEMA IF EXISTS certify CASCADE; -CREATE SCHEMA certify; -ALTER SCHEMA certify OWNER TO postgres; -ALTER DATABASE inji_certify SET search_path TO certify,pg_catalog,public; - -CREATE TABLE certify.key_alias( - id character varying(36) NOT NULL, - app_id character varying(36) NOT NULL, - ref_id character varying(128), - key_gen_dtimes timestamp, - key_expire_dtimes timestamp, - status_code character varying(36), - lang_code character varying(3), - cr_by character varying(256) NOT NULL, - cr_dtimes timestamp NOT NULL, - upd_by character varying(256), - upd_dtimes timestamp, - is_deleted boolean DEFAULT FALSE, - del_dtimes timestamp, - cert_thumbprint character varying(100), - uni_ident character varying(50), - CONSTRAINT pk_keymals_id PRIMARY KEY (id), - CONSTRAINT uni_ident_const UNIQUE (uni_ident) -); - -CREATE TABLE certify.key_policy_def( - app_id character varying(36) NOT NULL, - key_validity_duration smallint, - is_active boolean NOT NULL, - pre_expire_days smallint, - access_allowed character varying(1024), - cr_by character varying(256) NOT NULL, - cr_dtimes timestamp NOT NULL, - upd_by character varying(256), - upd_dtimes timestamp, - is_deleted boolean DEFAULT FALSE, - del_dtimes timestamp, - CONSTRAINT pk_keypdef_id PRIMARY KEY (app_id) -); - -CREATE TABLE certify.key_store( - id character varying(36) NOT NULL, - master_key character varying(36) NOT NULL, - private_key character varying(2500) NOT NULL, - certificate_data character varying NOT NULL, - cr_by character varying(256) NOT NULL, - cr_dtimes timestamp NOT NULL, - upd_by character varying(256), - upd_dtimes timestamp, - is_deleted boolean DEFAULT FALSE, - del_dtimes timestamp, - CONSTRAINT pk_keystr_id PRIMARY KEY (id) -); - -CREATE TABLE certify.svg_template ( - id UUID NOT NULL, - template VARCHAR NOT NULL, - cr_dtimes timestamp NOT NULL, - upd_dtimes timestamp, - CONSTRAINT pk_svgtmp_id PRIMARY KEY (id) -); - -CREATE TABLE certify.template_data( - context character varying(1024) NOT NULL, - credential_type character varying(512) NOT NULL, - template VARCHAR NOT NULL, - cr_dtimes timestamp NOT NULL default now(), - upd_dtimes timestamp, - CONSTRAINT pk_template PRIMARY KEY (context, credential_type) -); - - - -INSERT INTO certify.KEY_POLICY_DEF(APP_ID,KEY_VALIDITY_DURATION,PRE_EXPIRE_DAYS,ACCESS_ALLOWED,IS_ACTIVE,CR_BY,CR_DTIMES) VALUES('ROOT', 2920, 1125, 'NA', true, 'mosipadmin', now()); -INSERT INTO certify.KEY_POLICY_DEF(APP_ID,KEY_VALIDITY_DURATION,PRE_EXPIRE_DAYS,ACCESS_ALLOWED,IS_ACTIVE,CR_BY,CR_DTIMES) VALUES('CERTIFY_SERVICE', 1095, 50, 'NA', true, 'mosipadmin', now()); -INSERT INTO certify.KEY_POLICY_DEF(APP_ID,KEY_VALIDITY_DURATION,PRE_EXPIRE_DAYS,ACCESS_ALLOWED,IS_ACTIVE,CR_BY,CR_DTIMES) VALUES('CERTIFY_PARTNER', 1095, 50, 'NA', true, 'mosipadmin', now()); -INSERT INTO certify.KEY_POLICY_DEF(APP_ID,KEY_VALIDITY_DURATION,PRE_EXPIRE_DAYS,ACCESS_ALLOWED,IS_ACTIVE,CR_BY,CR_DTIMES) VALUES('CERTIFY_MOCK_RSA', 1095, 50, 'NA', true, 'mosipadmin', now()); -INSERT INTO certify.KEY_POLICY_DEF(APP_ID,KEY_VALIDITY_DURATION,PRE_EXPIRE_DAYS,ACCESS_ALLOWED,IS_ACTIVE,CR_BY,CR_DTIMES) VALUES('CERTIFY_MOCK_ED25519', 1095, 50, 'NA', true, 'mosipadmin', now()); -INSERT INTO certify.KEY_POLICY_DEF(APP_ID,KEY_VALIDITY_DURATION,PRE_EXPIRE_DAYS,ACCESS_ALLOWED,IS_ACTIVE,CR_BY,CR_DTIMES) VALUES('BASE', 730, 30, 'NA', true, 'mosipadmin', now()); - diff --git a/docker-compose/docker-compose-certify/config/certify-default.properties b/docker-compose/docker-compose-certify/config/certify-default.properties deleted file mode 100644 index 700dd974..00000000 --- a/docker-compose/docker-compose-certify/config/certify-default.properties +++ /dev/null @@ -1,168 +0,0 @@ -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this -# file, You can obtain one at https://mozilla.org/MPL/2.0/. - -## Application Name -spring.application.name=certify -spring.cloud.config.uri=http://localhost:8888 - -server.port=8090 -server.servlet.path=/v1/certify - -openapi.info.title=Certify Service -openapi.info.description=Rest Endpoints for operations related to certify -openapi.info.version=1.0 -openapi.info.license.name=Mosip -openapi.info.license.url=https://docs.mosip.io/platform/license -mosipbox.public.url=http://localhost:${server.port} -openapi.service.server.url=${mosipbox.public.url}${server.servlet.path} -openapi.service.server.description=Certify Service -springdoc.swagger-ui.disable-swagger-default-url=true -spring.mvc.servlet.path=${server.servlet.path} - -spring.messages.basename=messages -spring.messages.encoding=UTF-8 - -spring.main.allow-bean-definition-overriding=true -spring.mvc.pathmatch.matching-strategy=ANT_PATH_MATCHER - - - -## -------------------------------------- Authentication & Authorization ----------------------------------------------- - -mosip.certify.security.auth.post-urls={} -mosip.certify.security.auth.put-urls={} -mosip.certify.security.auth.get-urls={} - -mosip.certify.security.ignore-csrf-urls=**/actuator/**,/favicon.ico,**/error,\ - **/swagger-ui/**,**/v3/api-docs/**,\ - **/issuance/** - -mosip.certify.security.ignore-auth-urls=**/actuator/**,**/error,**/swagger-ui/**,\ - **/v3/api-docs/**, **/issuance/**,/public/** - - -## ------------------------------------------ Discovery openid-configuration ------------------------------------------- -mosip.certify.discovery.issuer-id=${mosipbox.public.url}${server.servlet.path} -mosip.certify.authorization.url=http://localhost:8088 - -##--------------change this later--------------------------------- -mosip.certify.supported.jwt-proof-alg={'RS256','PS256'} -mosip.certify.issuer=PluginIssuer - - -##----- These are reference to the oauth resource server providing jwk----------------------------------## -mosip.certify.cnonce-expire-seconds=40 - -mosip.certify.identifier=${mosipbox.public.url} -mosip.certify.authn.filter-urls={ '${server.servlet.path}/issuance/credential', '${server.servlet.path}/issuance/vd11/credential', '${server.servlet.path}/issuance/vd12/credential' } -mosip.certify.authn.issuer-uri=${mosip.certify.authorization.url}/v1/esignet -mosip.certify.authn.jwk-set-uri=http://esignet:8088/v1/esignet/oauth/.well-known/jwks.json -mosip.certify.authn.allowed-audiences={ '${mosipbox.public.url}${server.servlet.path}/issuance/credential', '${mosip.certify.authorization.url}/v1/esignet/vci/credential' } - -#------------------------------------ Key-manager specific properties -------------------------------------------------- -#Crypto asymmetric algorithm name -mosip.kernel.crypto.asymmetric-algorithm-name=RSA/ECB/OAEPWITHSHA-256ANDMGF1PADDING -#Crypto symmetric algorithm name -mosip.kernel.crypto.symmetric-algorithm-name=AES/GCM/PKCS5Padding -#Keygenerator asymmetric algorithm name -mosip.kernel.keygenerator.asymmetric-algorithm-name=RSA -#Keygenerator symmetric algorithm name -mosip.kernel.keygenerator.symmetric-algorithm-name=AES -#Asymmetric algorithm key length -mosip.kernel.keygenerator.asymmetric-key-length=2048 -#Symmetric algorithm key length -mosip.kernel.keygenerator.symmetric-key-length=256 -#Encrypted data and encrypted symmetric key separator -mosip.kernel.data-key-splitter=#KEY_SPLITTER# -#GCM tag length -mosip.kernel.crypto.gcm-tag-length=128 -#Hash algo name -mosip.kernel.crypto.hash-algorithm-name=PBKDF2WithHmacSHA512 -#Symmtric key length used in hash -mosip.kernel.crypto.hash-symmetric-key-length=256 -#No of iterations in hash -mosip.kernel.crypto.hash-iteration=100000 -#Sign algo name -mosip.kernel.crypto.sign-algorithm-name=RS256 -#Certificate Sign algo name -mosip.kernel.certificate.sign.algorithm=SHA256withRSA - -mosip.kernel.keymanager.hsm.config-path=CERTIFY_PKCS12/local.p12 -mosip.kernel.keymanager.hsm.keystore-type=PKCS12 -mosip.kernel.keymanager.hsm.keystore-pass=local - -#Type of keystore, Supported Types: PKCS11, PKCS12, Offline, JCE -#mosip.kernel.keymanager.hsm.keystore-type=PKCS11 -# For PKCS11 provide Path of config file. -# For PKCS12 keystore type provide the p12/pfx file path. P12 file will be created internally so provide only file path & file name. -# For Offline & JCE property can be left blank, specified value will be ignored. -#mosip.kernel.keymanager.hsm.config-path=/config/softhsm-application.conf -# Passkey of keystore for PKCS11, PKCS12 -# For Offline & JCE proer can be left blank. JCE password use other JCE specific properties. -#mosip.kernel.keymanager.hsm.keystore-pass=${softhsm.certify.mock.security.pin} - - -mosip.kernel.keymanager.certificate.default.common-name=www.example.com -mosip.kernel.keymanager.certificate.default.organizational-unit=EXAMPLE-CENTER -mosip.kernel.keymanager.certificate.default.organization=IIITB -mosip.kernel.keymanager.certificate.default.location=BANGALORE -mosip.kernel.keymanager.certificate.default.state=KA -mosip.kernel.keymanager.certificate.default.country=IN - -mosip.kernel.keymanager.softhsm.certificate.common-name=www.example.com -mosip.kernel.keymanager.softhsm.certificate.organizational-unit=Example Unit -mosip.kernel.keymanager.softhsm.certificate.organization=IIITB -mosip.kernel.keymanager.softhsm.certificate.country=IN - -# Application Id for PMS master key. -mosip.kernel.partner.sign.masterkey.application.id=PMS -mosip.kernel.partner.allowed.domains=DEVICE - -mosip.kernel.keymanager-service-validate-url=https://${mosip.hostname}/keymanager/validate -mosip.kernel.keymanager.jwtsign.validate.json=false -mosip.keymanager.dao.enabled=false -crypto.PrependThumbprint.enable=true - -mosip.kernel.keymgr.hsm.health.check.enabled=true -mosip.kernel.keymgr.hsm.health.key.app-id=CERTIFY_SERVICE -mosip.kernel.keymgr.hsm.healthkey.ref-id=TRANSACTION_CACHE - -mosip.kernel.keymgr.hsm.health.check.encrypt=true - -mosip.certify.cache.security.secretkey.reference-id=TRANSACTION_CACHE - -##----------------------------------------- Database properties -------------------------------------------------------- - -mosip.certify.database.hostname=database -mosip.certify.database.port=5432 -spring.datasource.url=jdbc:postgresql://${mosip.certify.database.hostname}:${mosip.certify.database.port}/inji_certify?currentSchema=certify -spring.datasource.username=postgres -spring.datasource.password=postgres - -spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect -spring.jpa.show-sql=false -spring.jpa.hibernate.ddl-auto=none -spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true - -## ---------------------------------------- Cache configuration -------------------------------------------------------- -spring.cache.type=redis -spring.data.redis.host=cache -spring.data.redis.port=6379 -spring.data.redis.password=redis - -#spring.cache.type=simple -spring.cache.cache-names=${mosip.certify.cache.names} - -management.health.redis.enabled=false - -mosip.certify.access-token-expire-seconds=86400 - -mosip.certify.cache.names=userinfo,vcissuance -# Cache size setup is applicable only for 'simple' cache type. -# Cache size configuration will not be considered with 'Redis' cache type -mosip.certify.cache.size={'userinfo': 200, 'vcissuance' : 2000 } - - -# Cache expire in seconds is applicable for both 'simple' and 'Redis' cache type -mosip.certify.cache.expire-in-seconds={'userinfo': ${mosip.certify.access-token-expire-seconds}, 'vcissuance': ${mosip.certify.access-token-expire-seconds}} \ No newline at end of file diff --git a/docker-compose/docker-compose-certify/config/certify-mock-identity.properties b/docker-compose/docker-compose-certify/config/certify-mock-identity.properties deleted file mode 100644 index d1ffce47..00000000 --- a/docker-compose/docker-compose-certify/config/certify-mock-identity.properties +++ /dev/null @@ -1,158 +0,0 @@ -## ------------------------------------------- Mock ID Integration properties ------------------------------------------------------------ -mosip.certify.integration.scan-base-package=io.mosip.certify.mock.integration -mosip.certify.integration.audit-plugin=LoggerAuditService -mosip.certify.integration.vci-plugin=MockVCIssuancePlugin - -## ------------------------------------------- Mock ID plugin related properties ------------------------------------------------------------ -mosip.certify.mock.vciplugin.verification-method=${mosip.certify.authn.jwk-set-uri} -mosip.certify.mock.authenticator.get-identity-url=http://mock-identity-system:8082/v1/mock-identity-system/identity -mosip.certify.cache.security.algorithm-name=AES/ECB/PKCS5Padding -mosip.certify.cache.secure.individual-id=false -mosip.certify.cache.store.individual-id=true -# TODO: Onboard secrets for local build -mosip.certify.mock.vciplugin.issuer.key-cert=dummy -mosip.certify.svg-templates=insurance-svg-template.json -mosip.certify.key-values={\ - 'vd12' : {\ - 'credential_issuer': '${mosip.certify.identifier}', \ - 'authorization_servers': {'${mosip.certify.authorization.url}'}, \ - 'credential_endpoint': '${mosip.certify.identifier}${server.servlet.path}/issuance/vd12/credential', \ - 'display': {{'name': 'Mock Verifiable Credential', 'locale': 'en'}},\ - 'credentials_supported' : { \ - 'MockVerifiableCredential_ldp' : {\ - 'format': 'ldp_vc',\ - 'scope' : 'mock_identity_vc_ldp',\ - 'cryptographic_binding_methods_supported': {'did:jwk'},\ - 'cryptographic_suites_supported': {'RsaSignature2018'},\ - 'proof_types_supported': {'jwt'},\ - 'credential_definition': {\ - 'type': {'VerifiableCredential','MockVerifiableCredential'},\ - 'credentialSubject': {\ - 'fullName': { 'display': {{'name': 'Full Name', 'locale': 'en' }}},\ - 'phone': { 'display': {{'name': 'Phone Number', 'locale': 'en' }}},\ - 'dateOfBirth': { 'display': {{'name': 'DOB', 'locale': 'en' }}},\ - 'gender': { 'display': {{'name': 'Gender', 'locale': 'en' }}},\ - 'email': { 'display': {{'name': 'Email Id', 'locale': 'en' }}},\ - 'region': { 'display': {{'name': 'Region', 'locale': 'en' }}},\ - 'province': { 'display': {{'name': 'Province', 'locale': 'en' }}},\ - 'UIN': { 'display': {{'name': 'UIN', 'locale': 'en' }}},\ - 'VID': { 'display': {{'name': 'VID', 'locale': 'en' }}},\ - 'postalCode': { 'display': {{'name': 'Postal Code', 'locale': 'en' }}}\ - }},\ - 'display': {{'name': 'Mock Verifiable Credential', \ - 'locale': 'en', \ - 'logo': {'url': '${mosipbox.public.url}/logo.png','alt_text': 'a square logo of a MOSIP'},\ - 'background_color': '#12107c',\ - 'text_color': '#FFFFFF'}},\ - 'order' : {'fullName','phone','dateOfBirth','gender','email','region','province','UIN', 'VID', 'postalCode'}\ - }\ - }\ - },\ - 'latest' : {\ - 'credential_issuer': '${mosip.certify.identifier}', \ - 'authorization_servers': {'${mosip.certify.authorization.url}'}, \ - 'credential_endpoint': '${mosip.certify.identifier}${server.servlet.path}/issuance/credential', \ - 'display': {{'name': 'Mock Verifiable Credential', 'locale': 'en'}},\ - 'credential_configurations_supported' : { \ - 'MockVerifiableCredential_ldp' : {\ - 'format': 'ldp_vc',\ - 'scope' : 'mock_identity_vc_ldp',\ - 'cryptographic_binding_methods_supported': {'did:jwk'},\ - 'credential_signing_alg_values_supported': {'RsaSignature2018'},\ - 'proof_types_supported': {'jwt': {'proof_signing_alg_values_supported': {'RS256', 'PS256', 'ES256'}}},\ - 'credential_definition': {\ - 'type': {'VerifiableCredential','MockVerifiableCredential'},\ - 'credentialSubject': {\ - 'fullName': { 'display': {{'name': 'Full Name', 'locale': 'en' }}},\ - 'phone': { 'display': {{'name': 'Phone Number', 'locale': 'en' }}},\ - 'dateOfBirth': { 'display': {{'name': 'DOB', 'locale': 'en' }}},\ - 'gender': { 'display': {{'name': 'Gender', 'locale': 'en' }}},\ - 'email': { 'display': {{'name': 'Email Id', 'locale': 'en' }}},\ - 'region': { 'display': {{'name': 'Region', 'locale': 'en' }}},\ - 'province': { 'display': {{'name': 'Province', 'locale': 'en' }}},\ - 'UIN': { 'display': {{'name': 'UIN', 'locale': 'en' }}},\ - 'VID': { 'display': {{'name': 'VID', 'locale': 'en' }}},\ - 'postalCode': { 'display': {{'name': 'Postal Code', 'locale': 'en' }}}\ - }},\ - 'display': {{'name': 'Mock Verifiable Credential', \ - 'locale': 'en', \ - 'logo': {'url': '${mosipbox.public.url}/logo.png','alt_text': 'a square logo of a MOSIP'},\ - 'background_color': '#12107c',\ - 'background_image': { 'uri': 'https://${mosipbox.public.url}/inji/mosip-logo.png' }, \ - 'text_color': '#FFFFFF'}},\ - 'order' : {'fullName','phone','dateOfBirth','gender','email','region','province','UIN', 'VID', 'postalCode'}\ - },\ - "DrivingLicenseCredential":{\ - 'format': 'mso_mdoc',\ - 'doctype': 'org.iso.18013.5.1.mDL',\ - 'scope' : 'sample_vc_mdoc',\ - 'cryptographic_binding_methods_supported': {'cose_key'},\ - 'credential_signing_alg_values_supported': {'ES256'},\ - 'proof_types_supported': {'jwt': {'proof_signing_alg_values_supported': {'ES256'}}},\ - 'claims': {\ - 'org.iso.18013.5.1': {'given_name': {'display': {{'name': 'Given Name','locale': 'en'}}},'family_name': {'display': {{'name': 'Family Name','locale': 'en'}}},'issue_date': {'display': {{'name': 'Issue Date','locale': 'en'}}},'expiry_date': {'display': {{'name': 'Expiry Date','locale': 'en'}}},'birth_date': {'display': {{'name': 'Birth Date','locale': 'en'}}},'issuing_country': {'display': {{'name': 'Issuing Country','locale': 'en'}}},'document_number': {'display': {{'name': 'Document Number','locale': 'en'}}}}},\ - 'display': {{'name': 'Mobile Driving License Verifiable Credential', \ - 'locale': 'en', \ - 'background_image': { 'uri': 'https://sunbird.org/images/sunbird-logo-new.png' }, \ - 'logo': {'url': 'https://sunbird.org/images/sunbird-logo-new.png','alt_text': 'a square logo of a Sunbird Mobile Driving License'},\ - 'background_color': '#FDFAF9',\ - 'text_color': '#7C4616'}},\ - 'order' : {'org.iso.18013.5.1~family_name','org.iso.18013.5.1~given_name','org.iso.18013.5.1~document_number','org.iso.18013.5.1~issuing_country','org.iso.18013.5.1~issue_date','org.iso.18013.5.1~expiry_date','org.iso.18013.5.1~birth_date'}\ - }\ - }\ - },\ - 'vd13.1' : {\ - 'credential_issuer': '${mosip.certify.identifier}', \ - 'authorization_servers': {'${mosip.certify.authorization.url}'}, \ - 'credential_endpoint': '${mosip.certify.identifier}${server.servlet.path}/issuance/credential', \ - 'svg_template_endpoint': '${mosip.certify.domain.url}${server.servlet.path}/public/svg-template/5b9c2a12-810a-7388-2dc8-13ee7ad88bac', \ - 'display': {{'name': 'Mock Verifiable Credential', 'locale': 'en'}},\ - 'credential_configurations_supported' : { \ - 'MockVerifiableCredential_ldp' : {\ - 'format': 'ldp_vc',\ - 'scope' : 'mock_identity_vc_ldp',\ - 'cryptographic_binding_methods_supported': {'did:jwk'},\ - 'credential_signing_alg_values_supported': {'RsaSignature2018'},\ - 'proof_types_supported': {'jwt': {'proof_signing_alg_values_supported': {'RS256', 'PS256', 'ES256'}}},\ - 'credential_definition': {\ - 'type': {'VerifiableCredential','MockVerifiableCredential'},\ - 'credentialSubject': {\ - 'fullName': { 'display': {{'name': 'Full Name', 'locale': 'en' }}},\ - 'phone': { 'display': {{'name': 'Phone Number', 'locale': 'en' }}},\ - 'dateOfBirth': { 'display': {{'name': 'DOB', 'locale': 'en' }}},\ - 'gender': { 'display': {{'name': 'Gender', 'locale': 'en' }}},\ - 'email': { 'display': {{'name': 'Email Id', 'locale': 'en' }}},\ - 'region': { 'display': {{'name': 'Region', 'locale': 'en' }}},\ - 'province': { 'display': {{'name': 'Province', 'locale': 'en' }}},\ - 'UIN': { 'display': {{'name': 'UIN', 'locale': 'en' }}},\ - 'VID': { 'display': {{'name': 'VID', 'locale': 'en' }}},\ - 'postalCode': { 'display': {{'name': 'Postal Code', 'locale': 'en' }}}\ - }},\ - 'display': {{'name': 'Mock Verifiable Credential', \ - 'locale': 'en', \ - 'logo': {'url': '${mosipbox.public.url}/logo.png','alt_text': 'a square logo of a MOSIP'},\ - 'background_color': '#12107c',\ - 'background_image': { 'uri': 'https://${mosipbox.public.url}/inji/mosip-logo.png' }, \ - 'text_color': '#FFFFFF'}},\ - 'order' : {'fullName','phone','dateOfBirth','gender','email','region','province','UIN', 'VID', 'postalCode'}\ - },\ - "DrivingLicenseCredential":{\ - 'format': 'mso_mdoc',\ - 'doctype': 'org.iso.18013.5.1.mDL',\ - 'scope' : 'sample_vc_mdoc',\ - 'cryptographic_binding_methods_supported': {'cose_key'},\ - 'credential_signing_alg_values_supported': {'ES256'},\ - 'proof_types_supported': {'jwt': {'proof_signing_alg_values_supported': {'ES256'}}},\ - 'claims': {\ - 'org.iso.18013.5.1': {'given_name': {'display': {{'name': 'Given Name','locale': 'en'}}},'family_name': {'display': {{'name': 'Family Name','locale': 'en'}}},'issue_date': {'display': {{'name': 'Issue Date','locale': 'en'}}},'expiry_date': {'display': {{'name': 'Expiry Date','locale': 'en'}}},'birth_date': {'display': {{'name': 'Birth Date','locale': 'en'}}},'issuing_country': {'display': {{'name': 'Issuing Country','locale': 'en'}}},'document_number': {'display': {{'name': 'Document Number','locale': 'en'}}}}},\ - 'display': {{'name': 'Mobile Driving License Verifiable Credential', \ - 'locale': 'en', \ - 'background_image': { 'uri': 'https://sunbird.org/images/sunbird-logo-new.png' }, \ - 'logo': {'url': 'https://sunbird.org/images/sunbird-logo-new.png','alt_text': 'a square logo of a Sunbird Mobile Driving License'},\ - 'background_color': '#FDFAF9',\ - 'text_color': '#7C4616'}},\ - 'order' : {'org.iso.18013.5.1~family_name','org.iso.18013.5.1~given_name','org.iso.18013.5.1~document_number','org.iso.18013.5.1~issuing_country','org.iso.18013.5.1~issue_date','org.iso.18013.5.1~expiry_date','org.iso.18013.5.1~birth_date'}\ - }\ - }\ - }\ -} \ No newline at end of file diff --git a/docker-compose/docker-compose-certify/config/certify-sunbird-insurance.properties b/docker-compose/docker-compose-certify/config/certify-sunbird-insurance.properties deleted file mode 100644 index c94323e5..00000000 --- a/docker-compose/docker-compose-certify/config/certify-sunbird-insurance.properties +++ /dev/null @@ -1,164 +0,0 @@ -# ------------------------------------------- Integrations ------------------------------------------------------------ -mosip.certify.integration.scan-base-package=io.mosip.certify.sunbirdrc.integration -mosip.certify.integration.vci-plugin=SunbirdRCVCIssuancePlugin -mosip.certify.integration.audit-plugin=LoggerAuditService - -##--------------------sunbird registry related demo configuration-------------------------## - -mosip.certify.vciplugin.sunbird-rc.issue-credential-url=http://sunbird-registry:80/credential/credentials/issue -mosip.certify.vciplugin.sunbird-rc.supported-credential-types=HealthInsuranceCredential,LifeInsuranceCredential,InsuranceCredential -mosip.certify.vciplugin.sunbird-rc.credential-type.HealthInsuranceCredential.static-value-map.issuerId=did:web:challabeehyv.github.io:DID-Resolve:190d673a-0cfb-45f4-a8f4-5efaaaef0b4b -mosip.certify.vciplugin.sunbird-rc.credential-type.HealthInsuranceCredential.template-url=https://raw.githubusercontent.com/challabeehyv/mimoto-config/main/InsuranceConfig.json -mosip.certify.vciplugin.sunbird-rc.credential-type.HealthInsuranceCredential.registry-get-url=http://sunbird-registry:80/registry/api/v1/Insurance/ -mosip.certify.vciplugin.sunbird-rc.credential-type.HealthInsuranceCredential.cred-schema-id=did:schema:c45e2840-bf2a-440d-b4aa-52ff3e205f18 -mosip.certify.vciplugin.sunbird-rc.credential-type.HealthInsuranceCredential.cred-schema-version=1.0.0 -mosip.certify.vciplugin.sunbird-rc.credential-type.HealthInsuranceCredential.registry-search-url=http://sunbird-registry:80/registry/api/v1/Insurance/search - -mosip.certify.vciplugin.sunbird-rc.credential-type.LifeInsuranceCredential.static-value-map.issuerId=did:web:challabeehyv.github.io:DID-Resolve:190d673a-0cfb-45f4-a8f4-5efaaaef0b4b -mosip.certify.vciplugin.sunbird-rc.credential-type.LifeInsuranceCredential.template-url=https://raw.githubusercontent.com/challabeehyv/mimoto-config/main/InsuranceConfig.json -mosip.certify.vciplugin.sunbird-rc.credential-type.LifeInsuranceCredential.registry-get-url=http://sunbird-registry:80/registry/api/v1/Insurance/ -mosip.certify.vciplugin.sunbird-rc.credential-type.LifeInsuranceCredential.cred-schema-id=did:schema:c45e2840-bf2a-440d-b4aa-52ff3e205f18 -mosip.certify.vciplugin.sunbird-rc.credential-type.LifeInsuranceCredential.cred-schema-version=1.0.0 -mosip.certify.vciplugin.sunbird-rc.credential-type.LifeInsuranceCredential.registry-search-url=http://sunbird-registry:80/registry/api/v1/Insurance/search - - -mosip.certify.vciplugin.sunbird-rc.credential-type.InsuranceCredential.static-value-map.issuerId=did:web:challabeehyv.github.io:DID-Resolve:190d673a-0cfb-45f4-a8f4-5efaaaef0b4b -mosip.certify.vciplugin.sunbird-rc.credential-type.InsuranceCredential.template-url=https://raw.githubusercontent.com/challabeehyv/mimoto-config/main/InsuranceConfig.json -mosip.certify.vciplugin.sunbird-rc.credential-type.InsuranceCredential.registry-get-url=http://sunbird-registry:80/registry/api/v1/Insurance/ -mosip.certify.vciplugin.sunbird-rc.credential-type.InsuranceCredential.cred-schema-id=did:schema:c45e2840-bf2a-440d-b4aa-52ff3e205f18 -mosip.certify.vciplugin.sunbird-rc.credential-type.InsuranceCredential.cred-schema-version=1.0.0 -mosip.certify.vciplugin.sunbird-rc.credential-type.InsuranceCredential.registry-search-url=http://sunbird-registry:80/registry/api/v1/Insurance/search - - -mosip.certify.svg-templates=insurance-svg-template.json -mosip.certify.key-values={\ - 'latest' : {\ - 'credential_issuer': '${mosipbox.public.url}', \ - 'authorization_servers': {'${mosip.certify.authorization.url}'}, \ - 'credential_endpoint': '${mosipbox.public.url}${server.servlet.path}/issuance/credential', \ - 'display': {{'name': 'Insurance', 'locale': 'en'}},\ - 'credential_configurations_supported' : { \ - "InsuranceCredential" : {\ - 'format': 'ldp_vc',\ - 'scope' : 'sunbird_rc_insurance_vc_ldp',\ - 'cryptographic_binding_methods_supported': {'did:jwk'},\ - 'credential_signing_alg_values_supported': {'Ed25519Signature2020'},\ - 'proof_types_supported': {'jwt': {'proof_signing_alg_values_supported': {'RS256', 'PS256'}}},\ - 'credential_definition': {\ - 'type': {'VerifiableCredential','InsuranceCredential'},\ - 'credentialSubject': {\ - 'fullName': {'display': {{'name': 'Name','locale': 'en'}}}, \ - 'mobile': {'display': {{'name': 'Phone Number','locale': 'en'}}},\ - 'dob': {'display': {{'name': 'Date of Birth','locale': 'en'}}},\ - 'gender': {'display': {{'name': 'Gender','locale': 'en'}}},\ - 'benefits': {'display': {{'name': 'Benefits','locale': 'en'}}},\ - 'email': {'display': {{'name': 'Email Id','locale': 'en'}}},\ - 'policyIssuedOn': {'display': {{'name': 'Policy Issued On','locale': 'en'}}},\ - 'policyExpiresOn': {'display': {{'name': 'Policy Expires On','locale': 'en'}}},\ - 'policyName': {'display': {{'name': 'Policy Name','locale': 'en'}}},\ - 'policyNumber': {'display': {{'name': 'Policy Number','locale': 'en'}}}\ - }},\ - 'display': {{'name': 'Sunbird RC Insurance Verifiable Credential', \ - 'locale': 'en', \ - 'logo': {'url': 'https://sunbird.org/images/sunbird-logo-new.png','alt_text': 'a square logo of a Sunbird'},\ - 'background_color': '#FDFAF9',\ - 'background_image': { 'uri': 'https://sunbird.org/images/sunbird-logo-new.png' }, \ - 'text_color': '#7C4616'}},\ - 'order' : {'fullName','policyName','policyExpiresOn','policyIssuedOn','policyNumber','mobile','dob','gender','benefits','email'}\ - },\ - "LifeInsuranceCredential":{\ - 'format': 'ldp_vc',\ - 'scope' : 'life_insurance_vc_ldp',\ - 'cryptographic_binding_methods_supported': {'did:jwk'},\ - 'credential_signing_alg_values_supported': {'Ed25519Signature2020'},\ - 'proof_types_supported': {'jwt': {'proof_signing_alg_values_supported': {'RS256', 'ES256'}}},\ - 'credential_definition': {\ - 'type': {'VerifiableCredential'},\ - 'credentialSubject': {\ - 'fullName': {'display': {{'name': 'Name','locale': 'en'}}}, \ - 'mobile': {'display': {{'name': 'Phone Number','locale': 'en'}}},\ - 'dob': {'display': {{'name': 'Date of Birth','locale': 'en'}}},\ - 'gender': {'display': {{'name': 'Gender','locale': 'en'}}},\ - 'benefits': {'display': {{'name': 'Benefits','locale': 'en'}}},\ - 'email': {'display': {{'name': 'Email Id','locale': 'en'}}},\ - 'policyIssuedOn': {'display': {{'name': 'Policy Issued On','locale': 'en'}}},\ - 'policyExpiresOn': {'display': {{'name': 'Policy Expires On','locale': 'en'}}},\ - 'policyName': {'display': {{'name': 'Policy Name','locale': 'en'}}},\ - 'policyNumber': {'display': {{'name': 'Policy Number','locale': 'en'}}}\ - }},\ - 'display': {{'name': 'Life Insurance Verifiable Credential', \ - 'locale': 'en', \ - 'logo': {'url': 'https://sunbird.org/images/sunbird-logo-new.png','alt_text': 'a square logo of a Sunbird'},\ - 'background_image': { 'uri': 'https://sunbird.org/images/sunbird-logo-new.png' }, \ - 'background_color': '#FDFAF9',\ - 'background_image': { 'uri': 'https://sunbird.org/images/sunbird-logo-new.png' }, \ - 'text_color': '#7C4616'}},\ - 'order' : {'fullName','policyName','policyExpiresOn','policyIssuedOn','policyNumber','mobile','dob','gender','benefits','email'}\ - }}\ - },\ - 'vd13.1' : {\ - 'credential_issuer': '${mosipbox.public.url}', \ - 'authorization_servers': {'${mosip.certify.authorization.url}'}, \ - 'credential_endpoint': '${mosipbox.public.url}${server.servlet.path}/issuance/credential', \ - 'svg_template_endpoint': '${mosip.certify.domain.url}${server.servlet.path}/public/svg-template/5b9c2a12-810a-7388-2dc8-13ee7ad88bac', \ - 'display': {{'name': 'Insurance', 'locale': 'en'}},\ - 'credential_configurations_supported' : { \ - "InsuranceCredential" : {\ - 'format': 'ldp_vc',\ - 'scope' : 'sunbird_rc_insurance_vc_ldp',\ - 'cryptographic_binding_methods_supported': {'did:jwk'},\ - 'credential_signing_alg_values_supported': {'Ed25519Signature2020'},\ - 'proof_types_supported': {'jwt': {'proof_signing_alg_values_supported': {'RS256', 'PS256'}}},\ - 'credential_definition': {\ - 'type': {'VerifiableCredential','InsuranceCredential'},\ - 'credentialSubject': {\ - 'fullName': {'display': {{'name': 'Name','locale': 'en'}}}, \ - 'mobile': {'display': {{'name': 'Phone Number','locale': 'en'}}},\ - 'dob': {'display': {{'name': 'Date of Birth','locale': 'en'}}},\ - 'gender': {'display': {{'name': 'Gender','locale': 'en'}}},\ - 'benefits': {'display': {{'name': 'Benefits','locale': 'en'}}},\ - 'email': {'display': {{'name': 'Email Id','locale': 'en'}}},\ - 'policyIssuedOn': {'display': {{'name': 'Policy Issued On','locale': 'en'}}},\ - 'policyExpiresOn': {'display': {{'name': 'Policy Expires On','locale': 'en'}}},\ - 'policyName': {'display': {{'name': 'Policy Name','locale': 'en'}}},\ - 'policyNumber': {'display': {{'name': 'Policy Number','locale': 'en'}}}\ - }},\ - 'display': {{'name': 'Sunbird RC Insurance Verifiable Credential', \ - 'locale': 'en', \ - 'logo': {'url': 'https://sunbird.org/images/sunbird-logo-new.png','alt_text': 'a square logo of a Sunbird'},\ - 'background_color': '#FDFAF9',\ - 'background_image': { 'uri': 'https://sunbird.org/images/sunbird-logo-new.png' }, \ - 'text_color': '#7C4616'}},\ - 'order' : {'fullName','policyName','policyExpiresOn','policyIssuedOn','policyNumber','mobile','dob','gender','benefits','email'}\ - },\ - "LifeInsuranceCredential":{\ - 'format': 'ldp_vc',\ - 'scope' : 'life_insurance_vc_ldp',\ - 'cryptographic_binding_methods_supported': {'did:jwk'},\ - 'credential_signing_alg_values_supported': {'Ed25519Signature2020'},\ - 'proof_types_supported': {'jwt': {'proof_signing_alg_values_supported': {'RS256', 'ES256'}}},\ - 'credential_definition': {\ - 'type': {'VerifiableCredential'},\ - 'credentialSubject': {\ - 'fullName': {'display': {{'name': 'Name','locale': 'en'}}}, \ - 'mobile': {'display': {{'name': 'Phone Number','locale': 'en'}}},\ - 'dob': {'display': {{'name': 'Date of Birth','locale': 'en'}}},\ - 'gender': {'display': {{'name': 'Gender','locale': 'en'}}},\ - 'benefits': {'display': {{'name': 'Benefits','locale': 'en'}}},\ - 'email': {'display': {{'name': 'Email Id','locale': 'en'}}},\ - 'policyIssuedOn': {'display': {{'name': 'Policy Issued On','locale': 'en'}}},\ - 'policyExpiresOn': {'display': {{'name': 'Policy Expires On','locale': 'en'}}},\ - 'policyName': {'display': {{'name': 'Policy Name','locale': 'en'}}},\ - 'policyNumber': {'display': {{'name': 'Policy Number','locale': 'en'}}}\ - }},\ - 'display': {{'name': 'Life Insurance Verifiable Credential', \ - 'locale': 'en', \ - 'logo': {'url': 'https://sunbird.org/images/sunbird-logo-new.png','alt_text': 'a square logo of a Sunbird'},\ - 'background_image': { 'uri': 'https://sunbird.org/images/sunbird-logo-new.png' }, \ - 'background_color': '#FDFAF9',\ - 'background_image': { 'uri': 'https://sunbird.org/images/sunbird-logo-new.png' }, \ - 'text_color': '#7C4616'}},\ - 'order' : {'fullName','policyName','policyExpiresOn','policyIssuedOn','policyNumber','mobile','dob','gender','benefits','email'}\ - }}\ - }\ -} \ No newline at end of file diff --git a/docker-compose/docker-compose-certify/config/esignet-default.properties b/docker-compose/docker-compose-certify/config/esignet-default.properties deleted file mode 100644 index 99315c41..00000000 --- a/docker-compose/docker-compose-certify/config/esignet-default.properties +++ /dev/null @@ -1,404 +0,0 @@ -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this -# file, You can obtain one at https://mozilla.org/MPL/2.0/. - -# Follow properites have their values assigned via 'overrides' environment variables of config server docker. -# DO NOT define these in any of the property files. They must be passed as env variables. Refer to config-server -# helm chart: -# db.dbuser.password -# keycloak.external.url -# keycloak.internal.host -# keycloak.internal.url -# keycloak.admin.password -# mosip.auth.client.secret (convention: ..secret) -# mosip.ida.client.secret -# mosip.admin.client.secret -# mosip.reg.client.secret -# mosip.prereg.client.secret -# softhsm.kernel.pin -# softhsm-security-pin -# email.smtp.host -# email.smtp.username -# email.smtp.secret -# mosip.kernel.tokenid.uin.salt -# mosip.kernel.tokenid.partnercode.salt -# mosip.api.internal.url -# mosip.api.public.url - -server.port=8088 -server.servlet.path=/v1/esignet - -openapi.info.title=e-Signet Service -openapi.info.description=Rest Endpoints for operations related to e-Signet -openapi.info.version=1.0 -openapi.info.license.name=Mosip -openapi.info.license.url=https://docs.mosip.io/platform/license -mosipbox.public.url=http://localhost:${server.port} -openapi.service.server.url=${mosipbox.public.url}${server.servlet.path} -openapi.service.server.description=e-Signet Service -springdoc.swagger-ui.disable-swagger-default-url=true -spring.mvc.servlet.path=${server.servlet.path} - -#logging.level.org.springframework.web=DEBUG -#logging.level.org.springframework.security=DEBUG - -spring.messages.basename=messages -spring.messages.encoding=UTF-8 - -spring.main.allow-bean-definition-overriding=true - -## ------------------------------------------------- e-Signet ---------------------------------------------------------- -mosip.esignet.amr-acr-mapping-file-url=https://raw.githubusercontent.com/mosip/mosip-config/collab1/amr-acr-mapping.json -mosip.esignet.auth-txn-id-length=10 -mosip.esignet.supported-id-regex=\\S* -mosip.esignet.id-token-expire-seconds=3600 -mosip.esignet.access-token-expire-seconds=3600 -mosip.esignet.link-code-expire-in-secs=600 -mosip.esignet.generate-link-code.limit-per-transaction=10 -mosip.esignet.authentication-expire-in-secs=600 -mosip.esignet.supported-pkce-methods={'S256'} - -mosip.esignet.captcha.required.auth-factors={{'PWD'}} - -mosip.esignet.header-filter.paths-to-validate={'${server.servlet.path}/authorization/send-otp', \ - '${server.servlet.path}/authorization/authenticate', \ - '${server.servlet.path}/authorization/v2/authenticate', \ - '${server.servlet.path}/authorization/v3/authenticate', \ - '${server.servlet.path}/authorization/auth-code'} - -## ------------------------------------------ e-Signet binding --------------------------------------------------------- - -mosip.esignet.binding.salt-length=16 -mosip.esignet.binding.audience-id=esignet-binding -mosip.esignet.binding.key-expire-days=10 -mosip.esignet.binding.encrypt-binding-id=false - -## -------------------------------------- Authentication & Authorization ----------------------------------------------- - -mosip.esignet.security.auth.post-urls={} -mosip.esignet.security.auth.put-urls={} -mosip.esignet.security.auth.get-urls={} - -mosip.esignet.security.ignore-csrf-urls=${server.servlet.path}/client-mgmt/**,${server.servlet.path}/oidc/**,${server.servlet.path}/oauth/**,\ - ${server.servlet.path}/actuator/**,/favicon.ico,${server.servlet.path}/error,\ - ${server.servlet.path}/swagger-ui/**,${server.servlet.path}/v3/api-docs/**,\ - ${server.servlet.path}/vci/** - -mosip.esignet.security.ignore-auth-urls=${server.servlet.path}/csrf/**,${server.servlet.path}/authorization/**,\ - ${server.servlet.path}/linked-authorization/**,${server.servlet.path}/oidc/**,${server.servlet.path}/oauth/**,\ - ${server.servlet.path}/actuator/**,/favicon.ico,${server.servlet.path}/error,${server.servlet.path}/swagger-ui/**,\ - ${server.servlet.path}/v3/api-docs/**,${server.servlet.path}/client-mgmt/**,${server.servlet.path}/vci/** - -##------------------------------------------ Kafka configurations ------------------------------------------------------ -spring.kafka.bootstrap-servers=kafka:9092 -spring.kafka.consumer.group-id=esignet-consumer -spring.kafka.consumer.enable-auto-commit=true -#spring.kafka.listener.concurrency=1 - -mosip.esignet.kafka.linked-session.topic=esignet-linked -mosip.esignet.kafka.linked-auth-code.topic=esignet-consented - -# captcha validator -mosip.esignet.send-otp.captcha-required=false -mosip.esignet.captcha-validator.url=https://www.google.com/recaptcha/api/siteverify -mosip.esignet.captcha-validator.secret=secretkey -mosip.esignet.captcha-validator.site-key=sitekey - -mosip.esignet.authenticator.ida.otp-channels=email,phone - -#------------------------------- Mock IDA integration properties-------------------------------------------- -mosip.esignet.mock.authenticator.get-identity-url=http://mock-identity-system:8082/v1/mock-identity-system/identity -mosip.esignet.mock.authenticator.kyc-auth-url=http://mock-identity-system:8082/v1/mock-identity-system/kyc-auth -mosip.esignet.mock.authenticator.kyc-exchange-url=http://mock-identity-system:8082/v1/mock-identity-system/kyc-exchange -mosip.esignet.mock.authenticator.ida.otp-channels=${mosip.esignet.authenticator.ida.otp-channels} -mosip.esignet.mock.authenticator.send-otp=http://mock-identity-system:8082/v1/mock-identity-system/send-otp -mosip.esignet.mock.supported.bind-auth-factor-types={'WLA'} -mosip.esignet.mock.vciplugin.verification-method=${mosip.esignet.vci.authn.jwk-set-uri} - -## ------------------------------------------ oauth & openid supported values ------------------------------------------ - -## supported scopes -mosip.esignet.supported.credential.scopes={'sample_vc_ldp','mock_identity_vc_ldp','mosip_identity_vc_ldp','sunbird_rc_insurance_vc_ldp','health_insurance_identity_vc_ldp','life_insurance_vc_ldp'} -mosip.esignet.supported.authorize.scopes={'resident-service'} -mosip.esignet.supported.openid.scopes={'profile','email','phone'} -mosip.esignet.openid.scope.claims={'profile' : {'name','given_name','middle_name','preferred_username','picture','gender','birthdate','locale','nickname', 'family_name','zoneinfo', 'updated_at','address'},'email' : {'email','email_verified'}, 'phone' : {'phone_number','phone_number_verified'}} -mosip.esignet.credential.scope-resource-mapping={'sample_vc_ldp' : '${mosipbox.public.url}${server.servlet.path}/vci/credential','mock_identity_vc_ldp' : '${mosipbox.public.url}${server.servlet.path}/vci/credential','mosip_identity_vc_ldp' : '${mosipbox.public.url}${server.servlet.path}/vci/credential','sunbird_rc_insurance_vc_ldp' : '${mosipbox.public.url}${server.servlet.path}/vci/credential','life_insurance_vc_ldp' : '${mosipbox.public.url}${server.servlet.path}/vci/credential','health_insurance_identity_vc_ldp' : '${mosipbox.public.url}${server.servlet.path}/vci/credential' } -## supported authorization processing flow to be used, Currently only supports Authorization Code Flow. -mosip.esignet.supported.response.types={'code'} - -## Form of Authorization Grant presented to token endpoint -mosip.esignet.supported.grant.types={'authorization_code'} - -## specifies how the Authorization Server displays the authentication and consent user interface pages to the End-User -# page-The Authorization Server SHOULD display the authentication and consent UI consistent with a full User Agent page view. If the display parameter is not specified, this is the default display mode. -# popup-The Authorization Server SHOULD display the authentication and consent UI consistent with a popup User Agent window. The popup User Agent window should be of an appropriate size for a login-focused dialog and should not obscure the entire window that it is popping up over. -# touch-The Authorization Server SHOULD display the authentication and consent UI consistent with a device that leverages a touch interface. -# wap-The Authorization Server SHOULD display the authentication and consent UI consistent with a "feature phone" type display. -mosip.esignet.supported.ui.displays={'page','popup','touch','wap'} - -## specifies whether the Authorization Server prompts the End-User for reauthentication and consent -# none-The Authorization Server MUST NOT display any authentication or consent user interface pages. -# An error is returned if an End-User is not already authenticated or the Client does not have pre-configured consent -# for the requested Claims or does not fulfill other conditions for processing the request. -# The error code will typically be login_required, interaction_required, or another code defined in Section 3.1.2.6. -# This can be used as a method to check for existing authentication and/or consent. -# login-The Authorization Server SHOULD prompt the End-User for reauthentication. If it cannot reauthenticate the End-User, \ -# it MUST return an error, typically login_required. -# consent-The Authorization Server SHOULD prompt the End-User for consent before returning information to the Client. -# If it cannot obtain consent, it MUST return an error, typically consent_required. -# select_account-The Authorization Server SHOULD prompt the End-User to select a user account. This enables an End-User -# who has multiple accounts at the Authorization Server to select amongst the multiple accounts that they might have current -# sessions for. If it cannot obtain an account selection choice made by the End-User, it MUST return an error, -# typically account_selection_required. -mosip.esignet.supported.ui.prompts={'none','login','consent','select_account'} - -## Type of the client assertion -mosip.esignet.supported.client.assertion.types={'urn:ietf:params:oauth:client-assertion-type:jwt-bearer'} - -## Type of the client authentication methods for token endpoint -mosip.esignet.supported.client.auth.methods={'private_key_jwt'} - - -## ---------------------------------------- Cache configuration -------------------------------------------------------- - -mosip.esignet.cache.secure.individual-id=false -mosip.esignet.cache.store.individual-id=true -mosip.esignet.cache.security.secretkey.reference-id=TRANSACTION_CACHE -mosip.esignet.cache.security.algorithm-name=AES/ECB/PKCS5Padding - -mosip.esignet.cache.names=clientdetails,preauth,authenticated,authcodegenerated,userinfo,linkcodegenerated,linked,linkedcode,linkedauth,consented,authtokens,bindingtransaction,vcissuance,apiRateLimit,blocked - -spring.cache.type=redis -spring.cache.cache-names=${mosip.esignet.cache.names} -spring.redis.host=cache -spring.redis.port=6379 -spring.redis.password=redis -management.health.redis.enabled=false - -#spring.cache.type=simple -mosip.esignet.cache.key.hash.algorithm=SHA3-256 -mosip.esignet.cache.size={'clientdetails' : 200, 'preauth': 200, 'authenticated': 200, 'authcodegenerated': 200, 'userinfo': 200, \ - 'linkcodegenerated' : 500, 'linked': 200 , 'linkedcode': 200, 'linkedauth' : 200 , 'consented' :200, 'authtokens': 2, 'bindingtransaction': 1500, 'vcissuance' : 2000, 'blocked': 300, 'apiRateLimit': 180} -mosip.esignet.cache.expire-in-seconds={'clientdetails' : 86400, 'preauth': 1000,'authenticated': ${mosip.esignet.authentication-expire-in-secs},'authenticated': 1000, 'authcodegenerated': 600, \ - 'userinfo': ${mosip.esignet.access-token-expire-seconds}, 'linkcodegenerated' : ${mosip.esignet.link-code-expire-in-secs}, \ - 'linked': 600 , 'linkedcode': ${mosip.esignet.link-code-expire-in-secs}, 'linkedauth' : ${mosip.esignet.authentication-expire-in-secs}, 'consented': 600, \ - 'authtokens': 28800, 'bindingtransaction': 600, 'vcissuance': ${mosip.esignet.access-token-expire-seconds}, 'apiRateLimit': 180, 'blocked': 300 } - -## ------------------------------------------ Discovery openid-configuration ------------------------------------------- - -mosip.esignet.domain.url=http://localhost:8088 -mosip.esignet.discovery.issuer-id=${mosip.esignet.domain.url}${server.servlet.path} - -# This property holds ./wellknown/jwks.json URL, -# for local deployments without esignet-ui nginx change the value to ${mosip.esignet.domain.url}${server.servlet.path}/oauth/.well-known/jwks.json -mosip.esignet.jwks-uri=${mosip.esignet.domain.url}/.well-known/jwks.json - -mosip.esignet.token.endpoint=${mosip.esignet.domain.url}${server.servlet.path}/oauth/v2/token - -mosip.esignet.oauth.key-values={'issuer': '${mosip.esignet.domain.url}' ,\ - \ 'authorization_endpoint': '${mosip.esignet.domain.url}/authorize' , \ - \ 'token_endpoint': '${mosip.esignet.token.endpoint}' , \ - \ 'jwks_uri' : '${mosip.esignet.jwks-uri}' , \ - \ 'token_endpoint_auth_methods_supported' : ${mosip.esignet.supported.client.auth.methods}, \ - \ 'token_endpoint_auth_signing_alg_values_supported' : {'RS256'},\ - \ 'scopes_supported' : ${mosip.esignet.supported.openid.scopes}, \ - \ 'response_modes_supported' : { 'query' }, \ - \ 'grant_types_supported' : ${mosip.esignet.supported.grant.types},\ - \ 'response_types_supported' : ${mosip.esignet.supported.response.types}} - -mosip.esignet.discovery.key-values={'issuer': '${mosip.esignet.domain.url}' ,\ - \ 'authorization_endpoint': '${mosip.esignet.domain.url}/authorize' , \ - \ 'token_endpoint': '${mosip.esignet.token.endpoint}' ,\ - \ 'jwks_uri' : '${mosip.esignet.jwks-uri}' , \ - \ 'userinfo_endpoint' : '${mosip.esignet.domain.url}${server.servlet.path}/oidc/userinfo' ,\ - \ 'scopes_supported' : ${mosip.esignet.supported.openid.scopes}, \ - \ 'response_types_supported' : ${mosip.esignet.supported.response.types}, \ - \ 'response_modes_supported' : { 'query' }, \ - \ 'token_endpoint_auth_methods_supported' : ${mosip.esignet.supported.client.auth.methods}, \ - \ 'token_endpoint_auth_signing_alg_values_supported' : {'RS256'}, \ - \ 'userinfo_signing_alg_values_supported' : {'RS256'}, \ - \ 'userinfo_encryption_alg_values_supported' : {'RSAXXXXX'},\ - \ 'userinfo_encryption_enc_values_supported' : {'A128GCM'}, \ - \ 'id_token_signing_alg_values_supported' : {'RS256'}, \ - \ 'claim_types_supported': {'normal'}, \ - \ 'claims_parameter_supported' : true, \ - \ 'display_values_supported' : ${mosip.esignet.supported.ui.displays}, \ - \ 'subject_types_supported' : { 'pairwise' }, \ - \ 'claims_supported' : {'name','address','gender','birthdate','picture','email','phone_number','individual_id'}, \ - \ 'acr_values_supported' : {'mosip:idp:acr:static-code', 'mosip:idp:acr:generated-code', 'mosip:idp:acr:linked-wallet', 'mosip:idp:acr:biometrics'},\ - \ 'request_parameter_supported' : false } - -##----------------------------------------- Database properties -------------------------------------------------------- - -mosip.esignet.database.hostname=database -mosip.esignet.database.port=5432 -spring.datasource.url=jdbc:postgresql://${mosip.esignet.database.hostname}:${mosip.esignet.database.port}/mosip_esignet?currentSchema=esignet -spring.datasource.username=postgres -spring.datasource.password=postgres - -spring.jpa.database-platform=org.hibernate.dialect.PostgreSQL95Dialect -spring.jpa.show-sql=false -spring.jpa.hibernate.ddl-auto=none -spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true - -#------------------------------------ Key-manager specific properties -------------------------------------------------- -#Crypto asymmetric algorithm name -mosip.kernel.crypto.asymmetric-algorithm-name=RSA/ECB/OAEPWITHSHA-256ANDMGF1PADDING -#Crypto symmetric algorithm name -mosip.kernel.crypto.symmetric-algorithm-name=AES/GCM/PKCS5Padding -#Keygenerator asymmetric algorithm name -mosip.kernel.keygenerator.asymmetric-algorithm-name=RSA -#Keygenerator symmetric algorithm name -mosip.kernel.keygenerator.symmetric-algorithm-name=AES -#Asymmetric algorithm key length -mosip.kernel.keygenerator.asymmetric-key-length=2048 -#Symmetric algorithm key length -mosip.kernel.keygenerator.symmetric-key-length=256 -#Encrypted data and encrypted symmetric key separator -mosip.kernel.data-key-splitter=#KEY_SPLITTER# -#GCM tag length -mosip.kernel.crypto.gcm-tag-length=128 -#Hash algo name -mosip.kernel.crypto.hash-algorithm-name=PBKDF2WithHmacSHA512 -#Symmtric key length used in hash -mosip.kernel.crypto.hash-symmetric-key-length=256 -#No of iterations in hash -mosip.kernel.crypto.hash-iteration=100000 -#Sign algo name -mosip.kernel.crypto.sign-algorithm-name=RS256 -#Certificate Sign algo name -mosip.kernel.certificate.sign.algorithm=SHA256withRSA - -mosip.kernel.keymanager.hsm.config-path=ESIGNET_PKCS12/local.p12 -mosip.kernel.keymanager.hsm.keystore-type=PKCS12 -mosip.kernel.keymanager.hsm.keystore-pass=local - -#Type of keystore, Supported Types: PKCS11, PKCS12, Offline, JCE -#mosip.kernel.keymanager.hsm.keystore-type=PKCS11 -# For PKCS11 provide Path of config file. -# For PKCS12 keystore type provide the p12/pfx file path. P12 file will be created internally so provide only file path & file name. -# For Offline & JCE property can be left blank, specified value will be ignored. -#mosip.kernel.keymanager.hsm.config-path=/config/softhsm-application.conf -# Passkey of keystore for PKCS11, PKCS12 -# For Offline & JCE proer can be left blank. JCE password use other JCE specific properties. -#mosip.kernel.keymanager.hsm.keystore-pass=${softhsm.esignet.mock.security.pin} - -mosip.esignet.supported-formats={'OTP': 'alpha-numeric', 'PWD': 'alpha-numeric', 'BIO': 'encoded-json', 'WLA': 'jwt', 'PIN': 'number', 'KBA': 'base64url-encoded-json'} - - -mosip.kernel.keymanager.certificate.default.common-name=www.example.com -mosip.kernel.keymanager.certificate.default.organizational-unit=EXAMPLE-CENTER -mosip.kernel.keymanager.certificate.default.organization=IIITB -mosip.kernel.keymanager.certificate.default.location=BANGALORE -mosip.kernel.keymanager.certificate.default.state=KA -mosip.kernel.keymanager.certificate.default.country=IN - -mosip.kernel.keymanager.softhsm.certificate.common-name=www.example.com -mosip.kernel.keymanager.softhsm.certificate.organizational-unit=Example Unit -mosip.kernel.keymanager.softhsm.certificate.organization=IIITB -mosip.kernel.keymanager.softhsm.certificate.country=IN - -# Application Id for PMS master key. -mosip.kernel.partner.sign.masterkey.application.id=PMS -mosip.kernel.partner.allowed.domains=DEVICE - -mosip.kernel.keymanager-service-validate-url=https://${mosip.hostname}/keymanager/validate -mosip.kernel.keymanager.jwtsign.validate.json=false -mosip.keymanager.dao.enabled=false -crypto.PrependThumbprint.enable=true - -mosip.kernel.keymgr.hsm.health.check.enabled=true -mosip.kernel.keymgr.hsm.health.key.app-id=OIDC_SERVICE -mosip.kernel.keymgr.hsm.healthkey.ref-id=TRANSACTION_CACHE - -mosip.kernel.keymgr.hsm.health.check.encrypt=true - -## -------------------------------------------- IDP-UI config ---------------------------------------------------------- -# NOTE: -# 1. linked-transaction-expire-in-secs value should be a sum of mosip.esignet.authentication-expire-in-secs and linked cache expire in seconds under mosip.esignet.cache.expire-in-seconds property -# 2. A new Qrcode will be autogenerated before the expiry of current qr-code, and the time difference in seconds for the same is defined in wallet.qr-code-buffer-in-secs property - -# mosip.esignet.ui.wallet.config={{'wallet.name': 'Inji Mobile App', 'wallet.logo-url': 'https://www.mosip.io/images/logo.png', 'wallet.download-uri': '#', \ -# 'wallet.deep-link-uri': 'inji://landing-page-name?linkCode=LINK_CODE&linkExpireDateTime=LINK_EXPIRE_DT' },{'wallet.name': 'Inji Mobile App1', 'wallet.logo-url': 'inji_logo.png', 'wallet.download-uri': '#', \ -# 'wallet.deep-link-uri': 'inji://landing-page-name?linkCode=LINK_CODE&linkExpireDateTime=LINK_EXPIRE_DT' }} - -# mosip.esignet.ui.wallet.config={'wallet.name': 'KBA', 'wallet.logo-url': 'inji_logo.png', "url": "https://sunbird.org/images/sunbird-logo-new.png"} - -# mosip.esignet.ui.wallet.config={{'wallet.name': 'KBA', 'wallet.logo-url': 'inji_logo.png', 'wallet.download-uri': '#', \ -# 'wallet.deep-link-uri': 'http://localhost:3001', "url": "https://sunbird.org/images/sunbird-logo-new.png" }} - -# mosip.esignet.ui.config.key-values={'sbi.env': 'Developer', 'sbi.timeout.DISC': 30, \ -# 'sbi.timeout.DINFO': 30, 'sbi.timeout.CAPTURE': 30, 'sbi.capture.count.face': 1, 'sbi.capture.count.finger': 1, \ -# 'sbi.capture.count.iris': 1, 'sbi.capture.score.face': 70, 'sbi.capture.score.finger':70, 'sbi.capture.score.iris':70, \ -# 'resend.otp.delay.secs': 120, 'send.otp.channels' : '${mosip.esignet.authenticator.ida.otp-channels}', \ -# 'captcha.sitekey' : '${mosip.esignet.captcha-validator.site-key}', 'captcha.enable' : '', \ -# 'auth.txnid.length' : '${mosip.esignet.auth-txn-id-length}', 'consent.screen.timeout-in-secs':${mosip.esignet.authentication-expire-in-secs}, \ -# 'consent.screen.timeout-buffer-in-secs': 5, 'linked-transaction-expire-in-secs': 120, 'sbi.port.range': 4501-4600, \ -# 'sbi.bio.subtypes.iris': 'UNKNOWN', 'sbi.bio.subtypes.finger': 'UNKNOWN', 'wallet.qr-code-buffer-in-secs': 10, 'otp.length': 6, \ -# 'password.regex': '', 'wallet.config': ${mosip.esignet.ui.wallet.config} } - - -mosip.esignet.ui.wallet.config={{'wallet.name': 'Inji', 'wallet.logo-url': 'inji_logo.png', 'wallet.download-uri': '#', \ - 'wallet.deep-link-uri': 'inji://landing-page-name?linkCode=LINK_CODE&linkExpireDateTime=LINK_EXPIRE_DT' }} - -mosip.esignet.ui.signup.config={'signup.banner': true, 'signup.url': 'http://localhost:3000/signup'} - -mosip.esignet.ui.forgot-password.config={'forgot-password': true, 'forgot-password.url': 'http://localhost:3000/forgot-password'} - -mosip.esignet.authenticator.default.auth-factor.kba.individual-id-field=policyNumber - -mosip.esignet.authenticator.default.auth-factor.kba.field-details={{"id":"policyNumber", "type":"text", "format":"", "maxLength": 50, "regex": "^[0-9\-]*$"},{"id":"fullName", "type":"text", "format":"", "maxLength": 50, "regex": "^[A-Za-z\s.0-9]+$"},{"id":"dob", "type":"date", "format":"dd/mm/yyyy"}} - - -mosip.esignet.ui.config.key-values={'sbi.env': 'Developer', 'sbi.timeout.DISC': 30, \ - 'sbi.timeout.DINFO': 30, 'sbi.timeout.CAPTURE': 30, 'sbi.capture.count.face': 1, 'sbi.capture.count.finger': 2, \ - 'sbi.capture.count.iris': 1, 'sbi.capture.score.face': 70, 'sbi.capture.score.finger':70, 'sbi.capture.score.iris':70, \ - 'send.otp.channels':'email,phone', 'consent.screen.timeout-in-secs':${mosip.esignet.authentication-expire-in-secs}, \ - 'consent.screen.timeout-buffer-in-secs': 5, 'sbi.port.range': 4501-4600, 'sbi.bio.subtypes.iris': 'UNKNOWN', 'sbi.bio.subtypes.finger': 'UNKNOWN', \ - 'resend.otp.delay.secs': 120, 'captcha.enable': '', 'captcha.sitekey': '6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI', \ - 'linked-transaction-expire-in-secs': 120, 'wallet.qr-code-buffer-in-secs': 10, 'auth.txnid.length': 10, \ - 'otp.length': 6, 'password.regex': '^.{8,20}$', \ 'password.max-length': 20, \ 'username.regex': '^[1-9][0-9]{7,8}$',\ 'username.prefix': '+855', \ - 'username.postfix': '', \ 'username.max-length': 9, \ 'username.input-type': 'number', \ 'wallet.config': ${mosip.esignet.ui.wallet.config},\ - 'signup.config': ${mosip.esignet.ui.signup.config}, \ - 'forgot-password.config': ${mosip.esignet.ui.forgot-password.config}, \ - 'auth.factor.kba.individual-id-field' : 'policyNumber',\ - 'auth.factor.kba.field-details':${mosip.esignet.authenticator.default.auth-factor.kba.field-details}} - -## ---------------------------------------------- VCI ------------------------------------------------------------------ -mosip.esignet.vci.identifier=${mosip.esignet.domain.url} -mosip.esignet.vci.authn.filter-urls={ '${server.servlet.path}/vci/credential' } -mosip.esignet.vci.authn.issuer-uri=${mosip.esignet.domain.url}${server.servlet.path} -mosip.esignet.vci.authn.jwk-set-uri=${mosip.esignet.domain.url}${server.servlet.path}/oauth/.well-known/jwks.json -mosip.esignet.vci.authn.allowed-audiences={ '${mosip.esignet.domain.url}${server.servlet.path}/vci/credential' } - -##change this to your value -mosip.esignet.cnonce-expire-seconds=1000 -mosip.esignet.vci.supported.jwt-proof-alg={'RS256','PS256','ES256'} - - -## -------------------------------------------- Others ---------------------------------------------------------- - -# Auth challenge type & format mapping. Auth challenge length validations for each auth factor type. -mosip.esignet.auth-challenge.OTP.format=alpha-numeric -mosip.esignet.auth-challenge.OTP.min-length=6 -mosip.esignet.auth-challenge.OTP.max-length=6 - -mosip.esignet.auth-challenge.PWD.format=alpha-numeric -mosip.esignet.auth-challenge.PWD.min-length=8 -mosip.esignet.auth-challenge.PWD.max-length=30 - -mosip.esignet.auth-challenge.BIO.format=encoded-json -mosip.esignet.auth-challenge.BIO.min-length=5000 -mosip.esignet.auth-challenge.BIO.max-length=300000 - -mosip.esignet.auth-challenge.WLA.format=jwt -mosip.esignet.auth-challenge.WLA.min-length=100 -mosip.esignet.auth-challenge.WLA.max-length=800 - -mosip.esignet.auth-challenge.KBA.format=base64url-encoded-json -mosip.esignet.auth-challenge.KBA.min-length=50 -mosip.esignet.auth-challenge.KBA.max-length=500 - -mosip.esignet.auth-challenge.PIN.format=number -mosip.esignet.auth-challenge.PIN.min-length=4 -mosip.esignet.auth-challenge.PIN.max-length=4 diff --git a/docker-compose/docker-compose-certify/config/esignet-mock-identity.properties b/docker-compose/docker-compose-certify/config/esignet-mock-identity.properties deleted file mode 100644 index c8240441..00000000 --- a/docker-compose/docker-compose-certify/config/esignet-mock-identity.properties +++ /dev/null @@ -1,17 +0,0 @@ -## ------------------------------------------- Integrations ------------------------------------------------------------ - - mosip.esignet.integration.scan-base-package=io.mosip.esignet.mock.integration - mosip.esignet.integration.binding-validator=BindingValidatorServiceImpl - mosip.esignet.integration.authenticator=MockAuthenticationService - mosip.esignet.integration.key-binder=MockKeyBindingWrapperService - mosip.esignet.integration.audit-plugin=LoggerAuditService - mosip.esignet.integration.captcha-validator=GoogleRecaptchaValidatorService - mosip.esignet.integration.vci-plugin=MockVCIssuancePlugin - -mosip.esignet.vci.key-values={} -mosip.esignet.captcha.required= -mosip.esignet.send-otp.attempts=30 -mosip.esignet.authenticate.attempts=30 -mosip.esignet.send-otp.invocation-gap-secs=10 -mosip.esignet.authenticate.invocation-gap-secs=50 - diff --git a/docker-compose/docker-compose-certify/config/esignet-sunbird-insurance.properties b/docker-compose/docker-compose-certify/config/esignet-sunbird-insurance.properties deleted file mode 100644 index 0b5328bf..00000000 --- a/docker-compose/docker-compose-certify/config/esignet-sunbird-insurance.properties +++ /dev/null @@ -1,42 +0,0 @@ - -# ------------------------------------------- Integrations ------------------------------------------------------------ -mosip.esignet.integration.scan-base-package=io.mosip.esignet.sunbirdrc.integration -mosip.esignet.integration.authenticator=SunbirdRCAuthenticationService -# this is a temporary workaround to circumvent eSignet crash, will get removed once eSignet removes VCI -mosip.esignet.integration.vci-plugin=MockVCIssuancePlugin -mosip.esignet.integration.key-binder=MockKeyBindingWrapperService -mosip.esignet.integration.audit-plugin=LoggerAuditService -mosip.esignet.integration.captcha-validator=GoogleRecaptchaValidatorService -mosip.esignet.captcha.required= -##--------------------sunbird registry related demo configuration-------------------------## -mosip.esignet.authenticator.sunbird-rc.auth-factor.kba.individual-id-field=${mosip.esignet.authenticator.default.auth-factor.kba.individual-id-field} -mosip.esignet.authenticator.sunbird-rc.auth-factor.kba.field-details=${mosip.esignet.authenticator.default.auth-factor.kba.field-details} -mosip.esignet.authenticator.sunbird-rc.auth-factor.kba.registry-search-url=http://sunbird-registry:80/registry/api/v1/Insurance/search -mosip.esignet.authenticator.sunbird-rc.kba.entity-id-field=osid - - -mosip.esignet.vciplugin.sunbird-rc.issue-credential-url=http://sunbird-registry:80/credential/credentials/issue -mosip.esignet.vciplugin.sunbird-rc.supported-credential-types=HealthInsuranceCredential,LifeInsuranceCredential,InsuranceCredential -mosip.esignet.vciplugin.sunbird-rc.credential-type.HealthInsuranceCredential.static-value-map.issuerId=did:web:challabeehyv.github.io:DID-Resolve:190d673a-0cfb-45f4-a8f4-5efaaaef0b4b -mosip.esignet.vciplugin.sunbird-rc.credential-type.HealthInsuranceCredential.template-url=https://raw.githubusercontent.com/challabeehyv/mimoto-config/main/InsuranceConfig.json -mosip.esignet.vciplugin.sunbird-rc.credential-type.HealthInsuranceCredential.registry-get-url=http://sunbird-registry:80/registry/api/v1/Insurance/ -mosip.esignet.vciplugin.sunbird-rc.credential-type.HealthInsuranceCredential.cred-schema-id=did:schema:c45e2840-bf2a-440d-b4aa-52ff3e205f18 -mosip.esignet.vciplugin.sunbird-rc.credential-type.HealthInsuranceCredential.cred-schema-version=1.0.0 -mosip.esignet.vciplugin.sunbird-rc.credential-type.HealthInsuranceCredential.registry-search-url=http://sunbird-registry:80/registry/api/v1/Insurance/search - -mosip.esignet.vciplugin.sunbird-rc.credential-type.LifeInsuranceCredential.static-value-map.issuerId=did:web:challabeehyv.github.io:DID-Resolve:190d673a-0cfb-45f4-a8f4-5efaaaef0b4b -mosip.esignet.vciplugin.sunbird-rc.credential-type.LifeInsuranceCredential.template-url=https://raw.githubusercontent.com/challabeehyv/mimoto-config/main/InsuranceConfig.json -mosip.esignet.vciplugin.sunbird-rc.credential-type.LifeInsuranceCredential.registry-get-url=http://sunbird-registry:80/registry/api/v1/Insurance/ -mosip.esignet.vciplugin.sunbird-rc.credential-type.LifeInsuranceCredential.cred-schema-id=did:schema:c45e2840-bf2a-440d-b4aa-52ff3e205f18 -mosip.esignet.vciplugin.sunbird-rc.credential-type.LifeInsuranceCredential.cred-schema-version=1.0.0 -mosip.esignet.vciplugin.sunbird-rc.credential-type.LifeInsuranceCredential.registry-search-url=http://sunbird-registry:80/registry/api/v1/Insurance/search - - -mosip.esignet.vciplugin.sunbird-rc.credential-type.InsuranceCredential.static-value-map.issuerId=did:web:challabeehyv.github.io:DID-Resolve:190d673a-0cfb-45f4-a8f4-5efaaaef0b4b -mosip.esignet.vciplugin.sunbird-rc.credential-type.InsuranceCredential.template-url=https://raw.githubusercontent.com/challabeehyv/mimoto-config/main/InsuranceConfig.json -mosip.esignet.vciplugin.sunbird-rc.credential-type.InsuranceCredential.registry-get-url=http://sunbird-registry:80/registry/api/v1/Insurance/ -mosip.esignet.vciplugin.sunbird-rc.credential-type.InsuranceCredential.cred-schema-id=did:schema:c45e2840-bf2a-440d-b4aa-52ff3e205f18 -mosip.esignet.vciplugin.sunbird-rc.credential-type.InsuranceCredential.cred-schema-version=1.0.0 -mosip.esignet.vciplugin.sunbird-rc.credential-type.InsuranceCredential.registry-search-url=http://sunbird-registry:80/registry/api/v1/Insurance/search - -mosip.esignet.vci.key-values={} diff --git a/docker-compose/docker-compose-certify/config/insurance-svg-template.json b/docker-compose/docker-compose-certify/config/insurance-svg-template.json deleted file mode 100644 index effea24c..00000000 --- a/docker-compose/docker-compose-certify/config/insurance-svg-template.json +++ /dev/null @@ -1,6 +0,0 @@ -[ - { - "id": "5b9c2a12-810a-7388-2dc8-13ee7ad88bac", - "content": "\n \n \n \n \n \n \n \n \n \n \n \n \n\n \n \n \n\n \n \n \n \n \n \n \n \n \n \n \n {{credentialSubject/policyName}}\n \n \n {{credentialSubject/policyNumber}}\n \n \n\n \n \n \n Full Name\n \n {{credentialSubject/fullName}}\n \n \n \n\n \n \n\n Phone Number\n \n {{credentialSubject/mobile}}\n \n Gender\n \n {{credentialSubject/gender}}\n \n \n\n \n \n\n Email\n \n {{credentialSubject/email}}\n \n \n\n \n \n \n Policy Issued On\n \n {{credentialSubject/policyIssuedOn}}\n \n Policy Expires On\n \n {{credentialSubject/policyExpiresOn}}\n \n Benefits\n \n \n {{credentialSubject/benefitsLine1}}\n {{credentialSubject/benefitsLine2}}\n \n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n Status\n \n \n Valid\n \n \n \n \n \n \n \n \n\n" - } -] \ No newline at end of file diff --git a/docker-compose/docker-compose-certify/config/mock-identity-system-default.properties b/docker-compose/docker-compose-certify/config/mock-identity-system-default.properties deleted file mode 100644 index b641b2c5..00000000 --- a/docker-compose/docker-compose-certify/config/mock-identity-system-default.properties +++ /dev/null @@ -1,145 +0,0 @@ -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this -# file, You can obtain one at https://mozilla.org/MPL/2.0/. - -# Follow properites have their values assigned via 'overrides' environment variables of config server docker. -# DO NOT define these in any of the property files. They must be passed as env variables. Refer to config-server -# helm chart: -# db.dbuser.password -# keycloak.external.url -# keycloak.internal.host -# keycloak.internal.url -# keycloak.admin.password -# mosip.auth.client.secret (convention: ..secret) -# mosip.ida.client.secret -# mosip.admin.client.secret -# mosip.reg.client.secret -# mosip.prereg.client.secret -# softhsm.kernel.pin -# softhsm-security-pin -# email.smtp.host -# email.smtp.username -# email.smtp.secret -# mosip.kernel.tokenid.uin.salt -# mosip.kernel.tokenid.partnercode.salt -# mosip.api.internal.url -# mosip.api.public.url - - -spring.main.allow-bean-definition-overriding=true - -server.port=8082 -#disabling health check so that client doesnt try to load properties from sprint config server every -# 5 minutes (should not be done in production) -health.config.enabled=false -server.servlet.context-path=/v1/mock-identity-system -management.security.enable=false -management.endpoint.health.show-details=always -management.endpoints.web.exposure.include=info,health,refresh,mappings -management.endpoint.metrics.enabled=true -management.endpoint.prometheus.enabled=true -management.metrics.export.prometheus.enabled=true - -openapi.info.title=${spring.application.name} -openapi.info.description=${spring.application.name} -openapi.info.version=1.0 -openapi.info.license.name=Mosip -openapi.info.license.url=https://docs.mosip.io/platform/license -mosipbox.public.url=http://localhost:${server.port} -openapi.service.servers[0].url=${mosipbox.public.url}${server.servlet.context-path} -openapi.service.servers[0].description=${spring.application.name} -openapi.group.name=${openapi.info.title} -openapi.group.paths[0]=/** -springdoc.swagger-ui.disable-swagger-default-url=true -springdoc.swagger-ui.tagsSorter=alpha -springdoc.swagger-ui.operationsSorter=alpha - -##----------------------------------------- Database properties -------------------------------------------------------- - -mosip.mockidentitysystem.database.hostname=database -mosip.mockidentitysystem.database.port=5432 -db.dbuser.password=postgres - -spring.datasource.url=jdbc:postgresql://${mosip.mockidentitysystem.database.hostname}:${mosip.mockidentitysystem.database.port}/mosip_mockidentitysystem?currentSchema=mockidentitysystem -spring.datasource.username=postgres -spring.datasource.password=${db.dbuser.password} - -#------------------------------------ Key-manager specific properties -------------------------------------------------- -#Crypto asymmetric algorithm name -mosip.kernel.crypto.asymmetric-algorithm-name=RSA/ECB/OAEPWITHSHA-256ANDMGF1PADDING -#Crypto symmetric algorithm name -mosip.kernel.crypto.symmetric-algorithm-name=AES/GCM/PKCS5Padding -#Keygenerator asymmetric algorithm name -mosip.kernel.keygenerator.asymmetric-algorithm-name=RSA -#Keygenerator symmetric algorithm name -mosip.kernel.keygenerator.symmetric-algorithm-name=AES -#Asymmetric algorithm key length -mosip.kernel.keygenerator.asymmetric-key-length=2048 -#Symmetric algorithm key length -mosip.kernel.keygenerator.symmetric-key-length=256 -#Encrypted data and encrypted symmetric key separator -mosip.kernel.data-key-splitter=#KEY_SPLITTER# -#GCM tag length -mosip.kernel.crypto.gcm-tag-length=128 -#Hash algo name -mosip.kernel.crypto.hash-algorithm-name=PBKDF2WithHmacSHA512 -#Symmtric key length used in hash -mosip.kernel.crypto.hash-symmetric-key-length=256 -#No of iterations in hash -mosip.kernel.crypto.hash-iteration=100000 -#Sign algo name -mosip.kernel.crypto.sign-algorithm-name=RS256 -#Certificate Sign algo name -mosip.kernel.certificate.sign.algorithm=SHA256withRSA - -mosip.kernel.keymanager.hsm.config-path=local.p12 -mosip.kernel.keymanager.hsm.keystore-type=PKCS12 -mosip.kernel.keymanager.hsm.keystore-pass=local - -#Type of keystore, Supported Types: PKCS11, PKCS12, Offline, JCE -#mosip.kernel.keymanager.hsm.keystore-type=PKCS11 -# For PKCS11 provide Path of config file. -# For PKCS12 keystore type provide the p12/pfx file path. P12 file will be created internally so provide only file path & file name. -# For Offline & JCE property can be left blank, specified value will be ignored. -#mosip.kernel.keymanager.hsm.config-path=/config/softhsm-application.conf -# Passkey of keystore for PKCS11, PKCS12 -# For Offline & JCE proer can be left blank. JCE password use other JCE specific properties. -#mosip.kernel.keymanager.hsm.keystore-pass=${softhsm.mock.identity.system.security.pin} - -mosip.kernel.keymanager.certificate.default.common-name=www.example.com -mosip.kernel.keymanager.certificate.default.organizational-unit=EXAMPLE-CENTER -mosip.kernel.keymanager.certificate.default.organization=IIITB -mosip.kernel.keymanager.certificate.default.location=BANGALORE -mosip.kernel.keymanager.certificate.default.state=KA -mosip.kernel.keymanager.certificate.default.country=IN - -mosip.kernel.keymanager.softhsm.certificate.common-name=www.example.com -mosip.kernel.keymanager.softhsm.certificate.organizational-unit=Example Unit -mosip.kernel.keymanager.softhsm.certificate.organization=IIITB -mosip.kernel.keymanager.softhsm.certificate.country=IN - -# Application Id for PMS master key. -mosip.kernel.partner.sign.masterkey.application.id=PMS -mosip.kernel.partner.allowed.domains=DEVICE - -mosip.kernel.keymanager-service-validate-url=https://${mosip.hostname}/keymanager/validate -mosip.kernel.keymanager.jwtsign.validate.json=false -mosip.keymanager.dao.enabled=false -crypto.PrependThumbprint.enable=true - -spring.jpa.database-platform=org.hibernate.dialect.PostgreSQL95Dialect -spring.jpa.show-sql=false -spring.jpa.hibernate.ddl-auto=none -spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true -mosip.esignet.mock.authenticator.ida.otp-channels=email,phone - -mosip.kernel.keymgr.hsm.health.check.enabled=false -mosip.kernel.keymgr.hsm.health.key.app-id=MOCK_AUTHENTICATION_SERVICE -mosip.kernel.keymgr.hsm.healthkey.ref-id=HEALTH_KEY - -##---------------------------------KBA Configurations------------------------------------------------------ - -#We can use any field from the IdentityData for KBA - -mosip.esignet.authenticator.auth-factor.kba.field-details={{"id":"individualId", "type":"text", "format":""},{"id":"email", "type":"text", "format":""},{"id":"dateOfBirth", "type":"date", "format":"yyyy-MM-dd"}} -mosip.esignet.authenticator.auth-factor.kba.field-language=eng \ No newline at end of file diff --git a/docker-compose/docker-compose-certify/config/svg-template.json b/docker-compose/docker-compose-certify/config/svg-template.json deleted file mode 100644 index 26d50c03..00000000 --- a/docker-compose/docker-compose-certify/config/svg-template.json +++ /dev/null @@ -1,6 +0,0 @@ -[ - { - "id": "5b9c2a12-810a-7388-2dc8-13ee7ad88bac", - "content": "\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n {{credentialSubject/policyName}}\n {{credentialSubject/policyNumber}}\n {{credentialSubject/fullName}}\n {{credentialSubject/gender}}\n {{credentialSubject/email}}\n {{credentialSubject/mobile}}\n\n Policy Issued On\n {{credentialSubject/policyIssuedOn}}\n\n Policy Expires On\n {{credentialSubject/policyExpiresOn}}\n\n Issuance Date On\n {{issuanceDate}}\n\n Expiration Date On\n {{expirationDate}}\n" - } -] \ No newline at end of file diff --git a/docker-compose/docker-compose-certify/docker-compose.yml b/docker-compose/docker-compose-certify/docker-compose.yml deleted file mode 100644 index 78715926..00000000 --- a/docker-compose/docker-compose-certify/docker-compose.yml +++ /dev/null @@ -1,144 +0,0 @@ -version: '3.8' - -services: - database: - image: 'postgres:latest' - ports: - - 5456:5432 - environment: - - POSTGRES_USER=postgres - - POSTGRES_PASSWORD=postgres - volumes: - - ./esignet_init.sql:/docker-entrypoint-initdb.d/esignet_init.sql - - ./certify_init.sql:/docker-entrypoint-initdb.d/certify_init.sql - - ./mock_identity_init.sql:/docker-entrypoint-initdb.d/mock_identity_init.sql - networks: - - network - artifactory-server: - image: 'mosipid/artifactory-server:0.9.1-INJI' - ports: - - 8080:8080 - networks: - - network - mock-identity-system: - image: 'mosipid/mock-identity-system:0.9.3' - user: root - ports: - - 8082:8082 - environment: - - artifactory_url_env=http://artifactory-server:8080/ - - container_user=mosip - - active_profile_env=default - - SPRING_CONFIG_NAME=mock-identity-system - - SPRING_CONFIG_LOCATION=/home/mosip/mock-identity-system-default.properties - depends_on: - - database - - artifactory-server - volumes: - - ./config/mock-identity-system-default.properties:/home/mosip/mock-identity-system-default.properties - networks: - - network - cache: - image: redis:6.2-alpine - restart: always - ports: - - '6379:6379' - command: redis-server --save 20 1 --loglevel warning --requirepass redis - volumes: - - cache:/data - networks: - - network - zookeeper: - image: wurstmeister/zookeeper - container_name: zookeeper - ports: - - "2181:2181" - networks: - - network - kafka: - image: wurstmeister/kafka - container_name: kafka - ports: - - "9092:9092" - environment: - KAFKA_ADVERTISED_LISTENERS: INSIDE://kafka:9092,OUTSIDE://localhost:9093 - KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: INSIDE:PLAINTEXT,OUTSIDE:PLAINTEXT - KAFKA_LISTENERS: INSIDE://0.0.0.0:9092,OUTSIDE://0.0.0.0:9093 - KAFKA_INTER_BROKER_LISTENER_NAME: INSIDE - KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181 - KAFKA_CREATE_TOPICS: "esignet-linked:1:1,esignet-consented:1:1" - networks: - - network - esignet: - image: 'mosipid/esignet:1.4.1' - user: root - ports: - - 8088:8088 - environment: - - artifactory_url_env=http://artifactory-server:8080/ - - container_user=mosip - - active_profile_env=default,mock-identity - - SPRING_CONFIG_NAME=esignet - - SPRING_CONFIG_LOCATION=/home/mosip/config/ - - esignet_wrapper_url_env=http://artifactory-server:8080/artifactory/libs-release-local/esignet/esignet-wrapper.zip - depends_on: - - database - - artifactory-server - - kafka - volumes: - - ./config/esignet-default.properties:/home/mosip/config/esignet-default.properties - - ./config/esignet-sunbird-insurance.properties:/home/mosip/config/esignet-sunbird-insurance.properties - - ./config/esignet-mock-identity.properties:/home/mosip/config/esignet-mock-identity.properties - - ./data/ESIGNET_PKCS12:/home/mosip/ESIGNET_PKCS12 -# - ./loader_path/esignet/:/home/mosip/additional_jars/ - networks: - - network - certify: - image: mosipid/inji-certify:0.9.1 - user: root - ports: - - 8090:8090 - environment: - - artifactory_url_env=http://artifactory-server:8080 - - container_user=mosip - - active_profile_env=default,mock-identity - - SPRING_CONFIG_NAME=certify - - SPRING_CONFIG_LOCATION=/home/mosip/config/ -# - enable_certify_artifactory=false -# - download_hsm_client=true - volumes: - - ./config/certify-default.properties:/home/mosip/config/certify-default.properties - - ./config/certify-sunbird-insurance.properties:/home/mosip/config/certify-sunbird-insurance.properties - - ./config/certify-mock-identity.properties:/home/mosip/config/certify-mock-identity.properties - - ./data/CERTIFY_PKCS12:/home/mosip/CERTIFY_PKCS12 -# - ./loader_path/certify/:/home/mosip/additional_jars/ - depends_on: - - esignet - networks: - - network - esignet-ui: - image: 'mosipid/oidc-ui:1.4.1' - user: root - ports: - - 3001:3000 - depends_on: - - esignet - - artifactory-server - environment: - - artifactory_url_env=http://artifactory-server:8080/ - - container_user=mosip - - DEFAULT_WELLKNOWN=%5B%7B%22name%22%3A%22OpenID%20Configuration%22%2C%22value%22%3A%22%2F.well-known%2Fopenid-configuration%22%7D%2C%7B%22name%22%3A%22Jwks%20Json%22%2C%22value%22%3A%22%2F.well-known%2Fjwks.json%22%7D%2C%7B%22name%22%3A%22Authorization%20Server%22%2C%22value%22%3A%22%2F.well-known%2Foauth-authorization-server%22%7D%2C%7B%22name%22%3A%22OpenID%20Credential%20Issuer%22%2C%22value%22%3A%22%2F.well-known%2Fopenid-credential-issuer%22%7D%5D - - SIGN_IN_WITH_ESIGNET_PLUGIN_URL=http://artifactory-server:8080/artifactory/libs-release-local/mosip-plugins/sign-in-with-esignet.zip - volumes: - - ./nginx.conf:/etc/nginx/nginx.conf - networks: - - network - -networks: - network: - name: mosip_network - external: true - -volumes: - cache: - driver: local diff --git a/docker-compose/docker-compose-certify/esignet_init.sql b/docker-compose/docker-compose-certify/esignet_init.sql deleted file mode 100644 index 988e3ffd..00000000 --- a/docker-compose/docker-compose-certify/esignet_init.sql +++ /dev/null @@ -1,138 +0,0 @@ -CREATE DATABASE mosip_esignet - ENCODING = 'UTF8' - LC_COLLATE = 'en_US.UTF-8' - LC_CTYPE = 'en_US.UTF-8' - TABLESPACE = pg_default - OWNER = postgres - TEMPLATE = template0; - -COMMENT ON DATABASE mosip_esignet IS 'e-Signet related data is stored in this database'; - -\c mosip_esignet postgres - -DROP SCHEMA IF EXISTS esignet CASCADE; -CREATE SCHEMA esignet; -ALTER SCHEMA esignet OWNER TO postgres; -ALTER DATABASE mosip_esignet SET search_path TO esignet,pg_catalog,public; - -CREATE TABLE esignet.client_detail( - id character varying(100) NOT NULL, - name character varying(256) NOT NULL, - rp_id character varying(100) NOT NULL, - logo_uri character varying(2048) NOT NULL, - redirect_uris character varying NOT NULL, - claims character varying NOT NULL, - acr_values character varying NOT NULL, - public_key character varying NOT NULL, - grant_types character varying NOT NULL, - auth_methods character varying NOT NULL, - status character varying(20) NOT NULL, - cr_dtimes timestamp NOT NULL, - upd_dtimes timestamp, - CONSTRAINT pk_clntdtl_id PRIMARY KEY (id), - CONSTRAINT uk_clntdtl_key UNIQUE (public_key) -); - -create table esignet.consent_detail ( - id UUID NOT NULL, - client_id VARCHAR NOT NULL, - psu_token VARCHAR NOT NULL, - claims VARCHAR NOT NULL, - authorization_scopes VARCHAR NOT NULL, - cr_dtimes TIMESTAMP DEFAULT NOW() NOT NULL, - expire_dtimes TIMESTAMP, - signature VARCHAR, - hash VARCHAR, - accepted_claims VARCHAR, - permitted_scopes VARCHAR, - PRIMARY KEY (id), - CONSTRAINT unique_client_token UNIQUE (client_id, psu_token) -); - -CREATE INDEX IF NOT EXISTS idx_consent_psu_client ON esignet.consent_detail(psu_token, client_id); - -create table esignet.consent_history ( - id UUID NOT NULL, - client_id VARCHAR NOT NULL, - psu_token VARCHAR NOT NULL, - claims VARCHAR NOT NULL, - authorization_scopes VARCHAR NOT NULL, - cr_dtimes TIMESTAMP DEFAULT NOW() NOT NULL, - expire_dtimes TIMESTAMP, - signature VARCHAR, - hash VARCHAR, - accepted_claims VARCHAR, - permitted_scopes VARCHAR, - PRIMARY KEY (id) -); -CREATE INDEX IF NOT EXISTS idx_consent_history_psu_client ON esignet.consent_history(psu_token, client_id); - -CREATE TABLE esignet.key_alias( - id character varying(36) NOT NULL, - app_id character varying(36) NOT NULL, - ref_id character varying(128), - key_gen_dtimes timestamp, - key_expire_dtimes timestamp, - status_code character varying(36), - lang_code character varying(3), - cr_by character varying(256) NOT NULL, - cr_dtimes timestamp NOT NULL, - upd_by character varying(256), - upd_dtimes timestamp, - is_deleted boolean DEFAULT FALSE, - del_dtimes timestamp, - cert_thumbprint character varying(100), - uni_ident character varying(50), - CONSTRAINT pk_keymals_id PRIMARY KEY (id), - CONSTRAINT uni_ident_const UNIQUE (uni_ident) -); - -CREATE TABLE esignet.key_policy_def( - app_id character varying(36) NOT NULL, - key_validity_duration smallint, - is_active boolean NOT NULL, - pre_expire_days smallint, - access_allowed character varying(1024), - cr_by character varying(256) NOT NULL, - cr_dtimes timestamp NOT NULL, - upd_by character varying(256), - upd_dtimes timestamp, - is_deleted boolean DEFAULT FALSE, - del_dtimes timestamp, - CONSTRAINT pk_keypdef_id PRIMARY KEY (app_id) -); - -CREATE TABLE esignet.key_store( - id character varying(36) NOT NULL, - master_key character varying(36) NOT NULL, - private_key character varying(2500) NOT NULL, - certificate_data character varying NOT NULL, - cr_by character varying(256) NOT NULL, - cr_dtimes timestamp NOT NULL, - upd_by character varying(256), - upd_dtimes timestamp, - is_deleted boolean DEFAULT FALSE, - del_dtimes timestamp, - CONSTRAINT pk_keystr_id PRIMARY KEY (id) -); - -CREATE TABLE esignet.public_key_registry( - id_hash character varying(100) NOT NULL, - auth_factor character varying(25) NOT NULL, - psu_token character varying(256) NOT NULL, - public_key character varying NOT NULL, - expire_dtimes timestamp NOT NULL, - wallet_binding_id character varying(256) NOT NULL, - public_key_hash character varying(100) NOT NULL, - certificate character varying NOT NULL, - cr_dtimes timestamp NOT NULL, - thumbprint character varying NOT NULL, - CONSTRAINT pk_public_key_registry PRIMARY KEY (id_hash, auth_factor) -); - - -INSERT INTO esignet.KEY_POLICY_DEF(APP_ID,KEY_VALIDITY_DURATION,PRE_EXPIRE_DAYS,ACCESS_ALLOWED,IS_ACTIVE,CR_BY,CR_DTIMES) VALUES('ROOT', 2920, 1125, 'NA', true, 'mosipadmin', now()); -INSERT INTO esignet.KEY_POLICY_DEF(APP_ID,KEY_VALIDITY_DURATION,PRE_EXPIRE_DAYS,ACCESS_ALLOWED,IS_ACTIVE,CR_BY,CR_DTIMES) VALUES('OIDC_SERVICE', 1095, 50, 'NA', true, 'mosipadmin', now()); -INSERT INTO esignet.KEY_POLICY_DEF(APP_ID,KEY_VALIDITY_DURATION,PRE_EXPIRE_DAYS,ACCESS_ALLOWED,IS_ACTIVE,CR_BY,CR_DTIMES) VALUES('OIDC_PARTNER', 1095, 50, 'NA', true, 'mosipadmin', now()); -INSERT INTO esignet.KEY_POLICY_DEF(APP_ID,KEY_VALIDITY_DURATION,PRE_EXPIRE_DAYS,ACCESS_ALLOWED,IS_ACTIVE,CR_BY,CR_DTIMES) VALUES('BINDING_SERVICE', 1095, 50, 'NA', true, 'mosipadmin', now()); -INSERT INTO esignet.KEY_POLICY_DEF(APP_ID,KEY_VALIDITY_DURATION,PRE_EXPIRE_DAYS,ACCESS_ALLOWED,IS_ACTIVE,CR_BY,CR_DTIMES) VALUES('MOCK_BINDING_SERVICE', 1095, 50, 'NA', true, 'mosipadmin', now()); diff --git a/docker-compose/docker-compose-certify/mock_identity_init.sql b/docker-compose/docker-compose-certify/mock_identity_init.sql deleted file mode 100644 index 7a1d7799..00000000 --- a/docker-compose/docker-compose-certify/mock_identity_init.sql +++ /dev/null @@ -1,83 +0,0 @@ -CREATE DATABASE mosip_mockidentitysystem - ENCODING = 'UTF8' - LC_COLLATE = 'en_US.UTF-8' - LC_CTYPE = 'en_US.UTF-8' - TABLESPACE = pg_default - OWNER = postgres - TEMPLATE = template0; - -COMMENT ON DATABASE mosip_mockidentitysystem IS 'Mock identity related data is stored in this database'; - -\c mosip_mockidentitysystem postgres - -DROP SCHEMA IF EXISTS mockidentitysystem CASCADE; -CREATE SCHEMA mockidentitysystem; -ALTER SCHEMA mockidentitysystem OWNER TO postgres; -ALTER DATABASE mosip_mockidentitysystem SET search_path TO mockidentitysystem,pg_catalog,public; - -CREATE TABLE mockidentitysystem.key_alias( - id character varying(36) NOT NULL, - app_id character varying(36) NOT NULL, - ref_id character varying(128), - key_gen_dtimes timestamp, - key_expire_dtimes timestamp, - status_code character varying(36), - lang_code character varying(3), - cr_by character varying(256) NOT NULL, - cr_dtimes timestamp NOT NULL, - upd_by character varying(256), - upd_dtimes timestamp, - is_deleted boolean DEFAULT FALSE, - del_dtimes timestamp, - cert_thumbprint character varying(100), - uni_ident character varying(50), - CONSTRAINT pk_keymals_id PRIMARY KEY (id), - CONSTRAINT uni_ident_const UNIQUE (uni_ident) -); - -CREATE TABLE mockidentitysystem.key_policy_def( - app_id character varying(36) NOT NULL, - key_validity_duration smallint, - is_active boolean NOT NULL, - pre_expire_days smallint, - access_allowed character varying(1024), - cr_by character varying(256) NOT NULL, - cr_dtimes timestamp NOT NULL, - upd_by character varying(256), - upd_dtimes timestamp, - is_deleted boolean DEFAULT FALSE, - del_dtimes timestamp, - CONSTRAINT pk_keypdef_id PRIMARY KEY (app_id) -); - -CREATE TABLE mockidentitysystem.key_store( - id character varying(36) NOT NULL, - master_key character varying(36) NOT NULL, - private_key character varying(2500) NOT NULL, - certificate_data character varying NOT NULL, - cr_by character varying(256) NOT NULL, - cr_dtimes timestamp NOT NULL, - upd_by character varying(256), - upd_dtimes timestamp, - is_deleted boolean DEFAULT FALSE, - del_dtimes timestamp, - CONSTRAINT pk_keystr_id PRIMARY KEY (id) -); - -CREATE TABLE mockidentitysystem.kyc_auth( - kyc_token VARCHAR(255), - individual_id VARCHAR(255), - partner_specific_user_token VARCHAR(255), - response_time TIMESTAMP, - transaction_id VARCHAR(255), - validity INTEGER -); - -CREATE TABLE mockidentitysystem.mock_identity( - individual_id VARCHAR(36) NOT NULL, - identity_json VARCHAR NOT NULL, - CONSTRAINT pk_mock_id_code PRIMARY KEY (individual_id) -); - -INSERT INTO mockidentitysystem.KEY_POLICY_DEF(APP_ID,KEY_VALIDITY_DURATION,PRE_EXPIRE_DAYS,ACCESS_ALLOWED,IS_ACTIVE,CR_BY,CR_DTIMES) VALUES('ROOT', 2920, 1125, 'NA', true, 'mosipadmin', now()); -INSERT INTO mockidentitysystem.KEY_POLICY_DEF(APP_ID,KEY_VALIDITY_DURATION,PRE_EXPIRE_DAYS,ACCESS_ALLOWED,IS_ACTIVE,CR_BY,CR_DTIMES) VALUES('MOCK_AUTHENTICATION_SERVICE', 1095, 50, 'NA', true, 'mosipadmin', now()); \ No newline at end of file diff --git a/docker-compose/docker-compose-certify/nginx.conf b/docker-compose/docker-compose-certify/nginx.conf deleted file mode 100644 index 39ecdbad..00000000 --- a/docker-compose/docker-compose-certify/nginx.conf +++ /dev/null @@ -1,72 +0,0 @@ -worker_processes 1; - -events { - worker_connections 1024; -} - -http { - access_log /var/log/nginx/access.log; - error_log /var/log/nginx/error.log; - server { - listen 3000; - server_name localhost; - - root /usr/share/nginx/html; - index index.html index.htm; - include /etc/nginx/mime.types; - - gzip on; - gzip_min_length 1000; - gzip_proxied expired no-cache no-store private auth; - gzip_types text/plain text/css application/json application/javascript application/x-javascript text/xml application/xml application/xml+rss text/javascript; - - location /v1/esignet { - proxy_pass http://esignet:8088/v1/esignet; - proxy_redirect off; - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Host $server_name; - } - location /.well-known/openid-configuration { - proxy_pass http://esignet:8088/v1/esignet/oidc/.well-known/openid-configuration; - proxy_redirect off; - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Host $server_name; - } - location /.well-known/jwks.json { - proxy_pass http://esignet:8088/v1/esignet/oauth/.well-known/jwks.json; - proxy_redirect off; - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Host $server_name; - } - location /.well-known/oauth-authorization-server { - proxy_pass http://esignet:8088/v1/esignet/oauth/.well-known/oauth-authorization-server; - proxy_redirect off; - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Host $server_name; - } - location /.well-known/openid-credential-issuer { - proxy_pass http://esignet:8088/v1/esignet/vci/.well-known/openid-credential-issuer; - proxy_redirect off; - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Host $server_name; - } - # location /oidc-ui { - # alias /usr/share/nginx/oidc-ui; - # try_files $uri $uri/ /oidc-ui/index.html; - # } - location / { - # alias /usr/share/nginx/html; - try_files $uri $uri/ /index.html; - } - } -} \ No newline at end of file diff --git a/docker-compose/docker-compose-injistack/README.md b/docker-compose/docker-compose-injistack/README.md index e99ffa09..f03d5341 100644 --- a/docker-compose/docker-compose-injistack/README.md +++ b/docker-compose/docker-compose-injistack/README.md @@ -1,24 +1,31 @@ # Inji Stack Setup -This guide provides instructions for setting up and running Inji Stack. +This guide provides instructions for setting up and running Inji Stack for a custom use-case using an existing foundational ID system. This shows how an institution can enable it's portfolio of deparments to build upon an existing identity to accelarate independent service delivery. In the below example, we help setup some components of **Inji Stack** which uses an Authorization Service of a **National ID** deployed by MOSIP to help other depute institutions setup a use-case specific Credential Delivery for it's citizens by two independent departments one at a time such as _Agriculture_ & _Transport_. This example demonstrates the delivery of profession specific identity cards to it's citizens **Farmer Identity Card** to eligible farmers by the **Agriculture Department** or a **Mobile Driving License** to eligible drivers by the **Transport Department**. These examples can be further extended for different usecases and used with different OIDC Compatible clients. + +On the more technical side, this demo showcases the two types of plugin an implementor can choose to implement depending upon their usecase & requirements and can even point to another pre-existing identity system demonstrating it's adaptability to various usecases while being backed by open standards which leads to faster adoption and widespread acceptability. + + +# QuickStart: Mock Certify Plugin Setup + +Expected time to setup: ~10 minutes + +You have two options for the certify plugin which gives Verifiable Credentials of different types + +1. Farmer Credential: returns an JSON-LD VC and is implemented using the [CSV Plugin](https://github.com/mosip/digital-credential-plugins/blob/release-0.3.x/mock-certify-plugin/src/main/java/io.mosip.certify.mock.integration/service/MockCSVDataProviderPlugin.java). +2. Mobile Driving License Credential: returns an mDL VC and is implemented using the [mock-mdl Plugin](https://github.com/mosip/digital-credential-plugins/blob/release-0.3.x/mock-certify-plugin/src/main/java/io.mosip.certify.mock.integration/service/MDocMockVCIssuancePlugin.java). + ## Prerequisites + - Docker and Docker Compose installed on your system - Git (to clone the repository) - Basic understanding of Docker and container operations -### Building inji-web-proxy -Before running the docker-compose, you need to build the inji-web-proxy image: - -```bash -# Clone the repository -git clone https://github.com/mosip/inji-web.git -b release-0.11.x -cd inji-web/inji-web-proxy - -# Build the Docker image -docker build -t inji-web-proxy:local . -``` +- Relevant Postman collections available from [here](../../docs/postman-collections/), please add the `mock` ones and install the [pmlib library](https://joolfe.github.io/postman-util-lib/) as per the steps given under the heading `Postman Collection` to the Postman setup +- Network Connectivity to access the AuthZ Service, in this example MOSIP Collab setup has been used +- (optional, required if Farmer Credential configured) GitHub Pages or similar service required to host a DID/public key ## Directory Structure Setup + Create the following directory structure before proceeding: ``` @@ -31,7 +38,7 @@ docker-compose-injistack/ β”‚ └── certify/ (plugin jar to be placed here) β”œβ”€β”€ config/ (default setup should work as is for csvplugin, any other config changes user can make as per their setup) β”‚ β”œβ”€β”€ certify-default.properties -β”‚ β”œβ”€β”€ certify-mock-identity.properties +β”‚ β”œβ”€β”€ certify-csvdp-farmer.properties β”‚ β”œβ”€β”€ mimoto-default.properties β”‚ β”œβ”€β”€ mimoto-issuers-config.json β”‚ β”œβ”€β”€ mimoto-trusted-verifiers.json @@ -41,83 +48,157 @@ docker-compose-injistack/ └── docker-compose.yml ``` -## Mock Certify Plugin Setup -You have two options for the certify plugin: -### Option 1: Use Existing Mock Plugin + +## Choosing a VCI plugin for issuance + + +### Recommended: Use one of the Existing Mock Plugin + - Supported versions: 0.3.0 and above -- Download the snapshot JAR from: +- Download the latest JAR from: ``` https://oss.sonatype.org/content/repositories/snapshots/io/mosip/certify/mock-certify-plugin/0.3.0-SNAPSHOT/ ``` - Place the downloaded JAR in `loader_path/certify/` -### Option 2: Create Custom Plugin -You can create your own plugin by implementing the following interface and place the resultant jar in loader_path: +### For Advanced Users: Create Custom Plugin + +You can create your own plugin by implementing the following interface and place the resultant jar in `loader_path`: + +Reference Implementation: [CSVDataProviderPlugin](https://github.com/mosip/digital-credential-plugins/blob/release-0.3.x/mock-certify-plugin/src/main/java/io.mosip.certify.mock.integration/service/MockCSVDataProviderPlugin.java) or [MDocMockVCIssuancePlugin](https://github.com/mosip/digital-credential-plugins/blob/release-0.3.x/mock-certify-plugin/src/main/java/io.mosip.certify.mock.integration/service/MDocMockVCIssuancePlugin.java). -Reference Implementation: [CSVDataProviderPlugin](https://github.com/mosip/digital-credential-plugins/blob/develop/mock-certify-plugin/src/main/java/io.mosip.certify.mock.integration/service/MockCSVDataProviderPlugin.java) ```java public interface DataProviderPlugin { // Implement your custom logic here } ``` +or, if you chose the VCIssuancePlugin implement the below interface. The above two examples + +```java +public interface VCIssuancePlugin { + // Implement your custom logic here +} +``` + +## Certificate Setup + +- Create a `certs/` directory inside the docker-compose-injistack directory. +- Place your PKCS12 keystore file in the `certs` directory as `oidckeystore.p12`. This is required for the Inji Web application and other applications which rely on Mimoto as a BFF and it can be configured as per these [docs](https://docs.inji.io/inji-wallet/inji-mobile/customization-overview/credential_providers#onboarding-mimoto-as-oidc-client-for-a-new-issuer) after the file is downloaded in the `certs` directory as shown in the directory tree. +- Update `mosip.oidc.p12.password` to the password of the `oidckeystore.p12` file in the Mimoto [Config file](./config/mimoto-default.properties). + + ## Configuration Setup +- If you chose the Recommended option, you just need to set the `active_profile_env` value of the certify service in [docker-compose.yaml](./docker-compose.yaml) as per use case or else configure your custom plugin and name the files & `active_profile_env` appropriately as follows, -### 1. Certificate Setup -- Place your PKCS12 certificate file (obtained from esignet onboarding) in: - ``` - certs/oidckeystore.p12 - ``` - [Collab Env OIDCKeystore](https://docs.inji.io/inji-wallet/inji-mobile/customization-overview/credential_providers#onboarding-mimoto-as-oidc-client-for-a-new-issuer) +| Use Case | active_profile_env | config file | +|-------------------------------|-----------------------|------------------------------------------| +| Farmer credential (default) | `default, csvdp-farmer` | ./config/certify-csvdp-farmer.properties | +| Mobile driving license | `default, mock-mdl` | ./config/certify-mock-mdl.properties | + + +### Recommended + +- If you are going ahead with the Farmer usecase, configure the below values in [here](config/certify-csvdp-farmer.properties) to refer to the web location where you'd host the DID. + +```properties +mosip.certify.data-provider-plugin.issuer-uri=did:web:someuser.github.io:somerepo:somedirectory +mosip.certify.data-provider-plugin.issuer-public-key-uri=did:web:someuser.github.io:somerepo:somedirectory#key-0 +``` + +- (required for Farmer setup) Certify will automatically generate the DID document for your usecase at [this endpoint](http://localhost:8090/v1/certify/issuance/.well-known/did.json), please copy the contents of the HTTP response and host it appropriately in the same location. + - A did with the ID `did:web:someuser.github.io:somerepo:somedirectory` will have be accessible at `https://someuser.github.io/somerepo/somedirectory/did.json`, i.e. if GitHub Pages is used to host the file, the contents should go in https://github.com/someuser/somerepo/blob/gh-pages/somedirectory/did.json assuming `gh-pages` is the branch for publishing GitHub Pages as per repository settings. + - To verify if everything is working you can try to resolve the DID via public DID resolvers such as [Uniresolver](https://dev.uniresolver.io/). + +- (required if Mobile driving license configured) Onboard issuer key and certificate data into property `mosip.certify.mock.mdoc.issuer-key-cert` using the creation script, please read the [plugin README](https://github.com/mosip/digital-credential-plugins/tree/release-0.3.x/mock-certify-plugin) for the same. + + +## Other configurations + +**Note**: Refer the relevant config file based on use case to connect to the required environment. + +Ensure all configuration files are properly updated in the config directory if you have are making any changes suggested for any Advanced usecase: -### 2. Configuration Files -Ensure all configuration files are properly updated in the config directory: - certify-default.properties -- certify-mock-identity.properties +- certify-csvdp-farmer.properties - mimoto-default.properties - mimoto-issuers-config.json - mimoto-trusted-verifiers.json - credential-template.html -[Mimoto Docker Compose Configuration Docs](https://github.com/mosip/mimoto/tree/release-0.15.x/docker-compose) -[Inji Certify Configuration Docs](../../README.md) + + ## Running the Application -### 1. Start the Services +### Start the Services + ```bash docker-compose up -d ``` -### 2. Verify Services +### Verify Services + Check if all services are running: ```bash docker-compose ps ``` ## Service Endpoints + The following services will be available: + - Database (PostgreSQL): `localhost:5433` - Certify Service: `localhost:8090` -- Nginx: `localhost:80` - Mimoto Service: `localhost:8099` -- Inji Web Proxy: `localhost:3010` - Inji Web: `localhost:3001` ## Using the Application -### Accessing the Web Interface +### Recommended: Accessing the Web Interface + 1. Open your browser and navigate to `http://localhost:3001` 2. You can: + - Download credentials + - View credential status at a Standards Compliant VC Verfier such as [Inji Verify](https://injiverify.collab.mosip.net). +3. As a sample, you can try downloading VC with the UIN `5860356276` or `2154189532`. The OTP for this purpose can be given as `111111` which is the Mock OTP for eSignet Collab Environment. The above sample identities should be present at both the Identity Provider(here, National ID) and at the Local Issuer(here, Agriculture Department or Transport Department). + +### Advanced Users: Accessing the Credentials via the Postman Interface + +1. Open Postman +2. Import the [Mock Collections & Environments](../../docs/postman-collections/) from here, make appropriate changes to the Credential Type and contexts as per your VerifiableCredential and the configured WellKnown. +3. You can - Download credentials - View credential status - Manage your digital identity + +## Advanced Configurations + +1. To use the Verifiable Credential Data Model 2.0 optional features one can configure them in the Velocity Template present in [this file](./certify_init.sql)as per [this draft spec](https://w3c-ccg.github.io/vc-render-method/). The Render Template has to be routable by all the clients and should be cached appropriately. The template is not expected to be updated as the consuming clients are expected to verify the integrity with the provided `digestMultibase`. For detailed information please go through the draft spec. + +```json + "renderMethod": [{ + "id": "https://yourdomain.certify.io/v1/certify/rendering-template/national-id", + "type": "SvgRenderingTemplate", + "name": "Portrait Mode", + "css3MediaQuery": "@media (orientation: portrait)", + "digestMultibase": "zQmAPdhyxzznFCwYxAp2dRerWC85Wg6wFl9G270iEu5h6JqW" + }] +``` + +The digest multibase can be hardcoded or if the template has been stored with Certify's DB & `mosip.certify.data-provider-plugin.rendering-template-id` is set to the correct the value `${_renderMethodSVGdigest}` can be used to enable Certify to evaluate it specifying the id of the rendering-template used. However, for optimal performance, it's recommended to not set this key and instead hardcode the `digestMultibase` value in the Velocity template itself. + +2. Deploying Inji Certify over a public URL, _using ngrok to demonstrate this_ + +- change the value of the `mosipbox_public_url` to point to the public URL in ./docker-compose.yaml where Certify service will be accessible, when using locally with ngrok create an HTTP tunnel for the port `8090`, which is the port for Certify and access the Inji Web at http://localhost:3001, to access Inji Web you may have to create another client with the Authorization service and more configuration should be required at Mimoto side + ## Troubleshooting ### Common Issues and Solutions + 1. Container startup issues: ```bash docker-compose logs [service_name] @@ -131,7 +212,22 @@ The following services will be available: - Verify plugin JAR is in the correct directory - Check plugin version compatibility +4. Postman throws an error `pmlib is not defined` + - Follow the steps defined in the pre-requsites above. + +5. The container images for Certify aren't published for the `linux/arm64` architecture yet, if your container runtime returns an error, you can try to run the engine in an emulated mode. This applies to Apple Silicon Mac users running Docker, they'd have to set `export DOCKER_DEFAULT_PLATFORM=linux/amd64` before doing `docker compose up -d`. + +6. Apple users using Colima may have issues with the permission of the `data/` directory. + - Set the owner, group and the permission mode-bits & the file's group & user ownership correctly so that the `local.p12` file can be created inside the data directory. + +7. VC download is failing with Mimoto error logs stating that VC Verification is failing. + - Check if the DID is updated & resolvable. The Multibase hash changes on each restart, please update it whenever a newer instance of Certify is setup. + - Check if the hosted DID matches with the [DID endpoint](http://localhost:8090/v1/certify/issuance/.well-known/did.json) + - As of now, Mimoto/Inji Web only supports downloads for Ed25519Signature2020 signed VerifiableCredential due to a limitation of the integrated VC-Verification module. + + ### Health Checks + Monitor service health: ```bash docker-compose ps @@ -140,7 +236,7 @@ docker logs [container_name] ## Hosting a public key in the form of a DID -1. Extract the certificate from the [Ceritfy Endpoint](http://localhost:8090/v1/certify/system-info/certificate?applicationId=CERTIFY_MOCK_ED25519&referenceId=ED25519_SIGN) +1. Extract the certificate from the [Ceritfy Endpoint](http://localhost:8090/v1/certify/system-info/certificate?applicationId=CERTIFY_VC_SIGN_ED25519&referenceId=ED25519_SIGN) 2. Use `openssl x509 -pubkey -noout -in filename.pem` to convert the certificate to a public key. 3. Convert the public key to a publicKeyMultibase as per the [spec](https://www.w3.org/community/reports/credentials/CG-FINAL-di-eddsa-2020-20220724/). @@ -156,6 +252,7 @@ docker-compose down -v ``` ## Security Considerations + - Keep your PKCS12 certificate secure - Regularly update configurations and credentials - Monitor service logs for security issues diff --git a/docker-compose/docker-compose-injistack/certify_init.sql b/docker-compose/docker-compose-injistack/certify_init.sql index ce556ee5..dad46153 100644 --- a/docker-compose/docker-compose-injistack/certify_init.sql +++ b/docker-compose/docker-compose-injistack/certify_init.sql @@ -15,6 +15,7 @@ CREATE SCHEMA certify; ALTER SCHEMA certify OWNER TO postgres; ALTER DATABASE inji_certify SET search_path TO certify,pg_catalog,public; +--- keymanager specific DB changes --- CREATE TABLE certify.key_alias( id character varying(36) NOT NULL, app_id character varying(36) NOT NULL, @@ -64,15 +65,39 @@ CREATE TABLE certify.key_store( CONSTRAINT pk_keystr_id PRIMARY KEY (id) ); -CREATE TABLE certify.svg_template ( - id UUID NOT NULL, +CREATE TABLE certify.ca_cert_store( + cert_id character varying(36) NOT NULL, + cert_subject character varying(500) NOT NULL, + cert_issuer character varying(500) NOT NULL, + issuer_id character varying(36) NOT NULL, + cert_not_before timestamp, + cert_not_after timestamp, + crl_uri character varying(120), + cert_data character varying, + cert_thumbprint character varying(100), + cert_serial_no character varying(50), + partner_domain character varying(36), + cr_by character varying(256), + cr_dtimes timestamp, + upd_by character varying(256), + upd_dtimes timestamp, + is_deleted boolean DEFAULT FALSE, + del_dtimes timestamp, + ca_cert_type character varying(25), + CONSTRAINT pk_cacs_id PRIMARY KEY (cert_id), + CONSTRAINT cert_thumbprint_unique UNIQUE (cert_thumbprint,partner_domain) + +); + +CREATE TABLE certify.rendering_template ( + id varchar(128) NOT NULL, template VARCHAR NOT NULL, cr_dtimes timestamp NOT NULL, upd_dtimes timestamp, CONSTRAINT pk_svgtmp_id PRIMARY KEY (id) ); -CREATE TABLE certify.template_data( +CREATE TABLE certify.credential_template( context character varying(1024) NOT NULL, credential_type character varying(512) NOT NULL, template VARCHAR NOT NULL, @@ -81,86 +106,74 @@ CREATE TABLE certify.template_data( CONSTRAINT pk_template PRIMARY KEY (context, credential_type) ); -INSERT INTO certify.template_data (context, credential_type, template, cr_dtimes, upd_dtimes) VALUES ('https://vharsh.github.io/DID/mock-context.json,https://www.w3.org/2018/credentials/v1', 'MockVerifiableCredential,VerifiableCredential', '{ - "@context": [ - "https://www.w3.org/2018/credentials/v1", - "https://vharsh.github.io/DID/mock-context.json"], - "issuer": "${issuer}", - "type": ["VerifiableCredential", "MockVerifiableCredential"], - "issuanceDate": "${validFrom}", - "expirationDate": "${validUntil}", - "credentialSubject": { - "gender": ${gender}, - "postalCode": ${postalCode}, - "fullName": ${fullName}, - "dateOfBirth": "${dateOfBirth}", - "province": ${province}, - "phone": "${phone}", - "addressLine1": ${addressLine1}, - "region": ${region}, - "vcVer": "${vcVer}", - "UIN": ${UIN}, - "email": "${email}", - "face": "${face}" - } -}', '2024-10-22 17:08:17.826851', NULL); -INSERT INTO certify.template_data (context, credential_type, template, cr_dtimes, upd_dtimes) VALUES ('https://vharsh.github.io/DID/mock-context.json,https://www.w3.org/ns/credentials/v2', 'MockVerifiableCredential,VerifiableCredential', '{ +INSERT INTO certify.credential_template (context, credential_type, template, cr_dtimes, upd_dtimes) VALUES ('https://www.w3.org/2018/credentials/v1', 'FarmerCredential,VerifiableCredential', '{ + "@context": [ + "https://www.w3.org/2018/credentials/v1", + "https://piyush7034.github.io/my-files/farmer.json", + "https://w3id.org/security/suites/ed25519-2020/v1" + ], + "issuer": "${_issuer}", + "type": [ + "VerifiableCredential", + "FarmerCredential" + ], + "issuanceDate": "${validFrom}", + "expirationDate": "${validUntil}", + "credentialSubject": { + "id": "${_holderId}", + "fullName": "${fullName}", + "mobileNumber": "${mobileNumber}", + "dateOfBirth": "${dateOfBirth}", + "gender": "${gender}", + "state": "${state}", + "district": "${district}", + "villageOrTown": "${villageOrTown}", + "postalCode": "${postalCode}", + "landArea": "${landArea}", + "landOwnershipType": "${landOwnershipType}", + "primaryCropType": "${primaryCropType}", + "secondaryCropType": "${secondaryCropType}", + "face": "${face}", + "farmerID": "${farmerID}" + } +} +', '2024-10-24 12:32:38.065994', NULL); + +INSERT INTO certify.credential_template (context, credential_type, template, cr_dtimes, upd_dtimes) VALUES ('https://www.w3.org/ns/credentials/v2', 'FarmerCredential,VerifiableCredential', '{ "@context": [ - "https://www.w3.org/ns/credentials/v2", "https://vharsh.github.io/DID/mock-context.json"], - "issuer": "${issuer}", - "type": ["VerifiableCredential", "MockVerifiableCredential"], + "https://www.w3.org/ns/credentials/v2", + "https://piyush7034.github.io/my-files/farmer.json", + "https://w3id.org/security/suites/ed25519-2020/v1" + ], + "issuer": "${_issuer}", + "type": [ + "VerifiableCredential", + "FarmerCredential" + ], "validFrom": "${validFrom}", "validUntil": "${validUntil}", "credentialSubject": { - "gender": ${gender}, - "postalCode": ${postalCode}, - "fullName": ${fullName}, + "id": "${_holderId}", + "fullName": "${fullName}", + "mobileNumber": "${mobileNumber}", "dateOfBirth": "${dateOfBirth}", - "province": ${province}, - "phone": "${phone}", - "addressLine1": ${addressLine1}, - "region": ${region}, - "vcVer": "${vcVer}", - "UIN": ${UIN}, - "email": "${email}", - "face": "${face}" + "gender": "${gender}", + "state": "${state}", + "district": "${district}", + "villageOrTown": "${villageOrTown}", + "postalCode": "${postalCode}", + "landArea": "${landArea}", + "landOwnershipType": "${landOwnershipType}", + "primaryCropType": "${primaryCropType}", + "secondaryCropType": "${secondaryCropType}", + "face": "${face}", + "farmerID": "${farmerID}" } -}', '2024-10-22 17:08:17.826851', NULL); -INSERT INTO certify.template_data (context, credential_type, template, cr_dtimes, upd_dtimes) VALUES ('https://www.w3.org/2018/credentials/v1', 'FarmerCredential,VerifiableCredential', '{ - "@context": [ - "https://www.w3.org/2018/credentials/v1", - "https://vharsh.github.io/DID/farmer.json", - "https://w3id.org/security/suites/ed25519-2020/v1" - ], - "issuer": "${issuer}", - "type": [ - "VerifiableCredential", - "FarmerCredential" - ], - "issuanceDate": "${validFrom}", - "expirationDate": "${validUntil}", - "credentialSubject": { - "name": "${name}", - "dateOfBirth": "${dateOfBirth}", - "highestEducation": "${highestEducation}", - "maritalStatus": "${maritalStatus}", - "typeOfHouse": "${typeOfHouse}", - "numberOfDependents": "${numberOfDependents}", - "phoneNumber": "${phoneNumber}", - "works": "${works}", - "landArea": "${landArea}", - "landOwnershipType": "${landOwnershipType}", - "primaryCropType": "${primaryCropType}", - "secondaryCropType": "${secondaryCropType}" - } -} -', '2024-10-24 12:32:38.065994', NULL); - +}', '2024-10-24 12:32:38.065994', NULL); INSERT INTO certify.key_policy_def(APP_ID,KEY_VALIDITY_DURATION,PRE_EXPIRE_DAYS,ACCESS_ALLOWED,IS_ACTIVE,CR_BY,CR_DTIMES) VALUES('ROOT', 2920, 1125, 'NA', true, 'mosipadmin', now()); INSERT INTO certify.key_policy_def(APP_ID,KEY_VALIDITY_DURATION,PRE_EXPIRE_DAYS,ACCESS_ALLOWED,IS_ACTIVE,CR_BY,CR_DTIMES) VALUES('CERTIFY_SERVICE', 1095, 60, 'NA', true, 'mosipadmin', now()); INSERT INTO certify.key_policy_def(APP_ID,KEY_VALIDITY_DURATION,PRE_EXPIRE_DAYS,ACCESS_ALLOWED,IS_ACTIVE,CR_BY,CR_DTIMES) VALUES('CERTIFY_PARTNER', 1095, 60, 'NA', true, 'mosipadmin', now()); -INSERT INTO certify.key_policy_def(APP_ID,KEY_VALIDITY_DURATION,PRE_EXPIRE_DAYS,ACCESS_ALLOWED,IS_ACTIVE,CR_BY,CR_DTIMES) VALUES('CERTIFY_MOCK_RSA', 1095, 60, 'NA', true, 'mosipadmin', now()); -INSERT INTO certify.key_policy_def(APP_ID,KEY_VALIDITY_DURATION,PRE_EXPIRE_DAYS,ACCESS_ALLOWED,IS_ACTIVE,CR_BY,CR_DTIMES) VALUES('CERTIFY_MOCK_ED25519', 1095, 60, 'NA', true, 'mosipadmin', now()); +INSERT INTO certify.key_policy_def(APP_ID,KEY_VALIDITY_DURATION,PRE_EXPIRE_DAYS,ACCESS_ALLOWED,IS_ACTIVE,CR_BY,CR_DTIMES) VALUES('CERTIFY_VC_SIGN_RSA', 1095, 60, 'NA', true, 'mosipadmin', now()); +INSERT INTO certify.key_policy_def(APP_ID,KEY_VALIDITY_DURATION,PRE_EXPIRE_DAYS,ACCESS_ALLOWED,IS_ACTIVE,CR_BY,CR_DTIMES) VALUES('CERTIFY_VC_SIGN_ED25519', 1095, 60, 'NA', true, 'mosipadmin', now()); INSERT INTO certify.key_policy_def(APP_ID,KEY_VALIDITY_DURATION,PRE_EXPIRE_DAYS,ACCESS_ALLOWED,IS_ACTIVE,CR_BY,CR_DTIMES) VALUES('BASE', 1095, 60, 'NA', true, 'mosipadmin', now()); - diff --git a/docker-compose/docker-compose-injistack/config/certify-csvdp-farmer.properties b/docker-compose/docker-compose-injistack/config/certify-csvdp-farmer.properties new file mode 100644 index 00000000..5c12aa26 --- /dev/null +++ b/docker-compose/docker-compose-injistack/config/certify-csvdp-farmer.properties @@ -0,0 +1,63 @@ +## ------------------------------------------- Mock ID Integration properties ------------------------------------------------------------ +mosip.certify.integration.scan-base-package=io.mosip.certify.mock.integration +mosip.certify.integration.audit-plugin=LoggerAuditService +mosip.certify.integration.vci-plugin=MockVCIssuancePlugin + +## ------------------------------------------- Mock ID plugin related properties ------------------------------------------------------------ +mosip.certify.mock.vciplugin.verification-method=${mosip.certify.authn.jwk-set-uri} +mosip.certify.mock.authenticator.get-identity-url=http://mock-identity-system:8082/v1/mock-identity-system/identity +mosip.certify.cache.security.algorithm-name=AES/ECB/PKCS5Padding +mosip.certify.cache.secure.individual-id=false +mosip.certify.cache.store.individual-id=true +mosip.certify.identifier=http://localhost:8090 + +mosip.certify.data-provider-plugin.issuer-uri=did:web:vharsh.github.io:DID:harsh +mosip.certify.data-provider-plugin.issuer-public-key-uri=did:web:vharsh.github.io:DID:harsh#key-0 + +mosip.certify.plugin-mode=DataProvider +mosip.certify.data-provider-plugin.id-field-prefix-uri=https://mosip.io/credential/ +mosip.certify.integration.data-provider-plugin=MockCSVDataProviderPlugin +mosip.certify.data-provider-plugin.issuer.vc-sign-algo=Ed25519Signature2020 +## CSV specific config +mosip.certify.mock.data-provider.csv.identifier-column=id +mosip.certify.mock.data-provider.csv.data-columns=id,fullName,mobileNumber,dateOfBirth,gender,state,district,villageOrTown,postalCode,landArea,landOwnershipType,primaryCropType,secondaryCropType,face,farmerID +mosip.certify.mock.data-provider.csv-registry-uri=/home/mosip/config/farmer_identity_data.csv +mosip.certify.data-provider-plugin.rendering-template-id= +mosip.certify.key-values={\ + 'latest' : {\ + 'credential_issuer': '${mosip.certify.identifier}', \ + 'authorization_servers': {'${mosip.certify.authorization.url}'}, \ + 'credential_endpoint': '${mosipbox.public.url}${server.servlet.path}/issuance/credential', \ + 'display': {{'name': 'Agricultural Department', 'locale': 'en'}},\ + 'credential_configurations_supported' : { \ + 'FarmerProfileCredential' : {\ + 'format': 'ldp_vc',\ + 'scope' : 'mock_identity_vc_ldp',\ + 'cryptographic_binding_methods_supported': {'did:jwk'},\ + 'credential_signing_alg_values_supported': {'Ed25519Signature2020'},\ + 'proof_types_supported': {'jwt': {'proof_signing_alg_values_supported': {'RS256', 'PS256'}}},\ + 'credential_definition': {\ + 'type': {'VerifiableCredential','FarmerCredential'},\ + 'credentialSubject': {\ + 'fullName': {'display': {{'name': 'Full Name','locale': 'en'}}}, \ + 'mobileNumber': {'display': {{'name': 'Phone Number','locale': 'en'}}},\ + 'dateOfBirth': {'display': {{'name': 'Date of Birth','locale': 'en'}}},\ + 'gender': {'display': {{'name': 'Gender','locale': 'en'}}},\ + 'state': {'display': {{'name': 'State','locale': 'en'}}},\ + 'district': {'display': {{'name': 'District','locale': 'en'}}},\ + 'villageOrTown': {'display': {{'name': 'Village or Town','locale': 'en'}}},\ + 'postalCode': {'display': {{'name': 'Postal Code','locale': 'en'}}},\ + 'landArea': {'display': {{'name': 'Land Area','locale': 'en'}}},\ + 'landOwnershipType': {'display': {{'name': 'Land Ownership Type','locale': 'en'}}},\ + 'primaryCropType': {'display': {{'name': 'Primary Crop Name','locale': 'en'}}},\ + 'secondaryCropType': {'display': {{'name': 'Secondary Crop type','locale': 'en'}}},\ + 'farmerID': {'display': {{'name': 'Farmer ID','locale': 'en'}}}\ + }},\ + 'display': {{'name': 'Farmer Profile Verifiable Credential', \ + 'locale': 'en', \ + 'logo': {'url': 'https://mosip.github.io/inji-config/logos/agro-vertias-logo.png','alt_text': 'a square logo of a Sunbird'},\ + 'background_color': '#FDFAF9',\ + 'background_image': { 'uri': 'https://mosip.github.io/inji-config/logos/agro-vertias-logo.png' }, \ + 'text_color': '#7C4616'}},\ + 'order' : {'farmerID','fullName','mobileNumber','dateOfBirth','gender','state','district','villageOrTown','postalCode','landArea','landOwnershipType','primaryCropType','secondaryCropType'}\ + }}}} diff --git a/docker-compose/docker-compose-injistack/config/certify-default.properties b/docker-compose/docker-compose-injistack/config/certify-default.properties index 31166d40..f0258328 100644 --- a/docker-compose/docker-compose-injistack/config/certify-default.properties +++ b/docker-compose/docker-compose-injistack/config/certify-default.properties @@ -39,16 +39,16 @@ mosip.certify.security.ignore-csrf-urls=**/actuator/**,/favicon.ico,**/error,\ **/issuance/** mosip.certify.security.ignore-auth-urls=**/actuator/**,**/error,**/swagger-ui/**,\ - **/v3/api-docs/**, **/issuance/**,/public/**, **/system-info/** + **/v3/api-docs/**, **/issuance/**,**/rendering-template/**, **/system-info/** ## ------------------------------------------ Discovery openid-configuration ------------------------------------------- mosip.certify.discovery.issuer-id=${mosipbox.public.url}${server.servlet.path} -mosip.certify.authorization.url=https://esignet-mock.dev1.mosip.net +mosip.certify.authorization.url=https://esignet-mock.collab.mosip.net ##--------------change this later--------------------------------- -mosip.certify.supported.jwt-proof-alg={'RS256','PS256'} -mosip.certify.issuer=CertifyIssuer +mosip.certify.supported.jwt-proof-alg={'RS256','PS256', 'ES256'} +mosip.certify.plugin-mode=DataProvider ##----- These are reference to the oauth resource server providing jwk----------------------------------## @@ -57,7 +57,7 @@ mosip.certify.cnonce-expire-seconds=40 mosip.certify.identifier=${mosipbox.public.url} mosip.certify.authn.filter-urls={ '${server.servlet.path}/issuance/credential', '${server.servlet.path}/issuance/vd11/credential', '${server.servlet.path}/issuance/vd12/credential' } mosip.certify.authn.issuer-uri=${mosip.certify.authorization.url}/v1/esignet -mosip.certify.authn.jwk-set-uri=https://esignet-mock.dev1.mosip.net/v1/esignet/oauth/.well-known/jwks.json +mosip.certify.authn.jwk-set-uri=https://esignet-mock.collab.mosip.net/v1/esignet/oauth/.well-known/jwks.json mosip.certify.authn.allowed-audiences={ '${mosipbox.public.url}${server.servlet.path}/issuance/credential', '${mosip.certify.authorization.url}/v1/esignet/vci/credential' } #------------------------------------ Key-manager specific properties -------------------------------------------------- @@ -165,4 +165,4 @@ mosip.certify.cache.size={'userinfo': 200, 'vcissuance' : 2000 } # Cache expire in seconds is applicable for both 'simple' and 'Redis' cache type -mosip.certify.cache.expire-in-seconds={'userinfo': ${mosip.certify.access-token-expire-seconds}, 'vcissuance': ${mosip.certify.access-token-expire-seconds}} \ No newline at end of file +mosip.certify.cache.expire-in-seconds={'userinfo': ${mosip.certify.access-token-expire-seconds}, 'vcissuance': ${mosip.certify.access-token-expire-seconds}} diff --git a/docker-compose/docker-compose-injistack/config/certify-mock-identity.properties b/docker-compose/docker-compose-injistack/config/certify-mock-identity.properties deleted file mode 100644 index 39627ee0..00000000 --- a/docker-compose/docker-compose-injistack/config/certify-mock-identity.properties +++ /dev/null @@ -1,103 +0,0 @@ -## ------------------------------------------- Mock ID Integration properties ------------------------------------------------------------ -mosip.certify.integration.scan-base-package=io.mosip.certify.mock.integration -mosip.certify.integration.audit-plugin=LoggerAuditService -mosip.certify.integration.vci-plugin=MockVCIssuancePlugin - -## ------------------------------------------- Mock ID plugin related properties ------------------------------------------------------------ -mosip.certify.mock.vciplugin.verification-method=${mosip.certify.authn.jwk-set-uri} -mosip.certify.mock.authenticator.get-identity-url=http://mock-identity-system:8082/v1/mock-identity-system/identity -mosip.certify.cache.security.algorithm-name=AES/ECB/PKCS5Padding -mosip.certify.cache.secure.individual-id=false -mosip.certify.cache.store.individual-id=true -# TODO: Onboard secrets for local build -mosip.certify.mock.vciplugin.issuer.key-cert="dummy-issuer-cert" -mosip.certify.mock.vciplugin.ca.key-cert=dummy -mosip.certify.svg-templates=insurance-svg-template.json -mosip.certify.identifier=http://localhost:8090 - -mosip.certify.issuer.uri=did:web:vharsh.github.io:DID:harsh -mosip.certify.issuer.pub.key=did:web:vharsh.github.io:DID:harsh#key-0 - -mosip.certify.issuer=CertifyIssuer -mosip.certify.issuer.id.field.prefix.url=https://mosip.io/credential/ -mosip.certify.integration.data-provider-plugin=MockCSVDataProviderPlugin -mosip.certify.issuer.vc-sign-algo=Ed25519Signature2020 -## CSV specific config -mosip.certify.data-provider.identifier.column=id -mosip.certify.data-provider.fields.include=id,name,phoneNumber,dateOfBirth,highestEducation,typeOfHouse,numberOfDependents,works,landArea,landOwnershipType,primaryCropType,secondaryCropType,maritalStatus -mosip.certify.plugin.csv.file.uri=https://raw.githubusercontent.com/jainhitesh9998/digital-credential-plugins/refs/heads/develop/mock-certify-plugin/src/test/resources/farmer_identity_data.csv -mosip.certify.issuer.svg.template.id= -mosip.certify.key-values={\ - 'vd12' : {\ - 'credential_issuer': '${mosip.certify.identifier}',\ - 'authorization_servers': {'${mosip.certify.authorization.url}'},\ - 'credential_endpoint': '${mosipbox.public.url}${server.servlet.path}/issuance/vd12/credential',\ - 'display': {{'name': 'Insurance', 'locale': 'en'}},\ - 'credentials_supported' : {\ - 'FarmerProfileCredential' : {\ - 'format': 'ldp_vc',\ - 'scope' : 'farmer_vc_ldp',\ - 'cryptographic_binding_methods_supported': {'did:jwk'},\ - 'cryptographic_suites_supported': {'RsaSignature2018'},\ - 'proof_types_supported': {'jwt'},\ - 'credential_definition': {\ - 'type': {'VerifiableCredential','FarmerCredential'},\ - 'credentialSubject': {\ - 'name': {'display': {{'name': 'Name','locale': 'en'}}}, \ - 'highestEducation': {'display': {{'name': 'Highest Education','locale': 'en'}}},\ - 'dateOfBirth': {'display': {{'name': 'Date of Birth','locale': 'en'}}},\ - 'maritalStatus': {'display': {{'name': 'Marital Status','locale': 'en'}}},\ - 'typeOfHouse': {'display': {{'name': 'Type of House','locale': 'en'}}},\ - 'numberOfDependents': {'display': {{'name': 'Number of Dependents','locale': 'en'}}},\ - 'phoneNumber': {'display': {{'name': 'Phone Number','locale': 'en'}}},\ - 'knowsLanguage': {'display': {{'name': 'Knows Language','locale': 'en'}}},\ - 'works': {'display': {{'name': 'Employment Type','locale': 'en'}}},\ - 'farmingType': {'display': {{'name': 'Farming Type','locale': 'en'}}},\ - 'landArea': {'display': {{'name': 'Land Area','locale': 'en'}}},\ - 'landOwnershipType': {'display': {{'name': 'Land Ownership Type','locale': 'en'}}},\ - 'primaryCropType': {'display': {{'name': 'Primary Crop Name','locale': 'en'}}},\ - 'secondaryCropType': {'display': {{'name': 'Secondary Crop type','locale': 'en'}}}\ - }},\ - 'display': {{'name': 'Farmer Profile Verifiable Credential', \ - 'locale': 'en', \ - 'logo': {'url': 'https://sunbird.org/images/sunbird-logo-new.png','alt_text': 'a square logo of a Sunbird'},\ - 'background_color': '#FDFAF9',\ - 'text_color': '#7C4616'}},\ - 'order' : {'fullName','policyName','policyExpiresOn','policyIssuedOn','policyNumber','mobile','dob','gender','benefits','email'}\ - }}},\ - 'latest' : {\ - 'credential_issuer': '${mosip.certify.identifier}', \ - 'authorization_servers': {'${mosip.certify.authorization.url}'}, \ - 'credential_endpoint': '${mosipbox.public.url}${server.servlet.path}/issuance/credential', \ - 'display': {{'name': 'Insurance', 'locale': 'en'}},\ - 'credential_configurations_supported' : { \ - 'FarmerProfileCredential' : {\ - 'format': 'ldp_vc',\ - 'scope' : 'mock_identity_vc_ldp',\ - 'cryptographic_binding_methods_supported': {'did:jwk'},\ - 'credential_signing_alg_values_supported': {'RsaSignature2018'},\ - 'proof_types_supported': {'jwt': {'proof_signing_alg_values_supported': {'RS256', 'PS256'}}},\ - 'credential_definition': {\ - 'type': {'VerifiableCredential','FarmerCredential'},\ - 'credentialSubject': {\ - 'name': {'display': {{'name': 'Name','locale': 'en'}}}, \ - 'highestEducation': {'display': {{'name': 'Highest Education','locale': 'en'}}},\ - 'dateOfBirth': {'display': {{'name': 'Date of Birth','locale': 'en'}}},\ - 'maritalStatus': {'display': {{'name': 'Marital Status','locale': 'en'}}},\ - 'typeOfHouse': {'display': {{'name': 'Type of House','locale': 'en'}}},\ - 'numberOfDependents': {'display': {{'name': 'Number of Dependents','locale': 'en'}}},\ - 'phoneNumber': {'display': {{'name': 'Phone Number','locale': 'en'}}},\ - 'knowsLanguage': {'display': {{'name': 'Knows Language','locale': 'en'}}},\ - 'works': {'display': {{'name': 'Employment Type','locale': 'en'}}},\ - 'farmingType': {'display': {{'name': 'Farming Type','locale': 'en'}}},\ - 'landArea': {'display': {{'name': 'Land Area','locale': 'en'}}},\ - 'landOwnershipType': {'display': {{'name': 'Land Ownership Type','locale': 'en'}}},\ - 'primaryCropType': {'display': {{'name': 'Primary Crop Name','locale': 'en'}}},\ - 'secondaryCropType': {'display': {{'name': 'Secondary Crop type','locale': 'en'}}}\ - }},\ - 'display': {{'name': 'Farmer Profile Verifiable Credential', \ - 'locale': 'en', \ - 'logo': {'url': 'https://sunbird.org/images/sunbird-logo-new.png','alt_text': 'a square logo of a Sunbird'},\ - 'background_color': '#FDFAF9',\ - 'background_image': { 'uri': 'https://sunbird.org/images/sunbird-logo-new.png' }, \ - 'text_color': '#7C4616'}}}}}} \ No newline at end of file diff --git a/docker-compose/docker-compose-injistack/config/certify-mock-mdl.properties b/docker-compose/docker-compose-injistack/config/certify-mock-mdl.properties new file mode 100644 index 00000000..bf1357ea --- /dev/null +++ b/docker-compose/docker-compose-injistack/config/certify-mock-mdl.properties @@ -0,0 +1,105 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at https://mozilla.org/MPL/2.0/. + +## ------------------------------------------- Plugin enable properties ------------------------------------------------------------ +mosip.certify.integration.scan-base-package=io.mosip.certify.mock.integration +mosip.certify.integration.audit-plugin=LoggerAuditService +mosip.certify.integration.vci-plugin=MDocMockVCIssuancePlugin +mosip.certify.plugin-mode=VCIssuance + +##commons +mosip.certify.data-provider-plugin.issuer.vc-sign-algo=Ed25519Signature2018 +mosip.certify.data-provider-plugin.issuer-public-key-uri= + +## ------------------------------------------- Plugin specific usecase properties ------------------------------------------------------------ +mosip.certify.cache.secure.individual-id=false +mosip.certify.cache.store.individual-id=false +mosip.certify.cache.security.algorithm-name=AES/ECB/PKCS5Padding +#TODO:Onboard issuer key and certificate data here format - "$base64EncodedPrivateKey||$base64EncodedCertificate" +mosip.certify.mock.mdoc.issuer-key-cert= +mosip.certify.mock.vciplugin.mdoc.issuer-key-cert=${mosip.certify.mock.mdoc.issuer-key-cert} + +## ------------------------------------------- Host values of connected services ------------------------------------------------------------ +mosip.injicertify.mock.host=localhost:8090 +mosip.api.public.host=api.collab.mosip.net + +## ------------------------------------------- UseCase specific default overriding properties ------------------------------------------------------------ +mosip.certify.domain.url=http://${mosip.injicertify.mock.host} +mosip.certify.identifier=${mosip.certify.domain.url} +mosip.certify.database.name=inji_certify_mock + + +mosip.certify.key-values={\ +'vd11' : { \ + 'credential_issuer': '${mosip.certify.identifier}', \ + 'credential_endpoint': '${mosip.certify.domain.url}${server.servlet.path}/issuance/vd11/credential', \ + 'display': {{'name': 'Transport Department', 'locale': 'en'}},\ + 'credentials_supported': {\ + {\ + 'format': 'mso_mdoc',\ + 'id': 'DrivingLicenseCredential', \ + 'scope' : 'sample_vc_mdoc',\ + 'cryptographic_suites_supported': {'ES256'},\ + 'proof_types_supported': {'jwt'},\ + 'claims': {\ + 'org.iso.18013.5.1': {'given_name': {'display': {{'name': 'Given Name','locale': 'en'}}},'family_name': {'display': {{'name': 'Family Name','locale': 'en'}}},'issue_date': {'display': {{'name': 'Issue Date','locale': 'en'}}},'expiry_date': {'display': {{'name': 'Expiry Date','locale': 'en'}}},'birth_date': {'display': {{'name': 'Birth Date','locale': 'en'}}},'issuing_country': {'display': {{'name': 'Issuing Country','locale': 'en'}}},'document_number': {'display': {{'name': 'Document Number','locale': 'en'}}}}},\ + 'display': {{'name': 'Mobile Driving License', \ + 'locale': 'en', \ + 'background_image': { 'uri': 'https://${mosip.api.public.host}/inji/mosip-logo.png' }, \ + 'logo': {'url': 'https://${mosip.api.public.host}/inji/mosip-logo.png','alt_text': 'a square logo of MOSIP'},\ + 'background_color': '#5F8A8B',\ + 'text_color': '#7C4616'}},\ + 'order' : {'org.iso.18013.5.1~family_name','org.iso.18013.5.1~given_name','org.iso.18013.5.1~document_number','org.iso.18013.5.1~issuing_country','org.iso.18013.5.1~issue_date','org.iso.18013.5.1~expiry_date','org.iso.18013.5.1~birth_date'}\ + }\ + }\ + },\ +'vd12' : {\ + 'credential_issuer': '${mosip.certify.identifier}', \ + 'authorization_servers': {'${mosip.certify.authorization.url}'}, \ + 'credential_endpoint': '${mosip.certify.domain.url}${server.servlet.path}/issuance/vd12/credential', \ + 'display': {{'name': 'Transport Department', 'locale': 'en'}},\ + 'credentials_supported' : { \ + "DrivingLicenseCredential":{\ + 'format': 'mso_mdoc',\ + 'doctype': 'org.iso.18013.5.1.mDL',\ + 'scope' : 'sample_vc_mdoc',\ + 'cryptographic_binding_methods_supported': {'cose_key'},\ + 'credential_signing_alg_values_supported': {'ES256'},\ + 'proof_types_supported': {'jwt': {'proof_signing_alg_values_supported': {'ES256'}}},\ + 'claims': {\ + 'org.iso.18013.5.1': {'given_name': {'display': {{'name': 'Given Name','locale': 'en'}}},'family_name': {'display': {{'name': 'Family Name','locale': 'en'}}},'issue_date': {'display': {{'name': 'Issue Date','locale': 'en'}}},'expiry_date': {'display': {{'name': 'Expiry Date','locale': 'en'}}},'birth_date': {'display': {{'name': 'Birth Date','locale': 'en'}}},'issuing_country': {'display': {{'name': 'Issuing Country','locale': 'en'}}},'document_number': {'display': {{'name': 'Document Number','locale': 'en'}}}}},\ + 'display': {{'name': 'Mobile Driving License', \ + 'locale': 'en', \ + 'background_image': { 'uri': 'https://${mosip.api.public.host}/inji/mosip-logo.png' }, \ + 'logo': {'url': 'https://${mosip.api.public.host}/inji/mosip-logo.png','alt_text': 'a square logo of MOSIP'},\ + 'background_color': '#5F8A8B',\ + 'text_color': '#7C4616'}},\ + 'order' : {'org.iso.18013.5.1~family_name','org.iso.18013.5.1~given_name','org.iso.18013.5.1~document_number','org.iso.18013.5.1~issuing_country','org.iso.18013.5.1~issue_date','org.iso.18013.5.1~expiry_date','org.iso.18013.5.1~birth_date'}\ + }}\ + },\ + 'latest' : {\ + 'credential_issuer': '${mosip.certify.identifier}', \ + 'authorization_servers': {'${mosip.certify.authorization.url}'}, \ + 'credential_endpoint': '${mosip.certify.domain.url}${server.servlet.path}/issuance/credential', \ + 'display': {{'name': 'Transport Department', 'locale': 'en'}},\ + 'credential_configurations_supported' : { \ + "DrivingLicenseCredential":{\ + 'format': 'mso_mdoc',\ + 'doctype': 'org.iso.18013.5.1.mDL',\ + 'scope' : 'sample_vc_mdoc',\ + 'cryptographic_binding_methods_supported': {'cose_key'},\ + 'credential_signing_alg_values_supported': {'ES256'},\ + 'proof_types_supported': {'jwt': {'proof_signing_alg_values_supported': {'ES256'}}},\ + 'claims': {\ + 'org.iso.18013.5.1': {'given_name': {'display': {{'name': 'Given Name','locale': 'en'}}},'family_name': {'display': {{'name': 'Family Name','locale': 'en'}}},'issue_date': {'display': {{'name': 'Issue Date','locale': 'en'}}},'expiry_date': {'display': {{'name': 'Expiry Date','locale': 'en'}}},'birth_date': {'display': {{'name': 'Birth Date','locale': 'en'}}},'issuing_country': {'display': {{'name': 'Issuing Country','locale': 'en'}}},'document_number': {'display': {{'name': 'Document Number','locale': 'en'}}}}},\ + 'display': {{'name': 'Mobile Driving License', \ + 'locale': 'en', \ + 'background_image': { 'uri': 'https://${mosip.api.public.host}/inji/mosip-logo.png' }, \ + 'logo': {'url': 'https://${mosip.api.public.host}/inji/mosip-logo.png','alt_text': 'a square logo of MOSIP'},\ + 'background_color': '#5F8A8B',\ + 'text_color': '#7C4616'}},\ + 'order' : {'org.iso.18013.5.1~family_name','org.iso.18013.5.1~given_name','org.iso.18013.5.1~document_number','org.iso.18013.5.1~issuing_country','org.iso.18013.5.1~issue_date','org.iso.18013.5.1~expiry_date','org.iso.18013.5.1~birth_date'}\ + }}\ + }\ +} diff --git a/docker-compose/docker-compose-injistack/config/farmer_identity_data.csv b/docker-compose/docker-compose-injistack/config/farmer_identity_data.csv index f1686362..c9dfe1fe 100644 --- a/docker-compose/docker-compose-injistack/config/farmer_identity_data.csv +++ b/docker-compose/docker-compose-injistack/config/farmer_identity_data.csv @@ -1,8 +1,6 @@ -id,name,phoneNumber,dateOfBirth,highestEducation,typeOfHouse,numberOfDependents,works,landArea,landOwnershipType,primaryCropType,secondaryCropType,maritalStatus -4567538768,John Doe,9876543210,1980-05-15,Bachelors Degree,Farmhouse,3,Full-time,50.5,Self-owned,Wheat,Vegetables,Married -4567538769,Mary Smith,8765432109,1975-08-22,High School,Ranch,4,Full-time,25.75,Leased,Rice,Pulses,Married -4567538770,Raj Patel,7654321098,1990-03-10,Primary Education,Cottage,2,Part-time,15.25,Family Owned,Cotton,Maize,Married -4567538771,Sarah Johnson,6543210987,1985-11-30,Diploma,Ranch,1,Full-time,35.5,Self-owned,Sugarcane,Rice,Single -4567538772,Kumar Swamy,5432109876,1970-04-18,No Formal Education,Cottage,5,Full-time,45.0,Self-owned,Maize,Wheat,Married -4567538773,Li Wei,4321098765,1988-09-25,Masters Degree,Farmhouse,2,Part-time,20.5,Leased,Vegetables,Fruits,Married -4567538774,Arun Kumar,9876543211,1987-06-20,Diploma,Cottage,2,Part-time,22.75,Family Owned,Rice,Cotton,Married +id,fullName,mobileNumber,dateOfBirth,gender,state,district,villageOrTown,postalCode,landArea,landOwnershipType,primaryCropType,secondaryCropType,face,farmerID +2154189532,Gorge Cooper,9876543210,25-05-1990,Male,Karnataka,Bangalore,Koramangala,453000,3 hectares,Owner,Maize,Rice,"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABwAAAAFCAYAAABW1IzHAAAAHklEQVQokWNgGPaAkZHxPyMj439sYrSQo51PBgsAALa0ECF30JSdAAAAAElFTkSuQmCC",987654321 +8267411578,James Rodrigious,8765432109,12-11-1985,Male,Uttar Pradesh,Lucknow,Gomti Nagar,226010,2.5 acres,Tenant,Rice,Wheat,"data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAIBAQEBAQIBAQECAgICAgQDAgICAgUEBAMEBgUGBgYFBgYGBwkIBgcJBwYGCAsICQoKCgoKBggLDAsKDAkKCgr/2wBDAQICAgICAgUDAwUKBwYHCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgr/wAARCACBAH0DASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD8afAXw+8B6trH9lat4djuUkulDSGV0YDPPKsK9Mvfg98AvB3xIs9G1P4bpqOmXJ4WTWbyHau4DA8uYep712nxf/Zw/wCFRfFCVNAsV+yTzkwLjHljIAAA7V55451q4v8AxHALtXU20WYwwwecMK4cPivaaHbXw3sq3sz6csf2Kf2Ftaso9UtvgBbqkq7kRfEup4I/8Ca19I/Yh/YNRB9q/ZrtnIPzE+K9WBI7j/j64z7Vm/A7xBear8OdJuZ2J/0Uc59zXeQ3ZZtwbvWybT3OJRTR8Kf8FG/hj8Evhb8btJ8MfA/4eReGNMuPCUV3c2EGp3V2GuDd3abt9zJI+fLji4zj2r54e3TGVNfRH/BTqUQftD6RIzcP4QhOfc3V0P6CvnhGbBXNb7oerGJERnJpJNxY4qbJI5PeoGkkMu1T3pqyFa71G7GZgDDvLMAF9TXvPwk+DHgU+CxqHjixSe5vdssMZHMCYIZcggj1rxnRYp31OAQwpJIsqsEc4Bwa9xPiuz0XRZ5dULJc3ELMqRjcsfBGAfSvPx1SqopQep62X0qd+dnN2nwn8GeKvibJ4S8L6XHHaRykPNNPIwVRjuWPYmv0Y/Yn/wCCDnwc+K9vZ+NPizDqA0i6QSQWazyxPeqf44h5kREYIIOMn3rwP/gkB+zRbfGv4qy/ELxRA1zpNjc7pLOdP3U7bQw3Ht0xxX7y/BnQ7a0sIZcCQuoMajlUHopHUV8vnGZYylWVOnUPt8pyfBuh9YnTPmux/wCDdL/gl9LppnPwJuzIMYb/AIS3WB+gvMV45+0P/wAG437NC6Hd6l8EPCU2nXK5+z20mp3M65IOP9fM/Nfq7pfmR23kvxVLxTbN9hlwOMUqmIzFUeb2hVHLcteI0gfyxftZfsC+PP2X/Fj+H/F3g84Qtul2McYOOcDivEprLwxpz+RceHrZm9Wz/jX9LX7WP7MPw8+P+gXGi+K9DtzIyHZcsuWB59Tivwb/AG8P2VpvgH8c77wdp+nNLZiWT7JIiZygIHbjvXTlOd1KkvZ1dTjzTIcPSfPTPtb9u3wymj6imo2zqkkc6gOrD7m/5ua+OPjXZ6Xf6wutaRMjB1IfYQRkmvsH9urWbuG7m0HWdPCq0mElbOCucHnpXxJNpiN4tn8PWl3ILdZgYo9vBHY4/OujKWuVX2PFzumvban1J+zN4Z1O8+FGk4ty2bVegJ7mvVNN+GPii9lCWekSnPrGR/SvRP8Agl98H7P4gLo/hjUIMxpZEkFc8jmv1D+Hv7GXwx0mNbi90SKWRSPvRf8A169+lhpVHd6HydSr7LRI/mF/4K1eE9S8NftF6Fp2q25hlPgq3cxnqP8ATLwZx74/T2r5kkLYLIT7V+oX/B2v4T0vwZ/wUU8D6L4fskgg/wCFGaW6xoMAf8TnWh/QV+X9qVbhzxXRfl+Q07CQi5l2wxjLMwVR6k11Vv8ACDxdDZjUr6zjiR4i6ySSYGB7nv7Vl+EoYH8Swm9H+jod5bHQg5FdRrfjjXPFV2mj6xr03kGVY4LYsCsQJ7fTNYzqvc6YRUpWE+DXw8m8QeIJr/UpWEEEL528jftyBU/xI1iawgW0C5dTsCZ/hJ5r17wt4MtfC3gCbRvD9tcfaHAkuL+dNrSFQfucYZSOp5rwjx1dTXPiLzbiQuqSfOT9a8ajXeKxT7I96rhfquEV+p+nP/BGrxf4t8BfBqCz8HeB4tSuLu9ubu8utQn8i1jiAVYozLnAPDYGOCa/QvwB+3/o/g7WLfR/ij8JNT0yaYgfb9Ju4ryzU5xzICvfofrXxF+xV+zJ8R/iR+wloLfBDxkNE1S7sFuWkK8ThpHlK5HIbOAD2Ir3j4BfskftVaN40v4tf+N2t6r4dh0+JLTSdeeN/tMh3earkx9MHG7IPpXzNf2dXG1O59zhVVoYOlzH6IeFPinoHiXSU1uxvGaGVdyFlwcc9fSvMPjZ+3v4B8A6v/wg2mfD7xDr+pB9jjSrXKKc459eo54FN+Gvh9vBvw98Q6TOyzSWGUs5Mgkjyye3fNeMfHf9mr4x61pOo3/wv8XXVlcT6U8tnqVvLGss11hcK4bAC8tyOflHrXPTxFWvL2Z01cNCF53Ol8dftFXV74bl1zXvg7rWmwOMtKLu1kKDn/lispkB+tfnj+374MPjr4gaTrcEBbfZSliR3L17b8EP2dv+ChOieJrSH4hfEA61ootn/tOW9ulWQt22qO2M+v1qr+0vo3h/SfF1vpeoSlBBE6xAL23fWudSpYTFO7NYUvrVMo/8FDvhrYeK/hNJqsOmrJfQXcJRiOdu4k18LaJ8C/Evi/x1pEnhmzR7q5iAuTI+0YD8DP8AwI/nX6UftX2N5cfCnUUglaOZRwV6gYavPv8Agnz+yNceP/CKeJ/FGpXBuruDzNPDRqQ8ZGCcn/awPxr28FifZULo+fxWAWPxmp9S/wDBJv8AZr8YeA7yTXPE9pBGLdTHCY5gxwU/Tmv0W0yIrDg8V87/ALDXgyPwd4OuvC8cwdrG4SJ8Y+U7Se1fRsEnluI84zX3GW1atbCc8z89znCUcLmHJT6H85n/AAeESGL/AIKXeAgDyfgNpg/8rWt1+UsS7ecnrX6q/wDB4U5f/gpn4Gz2+BOmAf8Ag51uvyo3sqnmqSZy043aRPHqNzaviI/rV/w7cW914ls7nVhmNblDJxngMDWXbw3F3L5duhZj0ArqPBfw61bUIbvXNSYxQWj7XVzgkkZ4B6isqsVynVS5vbnvniX4v3N3oF34e8C2YsbOM7Wuo8q0wwecHg9ccV4pPYaddeIrK11S4IiusG6cj7rbsZ/Kt3wfq2seJrB9H0aF5Y7chIhg9MZrUl/Z98X6hbnXtTCww7grRvIA3Psea8CPscNUd9D6DEe1xVKy6H7Gf8EMPHumar+zrodrBdE2mnvJYw+3lOwPHbsfxr9IfGHin4faZ4fafiS5MZHyJlsnPYGvxa/4I1eIvFPh7wVrXgDwo6/8SfxIh8vzMfLJDvwfqY5M/Uetfd2rfFqz8G31r4W+Kd/f/wBo6xaSGzSzhMkkqcq2Mc5+gr43Ht0sbUhD1P0jBUIYrAUud2se/wDhqTTpvAupasCymSdSQ64YfKeorf8AhV4w8Jat4ej0nVoVZ7dRGrOvf86+YtC1VrPTR4b0L4w6vomkR4FxpWraJK9zIR02S4B6cc9zXSad8c/gn8MNDk0O41HXZrq6cKjX2iXUs0smCFMbDcP061lClUbudNXDxqKpTZ738Wb3RNB0AG0hiTMJBljOcZz71+bP7TtheeNviLNJo+mm9S0Z43kZTwSQe1fUnxF134qS+Hzpk3Nq6bre5ll2yyRjOSy44NfCn7Q3jTxzZ+Nm0r4d/HaPwpNb7v7Tt50ObonBjm47Ebh+FTDBSzGroNYqjlmGVz6k+P8AZW19plzpTn5JQVxjrnI/rXp/7PXg1vhh8N/CGo6fcssOn6HbRzRJjcoZ0mPA57Y/GvHfi1ryXWolVfcIpwzL6kHOK+gNWuLHwb8P5rOfUBaSQ2abLnIGI/L4GTxnbgY9q9Olf2Vzw4Vv9otsdx+xX8XYpPip4k8CT2xJnkhulcqed0bfyAH5mvq4xv5+4+vFfJH/AATb8EP421vWvi/e2qxxtOY7Z+7RbW2dfbn8a+wNqSAsDX6VgoKlgaaZ+SZhi1i8zqVD+b7/AIPCWx/wUw8CEH/mhGmZ/wDB1rdflVGwZCGr9U/+DwoAf8FMPAgH/RCNMz9f7a1qvyrgAKnNN2bJprY1fDBvbTVIruzhVwrDcHbAxnnJr23xi7aj4TtJbTS4oSloTdpbktvbJ5P4V43odzBBp0wlbgxsu31BB4q3pXxP8UwWzxnWZlR1KtEG4IIxXJicPKqz0MNXhTi7lj4e/ETU/BHjmPU/D7t5Ly7XgYlRg4Gfwr6WvviZ4d1fw35mu6oZbqUhoERhIw69cdOfavkOKS4n1fdaDLscgV2P2LWtBsU1Zt0NzPgxsp52ng1y5hgKVZx8jpwOMdN+5sfUX7CH7XVh+zh+0XeWnijUzDoniVkh1KRWz9nuQwWOUDuQGPWv2W8W3Wo/F/4daN4q8H6vsv7RVeyuIZBlXy2CDz69a/m3v9Nu5orjVZLozmVsz+aQPmI/nX7If8EwfjP4u8Bfs0eB9R16e5v9JbTYku/OUlrZi7AKFA+7jJJPSvm8+wlOlRWJ7H2PCuY1K1d0p9D74+Gn7SPx/wBB0t7Dx34Rnv78L5cVzYaelwFJBGDKVBGTjvVK20jxR4m8aJ8T/jQM3GnSl9KsE8s/ZcjrNglhIDnHsa6vwX+0D8IjoC3FtqdmwaPcrPKo3Lg5x83NeQfGz9pPU/Gt5ceBvgLorXtzJkSzzrshtj/dzk54OcYrw54+9K6R9Z7al7Zqnh9TB/bJ/af0vwppMj6XI811FYv9mgt1LkK2cFgvKgnHNfjZb/tq+NfAXxM8Y/EDXfAWka/eeJtYEey/vXAs4LQGOJEK9VIcnn0r9UPif8C7zwb4Q1jxP4j15dU1y6s2865uIkhZUQMVgjVT/qxgflX4ffHjw9r3hfxzNZfZPLyzHAJ9a9LhetSdSaW58txRSxio00ftp8VLr+y2udV24WO9SRj/AHkByR+OK8+8Tftc/FD44araeHvEFqtpZsRHNa2crOJQW6kEehxxXX/GC9k1XS7iytDuYoXx7AHNYn7DHwL1L4k/FO1vjYeZHDKDuxnHINenkuEpVqup4XEGPrYVq3U/WP8AYq8Dx/Dz4DabpCAK81ujTBf7w3CvW7b5YzWF4A0FPDnhWy0hF2+TCFxj3Nb+0gYr7VnxMkoxv1Z/N9/weEoW/wCCmXgUHv8AAnTMf+DrW6/K2OMJGa/VX/g8Kf8A42YeAiD934D6WD9f7a1uvyrM4SPLnqeMVlZ8xpBvlQ5bpfLMBPU1C0WH2rmpdKtJL3UVihtJJXZwqxhCSxJ4AAr2/wCGX7Av7SnxfuYrvw38Obu0tJSMXF/G0EYz0BLCsMRisPg1z1Klj0MFlmaY+ryYak53PHvC729vrEU0rHOcV6v4z0XXfENxo2haNZvPcvYwNAkYJLmVm+Xj0+X8TX0LpH/BHPXfBHh278efGLx3FpzWds8gt7V0ljLhSQMjJ6jrXuX/AATw/ZYFukHxc8RQCdoIfJ0zzgBmGRclvbkV8vmfEmApU/bUZXP0HI+BM1r1VRxlP2Z4v8Hf+Cbes+HfAreNfjTYGSa6KS2ehmPcGYg7fMHDLzj6A1+g37Cfw6XQvhZp/wAPtYgWJo7PZKi8/MAf8a7fSfhRe+L/ADr7T7RJ47KQRIrN7A4rrvgr8PNW03x8Y7jSfJU7twUHAbAxXx1TNMVmVG9TY+wqZXl2SYz2dO1zo/DX7Ofw6khW31vwVaXTxEBZpkO79DXf+F/hf4d8Mf8AIC0yO2iHSOJcAV22k+E7nIFzDg1sf2DbQhodmSAcDHeuNUmndnDUrJqyPm39pLwnd+I7N9MSLcjNtx7E/wD16/NP9sj9izwnq/xDgbQ7PfNHC4vx5YG2Td0/Kv1v+Mup+HvCelTajdSpJqHIt7EkfM5zgnByBnHPavjzx+nh7Q9YJ8QFJLy5Z5bi5flpnLZLHnqSa0wuK+q1Wunke/hMkpZrSXtXYm+DmhR/E3Q7vxlrdsbO11GVfsDTKVENu/yknd90ZPevu39in9jm0+CUcOs28kMsdzDvhniYEMCMA5HrX51/8FDNVbwR+xt4i03RblbeJ7S2trSBHA+9dR4QD6Bj9AT2r27/AIN9f+CnM3xU8MWv7GHxx8XW83iDw/b+b4R1K+cRG/08gRiKY4wWjYMVx2AzxX6bw9S/dVKiPxLi5SdanA/UVYnA3EdKc74OeakeREVAHBVxkYOajlaEttQ5zX0EXdnx8ZSqbn83v/B4Kxl/4KXeCAP+iF6X/wCnnWq/Mj4XfDTxR8WvHFj4J8J2xuL2+m2Qx54GBksTzgADrX6c/wDB4CAn/BTLwMEzz8CNM3fX+2daryD/AIIj/Ae38QeN9W+MerWuU06IWmnyEZBkdSXGe3ykfpXl5tjVl+EnXPqeHMs/tXMqeHXU+sf2Sf8AgmB8Ifgx4YtdZ8SeHLfVNbSIST6lcwAvFIAeEIOCDwc19EeG30iPRJXgiMc9s6rcBlx2ycevFeiaVpq/8I7DEybSI/nX35ry/wCJGga7HqbDSb10jll2uqkfdJwf0r8RxOOxuNxDq1Gf1BlmV4XL6CpUOh5x8eNFuvjWf+Fa+HXAtLo5vpi2P3YOGHPBypNek+C/COmeEbO08K6Fp8dvplhYmKBYugCjCDHt0qbwz4K07wpbSPDaQyyTD/XSNh+mOla8Mf2XR2SPrj+hrllUl7K1z0eV+1527npX7LPnpaXLSaYz2z6jIzTKhJ3+XHkflt/M17r4W0Lw82tT6hKxSRpcp5iY7e9edfst61Y2PwpZLRJnm/tVjcbIiQCY4vSvR7xLvVmNxa6Y554d0IxX1GBVOnh031PynO3WrY+ozukhssiRrmMgtgYcHrXDfHHx6fCFt9j8O28b3+0/fcrzn1FW40m0LQ5NT1TCLChYMD/EASK8P8SeL9R8ba7NrV3ICBJhDuzwajHV40oK24siyqtiJ3bOD8V6L4o8Va7L448W6q4uzu2QbwyRg9QD+FfKP7VmpaxN41t4rK+tlMcTiQSXIXnd29a+w/GF8biGSyLZDdq8yufCmgWd7NLc+Gba4kmfc8kmc5/A148ddWz9MwuFpU6ap9j5f/4LOfECw0rQfDHwm0rUALm+vG1S8iiYExpFuijjPoMyynnnivjHTdb1DwZDpPi/wjrd3peq2VzHPa3NjP5TxyBuGz3HqO9T/Gf4teK/jb8Tr74ieOZmuL29kzEjybhbpnOxT6ZJPPrWFrSedDDB2Uc/XNfuWAw/1SgqZ/J+a46OOxnOz90/+CK3/BXBP2ntMh/Zq/aS8U2cfj2wgY6NrFxNsXV4M4LzHHEnHABPXmv0Shilwtx50ZQruyJAcD3r+R3SfFfiXwnf23iDwxq93pd7ZOGt9Q0+ZkmjIOeCpyORX2T+y7/wXw/bz+Bd1Bpvizxfa+PdAaMxzW3iiBXudh4x533ycZ5J+teh7RR2PBcLJmJ/weBQTD/gpn4FLIQH+Bel9fQ61rQ/xruf+CSfw/8A+EA/ZW8NNcRbJdbv7i/uDjrvwIf/ACHEPzxXy1/wWt/bksv+Cmf7ZHgP4qaF8PrnQryy8AWGg6hp9zfGZZJY9U1CX91x93/SccdTX6I/s7+CrL4ffDrQfBMo2R6XpccCgDvGuB/LNfBccYm2ChS7s/WPDDAyeOni/wCQ9++3wQaZES/JTMn1rifEOoR3OvpHE+YyDuP41FN4kuNUMlhBcEbWwxB6GqDRwWN1snumd89WFflibtsf0BTpJyuupo69DAI0mtmyUYAfTPNPmeJrMRseZBlfpWfLeh5hb7s7mwPrWvHYSzm306O1VrnzFjhDHqSen51iqcvrKQ6/7iDe+h9N/svafongz4UQNNaN5mpCOd2WMkkgEV6HL4r0uH5Bf3CoT/qfK/pXJaB8PPEum+F9GsbPWp7drWz2NCuAo+YmrV1puraVK1/rMccvl9bgyZINfZ0XVp0D8dxkYYjG1Glucr+0r8WtNsfD8PhjRJJvNuSvmI8ZXjdg/pXkUT2+l6SdrYY4I4o8c+KX8e+OZ9WZy1tG7CBj/dPNZupTtcX6WSHMYBHWvnMXWlVq2P0DKMu+r4KCW5GRLqMn2lxmsrWrOT7Wdi8c10EqDTLYpGcAVkzXqTvvZ+frWDex78Yvksj8PmJlvhcZz71eaM3DZ61V02Dzx0rZt7PyecV/Qq7H8XtLm0KN5bmCwbt6VlWcJkXzlGWre1v/AI82U+tU/D9mZYQ4Bq4yigV2WfgN8Mx8Uf23/BNjNbebHpmmJqF0uM48mSZl/wDInl/nX6xziXTrRZZD82K/PD/gnxbpD+3dLv6f8K4mL/X7bHiv0B+LustpXgK41W0c+fEuVx9DX5ZxrVlUzCnSP6G8LsPRo5HVxD3MvwX43uZvE+q2L7yyXfy4BxjbXf28djqMP26UbpgeFI614j+zR4hufF1tNrl4x86ZgZsn1XmvY7eQWs4a1OYx3r4ydP2VZ3P0nCz9tRLqWi3jiSGECWKdcqO3Oa7/AOGmkT+IPipodq8e9f7SgeZSeNolXOfwrh9GvUGpu8R/1zbm+tesfs0SQ3Pxtt7S4b5fsspH1AFbYenzYynY8/MKjp5dU5j6ueymuJBIbyQD+5jivJf2pviIfB/hk+H9JuP9Mu2UGPOMoTgn8jXr2vX0Gm2stzPKYkQH94vr2B9q+LfGni3Vvir8RbzxPqczG1jmZLJWPCR8bQPwAr3swrqlRPz3hjL5YzMva1P4cGVtMSKx0pICcSFeR71HElz54uM4x3Jq5JbwG7DyHmq3ifXtM0XTXkK+YwOAmM5P4V8rZuzP1aDS0RH4qvr27it9NsXXzpsFnD9OcVv+F/B2nWdiYdat47iUY+djn+Vcj4Nj1C7tZ9f1SzjCSzf6IrPzGuBkY7cmtGXxrPaOY1l/WuqlaT1FGM5n4heH/wCH61ut978aKK/oGXxn8Wx3M7W/9Q9P8J/8ew/CiisX8RrT2keo/sF/8nzX3/ZOJf8A0vhr7t+MP/JPrr/rif5GiivzHjD/AJGdM/oLw0/5JeZ57+xv/wAgW7+o/wDQDXt9h/yDjRRXxuJ/jH6JhSx4b/5CCV67+zX/AMl6tf8Ar0m/pRRXThv96gcOcf7lUPqX4wf8k/1T/rm3/oBr430H/kEj/fFFFdOabM+U4V/3ep6suXf/AB8VynjX/j9i/wCvhaKK8dbfd+aPvKeyOln/AOQWn+7/AI1x2t/8fh/GiiuiH8Rndh/jf9dD/9k=",123456789 +5860356276,Jane Thompson,7550166914,24-01-1998,Female,Karnataka,Bangalore,Koramangala,560068,5 acres,Self-owned,Cotton,Barley,"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABwAAAAFCAYAAABW1IzHAAAAHklEQVQokWNgGPaAkZHxPyMj439sYrSQo51PBgsAALa0ECF30JSdAAAAAElFTkSuQmCC",4567538771 +654321098,Sarah Johnson,6543210987,15-02-1988,Male,Tamil Nadu,Madurai,Melur,625106,1 hectare,Owner,Banana,Mango,"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABwAAAAFCAYAAABW1IzHAAAAHklEQVQokWNgGPaAkZHxPyMj439sYrSQo51PBgsAALa0ECF30JSdAAAAAElFTkSuQmCC",4567538772 +543210987,Arun Kumar,5432109876,22-09-1995,Male,Karnataka,Bangalore,Koramangala,560034,2 acres,Tenant,Tomato,Peppers,"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABwAAAAFCAYAAABW1IzHAAAAHklEQVQokWNgGPaAkZHxPyMj439sYrSQo51PBgsAALa0ECF30JSdAAAAAElFTkSuQmCC",345678910 diff --git a/docker-compose/docker-compose-injistack/config/mimoto-default.properties b/docker-compose/docker-compose-injistack/config/mimoto-default.properties index deffd6d6..ded8fe45 100644 --- a/docker-compose/docker-compose-injistack/config/mimoto-default.properties +++ b/docker-compose/docker-compose-injistack/config/mimoto-default.properties @@ -41,12 +41,10 @@ mosip.inji.minStorageRequired=2 # START bootstrap.properties -spring.cloud.config.uri=http://nginx/ +spring.cloud.config.uri=http://inji-web:3004/ spring.cloud.config.name=mimoto,inji spring.application.name=mimoto - -#config.server.file.storage.uri=https://raw.githubusercontent.com/mosip/mosip-config/collab1/ -config.server.file.storage.uri=http://nginx/ +config.server.file.storage.uri=http://inji-web:3004/ management.endpoint.health.show-details=always management.endpoints.web.exposure.include=info,health,refresh @@ -260,7 +258,7 @@ mosip.openid.issuers=mimoto-issuers-config.json mosip.openid.htmlTemplate=credential-template.html mosip.oidc.client.assertion.type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer mosip.oidc.p12.filename=oidckeystore.p12 -mosip.oidc.p12.password=mosip123 +mosip.oidc.p12.password=mosip123securepassword mosip.oidc.p12.path=certs/ diff --git a/docker-compose/docker-compose-injistack/config/mimoto-issuers-config.json b/docker-compose/docker-compose-injistack/config/mimoto-issuers-config.json index 13be6792..9a0ebd91 100644 --- a/docker-compose/docker-compose-injistack/config/mimoto-issuers-config.json +++ b/docker-compose/docker-compose-injistack/config/mimoto-issuers-config.json @@ -1,29 +1,56 @@ { "issuers": [ { - "credential_issuer": "Mock", + "credential_issuer": "Farmer", + "issuer_id": "Farmer", "protocol": "OpenId4VCI", "display": [ { - "name": "Farmers Credentials", + "name": "Agriculture Department", + "logo": { + "url": "https://mosip.github.io/inji-config/logos/agro-vertias-logo.png", + "alt_text": "agri-logo" + }, + "title": "Agriculture Department", + "description": "Download Farmers Credentials", + "language": "en" + } + ], + "client_id": "wallet-demo", + "redirect_uri": "io.mosip.residentapp.inji://oauthredirect", + "token_endpoint": "http://localhost:8099/v1/mimoto/get-token/Farmer", + "authorization_audience": "https://esignet-mock.collab.mosip.net/v1/esignet/oauth/v2/token", + "proxy_token_endpoint": "https://esignet-mock.collab.mosip.net/v1/esignet/oauth/v2/token", + "client_alias": "wallet-demo-client", + "qr_code_type": "EmbeddedVC", + "enabled": "true", + "wellknown_endpoint": "http://certify:8090/v1/certify/issuance/.well-known/openid-credential-issuer" + }, + { + "issuer_id": "MockMdl", + "credential_issuer": "MockMdl", + "protocol": "OpenId4VCI", + "display": [ + { + "name": "Transport Department", "logo": { "url": "https://api.collab.mosip.net/inji/mosip-logo.png", "alt_text": "mosip-logo" }, - "title": "Mock Identity", - "description": "Download Mock Identity Credential", + "title": "Transport Department", + "description": "Download Mobile Driving License", "language": "en" } ], - "client_id": "mpartner-mock-testing", + "client_id": "wallet-demo", "redirect_uri": "io.mosip.residentapp.inji://oauthredirect", - "token_endpoint": "http://localhost:8099/v1/mimoto/get-token/Mock", - "authorization_audience": "https://esignet-mock.dev1.mosip.net/v1/esignet/oauth/v2/token", - "proxy_token_endpoint": "https://esignet-mock.dev1.mosip.net/v1/esignet/oauth/v2/token", - "client_alias": "mpartner-mock-testing", + "token_endpoint": "http://localhost:8099/v1/mimoto/get-token/MockMdl", + "authorization_audience": "https://esignet-mock.collab.mosip.net/v1/esignet/oauth/v2/token", + "proxy_token_endpoint": "https://esignet-mock.collab.mosip.net/v1/esignet/oauth/v2/token", + "client_alias": "wallet-demo-client", "qr_code_type": "EmbeddedVC", "enabled": "true", "wellknown_endpoint": "http://certify:8090/v1/certify/issuance/.well-known/openid-credential-issuer" - } + } ] } diff --git a/docker-compose/docker-compose-injistack/docker-compose.yaml b/docker-compose/docker-compose-injistack/docker-compose.yaml index c02493ab..9c02a17e 100644 --- a/docker-compose/docker-compose-injistack/docker-compose.yaml +++ b/docker-compose/docker-compose-injistack/docker-compose.yaml @@ -14,42 +14,34 @@ services: - "5433:5432" certify: - image: mosipdev/inji-certify:develop + image: mosipqa/inji-certify:0.10.x user: root ports: - 8090:8090 environment: - container_user=mosip - - active_profile_env=default, mock-identity + - active_profile_env=default, csvdp-farmer - SPRING_CONFIG_NAME=certify - SPRING_CONFIG_LOCATION=/home/mosip/config/ - enable_certify_artifactory=false - download_hsm_client=false + - mosipbox_public_url=http://certify:8090 volumes: - ./config/certify-default.properties:/home/mosip/config/certify-default.properties - - ./config/certify-mock-identity.properties:/home/mosip/config/certify-mock-identity.properties + - ./config/certify-csvdp-farmer.properties:/home/mosip/config/certify-csvdp-farmer.properties + - ./config/certify-mock-mdl.properties:/home/mosip/config/certify-mock-mdl.properties - ./data/CERTIFY_PKCS12:/home/mosip/CERTIFY_PKCS12 - ./loader_path/certify/:/home/mosip/additional_jars/ + # modify the below file to change the identity fields in the VC + - ./config/farmer_identity_data.csv:/home/mosip/config/farmer_identity_data.csv networks: - network depends_on: - database - nginx: - container_name: nginx - image: nginx:alpine - ports: - - '80:80' - volumes: - - ./config/mimoto-issuers-config.json:/config/server/mimoto-issuers-config.json - - ./config/mimoto-trusted-verifiers.json:/config/server/mimoto-trusted-verifiers.json - - ./config/credential-template.html:/config/server/credential-template.html - - ./nginx.conf:/etc/nginx/nginx.conf - networks: - - network mimoto-service: container_name: 'Mimoto-Service' - image: 'mosipid/mimoto:0.14.0' + image: mosipqa/mimoto:release-0.15.x user: root ports: - '8099:8099' @@ -65,36 +57,26 @@ services: - ./config/mimoto-issuers-config.json:/home/mosip/mimoto-issuers-config.json - ./config/mimoto-trusted-verifiers.json:/home/mosip/mimoto-trusted-verifiers.json - ./certs/oidckeystore.p12:/home/mosip/certs/oidckeystore.p12 - depends_on: - - nginx - - inji-web-proxy: - container_name: 'inji-web-proxy' - image: inji-web-proxy:local - ports: - - '3010:3010' - environment: - - MIMOTO_HOST=http://mimoto-service:8099/v1/mimoto - - PORT=3010 - depends_on: - - mimoto-service - networks: - - network inji-web: container_name: 'inji-web' - image: mosipdev/inji-web:develop + image: mosipqa/inji-web:release-0.11.x ports: - '3001:3004' environment: - - MIMOTO_HOST=http://localhost:3010 - DEFAULT_LANG=en + - MIMOTO_HOST=http://localhost:3001/v1/mimoto + volumes: + - ./config/mimoto-default.properties:/home/mosip/mimoto-default.properties + - ./config/mimoto-issuers-config.json:/home/mosip/mimoto-issuers-config.json + - ./config/mimoto-trusted-verifiers.json:/home/mosip/mimoto-trusted-verifiers.json + - ./config/credential-template.html:/home/mosip/credential-template.html + - ./nginx.conf:/etc/nginx/conf.d/default.conf depends_on: - - inji-web-proxy + - mimoto-service networks: - network - networks: network: name: mosip_network diff --git a/docker-compose/docker-compose-injistack/nginx.conf b/docker-compose/docker-compose-injistack/nginx.conf index 03a3e1d7..fd5d0e04 100644 --- a/docker-compose/docker-compose-injistack/nginx.conf +++ b/docker-compose/docker-compose-injistack/nginx.conf @@ -1,12 +1,48 @@ -events { } +server { + listen 3004; + # Default location for normal static files + location / { + root /usr/share/nginx/html; + index index.html index.htm; + try_files $uri $uri/ /index.html; + } + + # Serve files from /home/mosip with autoindex enabled + location ~* \.json$ { + root /home/mosip; + autoindex on; + } + + # Serve files from /home/mosip with autoindex enabled + location /credential-template.html { + root /home/mosip; + autoindex on; + } -http { - server { - listen 80; + # Proxy API requests to mimoto-service + location /v1/mimoto/ { + proxy_pass http://mimoto-service:8099/v1/mimoto/; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_http_version 1.1; + proxy_set_header Connection ""; - location / { - root /config/server; - autoindex on; + # Add CORS headers + add_header 'Access-Control-Allow-Origin' '*' always; + add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always; + add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization, Cache-Control' always; + + # Handle OPTIONS requests (for pre-flight checks) + if ($request_method = 'OPTIONS') { + return 204; } } -} + + error_page 500 502 503 504 /50x.html; + + location = /50x.html { + root /usr/share/nginx/html; + } +} \ No newline at end of file diff --git a/docker-compose/docker-compose-sunbird/.env b/docker-compose/docker-compose-sunbird/.env deleted file mode 100644 index b163b818..00000000 --- a/docker-compose/docker-compose-sunbird/.env +++ /dev/null @@ -1,36 +0,0 @@ -# vault service -VAULT_ADDR=http://0.0.0.0:8200 -VAULT_API_ADDR=http://0.0.0.0:8200 -VAULT_ADDRESS=http://0.0.0.0:8200 - -# identity service -VAULT_ADDR=http://vault:8200 -VAULT_TOKEN= -VAULT_BASE_URL=http://vault:8200/v1 -VAULT_ROOT_PATH=http://vault:8200/v1/kv -VAULT_TIMEOUT=5000 -VAULT_PROXY=false -SIGNING_ALGORITHM=Ed25519Signature2020 -JWKS_URI= -ENABLE_AUTH=false -WEB_DID_BASE_URL=https://challabeehyv.github.io/DID-Resolve - -# schema service -IDENTITY_BASE_URL=http://identity:3332 -JWKS_URI= -ENABLE_AUTH=false - -# credential service -IDENTITY_BASE_URL=http://identity:3332 -SCHEMA_BASE_URL=http://schema:3333 -CREDENTIAL_SERVICE_BASE_URL= -JWKS_URI= -ENABLE_AUTH=false - -# db service -POSTGRES_USER=postgres -POSTGRES_PASSWORD=postgres - -# registry -RELEASE_VERSION=v1.0.0 -SCHEMA_DIR=schemas/registry diff --git a/docker-compose/docker-compose-sunbird/.gitignore b/docker-compose/docker-compose-sunbird/.gitignore deleted file mode 100644 index d8acd276..00000000 --- a/docker-compose/docker-compose-sunbird/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -data - -keys.txt -data -db-data \ No newline at end of file diff --git a/docker-compose/docker-compose-sunbird/docker-compose.yml b/docker-compose/docker-compose-sunbird/docker-compose.yml deleted file mode 100644 index 484d76ff..00000000 --- a/docker-compose/docker-compose-sunbird/docker-compose.yml +++ /dev/null @@ -1,183 +0,0 @@ -version: '2.4' - -services: - vault: - image: vault:1.13.3 - restart: always - volumes: - - ./vault.json:/vault/config/vault.json - - ./data/vault-data:/vault/file - environment: - - VAULT_ADDR=${VAULT_ADDR} - - VAULT_API_ADDR=${VAULT_API_ADDR} - - VAULT_ADDRESS=${VAULT_ADDRESS} - cap_add: - - IPC_LOCK - command: vault server -config=/vault/config/vault.json - ports: - - 8200:8200 - healthcheck: - test: - [ - "CMD-SHELL", - "wget --spider http://127.0.0.1:8200/v1/sys/health || exit 1", - ] - interval: 10s - timeout: 5s - retries: 3 - networks: - - network - identity: - image: ghcr.io/sunbird-rc/sunbird-rc-identity-service:v2.0.0-rc3 - ports: - - "3332:3332" - depends_on: - vault: - condition: service_healthy - db: - condition: service_healthy - environment: - - DATABASE_URL=postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@db:5432/postgres - - VAULT_ADDR=${VAULT_ADDR} - - VAULT_TOKEN=${VAULT_TOKEN} - - VAULT_BASE_URL=${VAULT_BASE_URL} - - VAULT_ROOT_PATH=${VAULT_ROOT_PATH} - - VAULT_TIMEOUT=${VAULT_TIMEOUT} - - VAULT_PROXY=${VAULT_PROXY} - - SIGNING_ALGORITHM=${SIGNING_ALGORITHM} - - JWKS_URI=${JWKS_URI} - - ENABLE_AUTH=${ENABLE_AUTH} - - WEB_DID_BASE_URL=${WEB_DID_BASE_URL} - healthcheck: - test: - [ "CMD-SHELL", "curl -f http://localhost:3332/health || exit 1" ] - interval: 10s - timeout: 5s - retries: 5 - networks: - - network - schema: - image: ghcr.io/sunbird-rc/sunbird-rc-credential-schema:v2.0.0-rc3 - ports: - - "3333:3333" - depends_on: - db: - condition: service_healthy - identity: - condition: service_healthy - environment: - - DATABASE_URL=postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@db:5432/postgres - - IDENTITY_BASE_URL=${IDENTITY_BASE_URL} - - JWKS_URI=${JWKS_URI} - - ENABLE_AUTH=${ENABLE_AUTH} - healthcheck: - test: - [ "CMD-SHELL", "curl -f http://localhost:3333/health || exit 1" ] - interval: 10s - timeout: 5s - retries: 5 - networks: - - network - credential: - image: ghcr.io/sunbird-rc/sunbird-rc-credentials-service:v2.0.0-rc3 - ports: - - "3000:3000" - depends_on: - db: - condition: service_healthy - identity: - condition: service_healthy - schema: - condition: service_healthy - environment: - - DATABASE_URL=postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@db:5432/postgres - - IDENTITY_BASE_URL=${IDENTITY_BASE_URL} - - SCHEMA_BASE_URL=${SCHEMA_BASE_URL} - - CREDENTIAL_SERVICE_BASE_URL=${CREDENTIAL_SERVICE_BASE_URL} - - JWKS_URI=${JWKS_URI} - - ENABLE_AUTH=${ENABLE_AUTH} - - QR_TYPE=W3C_VC - healthcheck: - test: - [ "CMD-SHELL", "curl -f http://localhost:3000/health || exit 1" ] - interval: 10s - timeout: 5s - retries: 5 - networks: - - network - db: - image: postgres:12.1-alpine - ports: - - 5433:5432 - environment: - - POSTGRES_USER=${POSTGRES_USER} - - POSTGRES_PASSWORD=${POSTGRES_PASSWORD} - volumes: - - ./data/db-data:/var/lib/postgresql/data - healthcheck: - test: [ "CMD-SHELL", "pg_isready -U postgres" ] - interval: 10s - timeout: 5s - retries: 5 - networks: - - network - registry: - image: ghcr.io/sunbird-rc/sunbird-rc-core:${RELEASE_VERSION} - volumes: - - ./${SCHEMA_DIR}:/home/sunbirdrc/config/public/_schemas - environment: - - connectionInfo_uri=jdbc:postgresql://db:5432/postgres - - connectionInfo_username=${POSTGRES_USER} - - connectionInfo_password=${POSTGRES_PASSWORD} - - encryption_enabled=false - - event_enabled=false - - search_providerName=${SEARCH_PROVIDER_NAME-dev.sunbirdrc.registry.service.NativeSearchService} - - idgen_enabled=false - - claims_enabled=false - - certificate_enabled=false - - signature_enabled=false - - filestorage_enabled=false - - registry_base_apis_enable=false - - logging.level.root=INFO - - async_enabled=false - - authentication_enabled=false - - notification_enabled=false - - webhook_enabled=false - - manager_type=DefinitionsManager - ports: - - '8044:8081' - depends_on: - db: - condition: service_healthy - healthcheck: - test: - [ - 'CMD-SHELL', - 'wget -nv -t1 --spider http://localhost:8081/health || exit 1', - ] - interval: 30s - timeout: 10s - retries: 10 - networks: - - network - sunbird-registry: - image: nginx:stable-alpine - volumes: - - ./imports/nginx/nginx.conf:/etc/nginx/conf.d/default.conf - ports: - - '8000:80' - depends_on: - registry: - condition: service_healthy - identity: - condition: service_healthy - schema: - condition: service_healthy - credential: - condition: service_healthy - networks: - - network -networks: - network: - name: mosip_network - external: true diff --git a/docker-compose/docker-compose-sunbird/imports/nginx/nginx.conf b/docker-compose/docker-compose-sunbird/imports/nginx/nginx.conf deleted file mode 100644 index 1aa7c318..00000000 --- a/docker-compose/docker-compose-sunbird/imports/nginx/nginx.conf +++ /dev/null @@ -1,23 +0,0 @@ -server { - listen 80; - - location / { - proxy_pass http://vault:8200/; - } - - location /schema/ { - proxy_pass http://schema:3333/; - } - - location /credential/ { - proxy_pass http://credential:3000/; - } - - location /identity/ { - proxy_pass http://identity:3332/; - } - - location /registry/ { - proxy_pass http://registry:8081/; - } -} diff --git a/docker-compose/docker-compose-sunbird/schemas/credentials/Insurance.json b/docker-compose/docker-compose-sunbird/schemas/credentials/Insurance.json deleted file mode 100644 index bd321835..00000000 --- a/docker-compose/docker-compose-sunbird/schemas/credentials/Insurance.json +++ /dev/null @@ -1,62 +0,0 @@ -{ - "schema": { - "type": "https://w3c-ccg.github.io/vc-json-schemas/", - "version": "1.0.0", - "id": "did:ulpschema:c9cc0f03-4f94-4f44-9bcd-b24a8696fa2", - "name": "Proof of Medical Insurance Credential", - "author": "did:example:bc18444a-b68c-49ec-ac66-336697616222", - "authored": "2022-12-19T09:22:23.064Z", - "schema": { - "$id": "Proof-of-Medical-Insurance-Credential-1.0", - "$schema": "https://json-schema.org/draft/2019-09/schema", - "description": "The holder is holding the certificate of Insurance", - "type": "object", - "properties": { - "policyNumber": { - "type": "string" - }, - "policyName": { - "type": "string" - }, - "policyExpiresOn": { - "type": "string" - }, - "policyIssuedOn": { - "type": "string" - }, - "benefits": { - "type": "array", - "items": { - "type": "string" - } - }, - "fullName": { - "type": "string", - "title": "Full Name" - }, - "dob": { - "type": "string" - }, - "gender": { - "type": "string", - "enum": [ - "Male", - "Female", - "Other" - ] - } - }, - "required": [ - "policyNumber", - "policyName", - "fullName", - "dob" - ], - "additionalProperties": true - } - }, - "tags": [ - "InsuranceCertificate" - ], - "status": "DRAFT" -} diff --git a/docker-compose/docker-compose-sunbird/schemas/registry/Insurance.json b/docker-compose/docker-compose-sunbird/schemas/registry/Insurance.json deleted file mode 100644 index 44f19c9e..00000000 --- a/docker-compose/docker-compose-sunbird/schemas/registry/Insurance.json +++ /dev/null @@ -1,84 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema", - "type": "object", - "properties": { - "Insurance": { - "$ref": "#/definitions/Insurance" - } - }, - "required": [ - "Insurance" - ], - "title":"Insurance", - "definitions": { - "Insurance": { - "$id": "#/properties/Insurance", - "type": "object", - "title": "Insurance", - "required": [ - "policyNumber", - "policyName", - "policyExpiresOn", - "policyIssuedOn", - "fullName", - "dob" - ], - "properties": { - "policyNumber": { - "type": "string" - }, - "policyName": { - "type": "string" - }, - "policyExpiresOn": { - "type": "string", - "format": "date-time" - }, - "policyIssuedOn": { - "type": "string", - "format": "date-time" - }, - "benefits": { - "type": "array", - "items": { - "type": "string" - } - }, - "fullName": { - "type": "string", - "title": "Full Name" - }, - "dob": { - "type": "string", - "format": "date" - }, - "gender": { - "type": "string", - "enum": [ - "Male", - "Female", - "Other" - ] - }, - "mobile": { - "type": "string", - "title": "Mobile number" - }, - "email": { - "type": "string", - "title": "Email ID" - } - } - } - }, - "_osConfig": { - "osComment": [], - "privateFields": [], - "signedFields": [], - "indexFields": [], - "uniqueIndexFields": [], - "roles": ["anonymous"], - "inviteRoles": ["anonymous"] - } - } - \ No newline at end of file diff --git a/docker-compose/docker-compose-sunbird/setup_vault.sh b/docker-compose/docker-compose-sunbird/setup_vault.sh deleted file mode 100644 index c9bcfd77..00000000 --- a/docker-compose/docker-compose-sunbird/setup_vault.sh +++ /dev/null @@ -1,77 +0,0 @@ -#!/bin/bash - -# This script does the following things -# * Start a vault instance with vault/vault.json configuration -# * Unseal the vault -# * Create a v2 kv engine -# * Prints the unseal keys and root token -# * This script does not automatically unseal vault on restarts, it only works with fresh installations - -COMPOSE_FILE="${1:-docker-compose.yml}" -SERVICE_NAME="${2:-vault}" - -echo "Setting up $SERVICE_NAME in $COMPOSE_FILE" - -docker compose -f "$COMPOSE_FILE" up -d "$SERVICE_NAME" - -# Function to check if Vault is ready -check_vault_status() { - vault_status=$(docker compose -f "$COMPOSE_FILE" exec "$SERVICE_NAME" vault status 2>&1) - if [[ $vault_status == *"connection refused"* ]]; then - echo "Unable to connect to Vault. Waiting for Vault to start..." - return 1 - elif [[ $vault_status == *"Sealed true"* ]]; then - echo "Vault is sealed. Waiting for unsealing..." - return 0 - else - echo "Unsealed and up. Moving to next steps." - return 0 - fi -} - - -# Wait for Vault service to become available -until check_vault_status; do - echo "Waiting for Vault service to start..." - sleep 1; -done - - -if [[ $vault_status == *"Initialized true"* ]]; then - echo "Vault is initialized already. Unsealing if it is not unsealed" -else - # keys contains ansi escape sequences, remove them if any - docker compose -f "$COMPOSE_FILE" exec -T "$SERVICE_NAME" vault operator init > ansi-keys.txt - sed 's/\x1B\[[0-9;]*[JKmsu]//g' < ansi-keys.txt > keys.txt -fi - -sed -n 's/Unseal Key [1-1]\+: \(.*\)/\1/p' keys.txt > parsed-key.txt -key=$(cat parsed-key.txt) -docker compose -f "$COMPOSE_FILE" exec -T "$SERVICE_NAME" vault operator unseal "$key" < /dev/null - -sed -n 's/Unseal Key [2-2]\+: \(.*\)/\1/p' keys.txt > parsed-key.txt -key=$(cat parsed-key.txt) -docker compose -f "$COMPOSE_FILE" exec -T "$SERVICE_NAME" vault operator unseal "$key" < /dev/null - -sed -n 's/Unseal Key [3-3]\+: \(.*\)/\1/p' keys.txt > parsed-key.txt -key=$(cat parsed-key.txt) -docker compose -f "$COMPOSE_FILE" exec -T "$SERVICE_NAME" vault operator unseal "$key" < /dev/null - -root_token=$(sed -n 's/Initial Root Token: \(.*\)/\1/p' keys.txt | tr -dc '[:print:]') - -if [[ $vault_status == *"Initialized true"* ]]; then - echo "Vault is initialized already. Skipping creating a KV engine" -else - sed -i "s/VAULT_TOKEN=.*/VAULT_TOKEN=$root_token/" ".env" - docker compose -f "$COMPOSE_FILE" exec -e VAULT_TOKEN=$root_token -T "$SERVICE_NAME" vault secrets enable -path=kv kv-v2 -fi - -echo -e "\nNOTE: KEYS ARE STORED IN keys.txt" - -if [ -f "ansi-keys.txt" ] ; then - rm ansi-keys.txt -fi - -if [ -f "parsed-key.txt" ] ; then - rm parsed-key.txt -fi diff --git a/docker-compose/docker-compose-sunbird/vault.json b/docker-compose/docker-compose-sunbird/vault.json deleted file mode 100644 index bb870c48..00000000 --- a/docker-compose/docker-compose-sunbird/vault.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "listener": { - "tcp": { - "address": "0.0.0.0:8200", - "tls_disable": 1 - } - }, - "backend": { - "file": { - "path": "/vault/file" - } - }, - "default_lease_ttl": "168h", - "max_lease_ttl": "0h", - "api_addr": "http://0.0.0.0:8200", - "ui": "true", - "disable_mlock": "true" - } - \ No newline at end of file diff --git a/docs/Local-Development.md b/docs/Local-Development.md new file mode 100644 index 00000000..8e1f3b0d --- /dev/null +++ b/docs/Local-Development.md @@ -0,0 +1,32 @@ +# Local Development of Inji Certify + +**Pre-requisites**: + +- Java 21, Postgres DB installed & configured +- Git Bash for Windows users + +1. Clone the repo, usually the active development happens on the `develop` branch but one can check out a tagged version as well. +2. Run the DB init scripts present in `db_scripts/mosip_certify` , running `./deploy.sh deploy.properties` is a good way to init the DB. +3. Decide on the issuance mode of Certify. Some plugins enable Certify to operate as a Proxy and others enable it to work as an Issuer, configure `mosip.certify.plugin-mode` appropriately as `DataProvider` or `VCIssuance`. + * [Recommended] Set it to `DataProvider` if you want a quickest possible working setup, and configure `mosip.certify.data-provider-plugin.issuer-uri` and `mosip.certify.data-provider-plugin.issuer-public-key-uri` appropriately. + * If you have another Issuance module such as Sunbird, MOSIP Stack, you may want to set it up in `VCIssuance` mode. +4. Decide on the VCI plugin for use locally and configure it, while running locally from an IDE such as Eclipse or IntelliJ one needs to add configuration to the `application-local.properties` and add the VCI plugin dependency JAR to the certify-service project which implements one of `DataProviderPlugin` or `VCIssuancePlugin` interfaces. +5. Get a compatible eSignet setup running configured with the appropriate Authenticator plugin implementation matching the VCI plugin. + * Configure `mosip.certify.authorization.url` to point to your Authorization service hostname, this could be a working eSignet instance or another AuthZ provider configured with an [Authenticator plugin implementation](https://docs.esignet.io/integration/authenticator), essentially enabling the VC Issuing plugin to do the work. + * Configure `mosip.certify.domain.url`, `mosip.certify.identifier`, `mosip.certify.authn.issuer-uri`, `mosip.certify.authn.jwk-set-uri`, `mosip.certify.authn.allowed-audiences` appropriately as per the Authorization service and Certify URI. + * Update the `mosip.certify.key-values` with the well known appropriately, with the correct credential-type, scope and other relevant attributes. + * Update the well known configuration in `mosip.certify.key-values` to match the Credential type, scope and other fields to match your VerifiableCredential. + * Appropriately configure the `mosip.certify.authn.allowed-audiences` to allowed audiences such that it matches with the AuthZ token when the Credential issue request is made to Certify. +6. (required if Mobile driving license configured) Onboard issuer key and certificate data into property `mosip.certify.mock.mdoc.issuer-key-cert` using the creation script. +7. Perform Authentication & VC Issuance to see if the Certify & AuthZ stack is working apprpriately. Look out for the Postman collections referred to in the main README.md of this project. + + +## Locally setting up CSV Plugin + + +The above README can be used to setup the [CSV Plugin](https://github.com/mosip/digital-credential-plugins/tree/develop/mock-certify-plugin) and it'll help showcase how one can setup a custom authored plugin for local testing. + +Pre-requisites: + +* a working Authorization service which gives an identifiable information in the end-user's ID in the `sub` field +* pre-populated CSV file configured with the matching identities to be authenticated against diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 00000000..9c2fa135 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,6 @@ +# Developer READMEs + +- [Local Development](./Local-Development.md) +- [How to decide b/w VCIssuance & DataProviderPlugin while writing your own](./VCIssuance-vs-DataProvider.md) + +# Integrator READMEs diff --git a/docs/VCIssuance-vs-DataProvider.md b/docs/VCIssuance-vs-DataProvider.md new file mode 100644 index 00000000..d74c60d2 --- /dev/null +++ b/docs/VCIssuance-vs-DataProvider.md @@ -0,0 +1,61 @@ +# VCIssuance vs DataProvider Plugin + + +Certify has a plugin model to issue VCs so that implementors can extend Inji Certify to issue various VCs and and the plugin can be of two types. + +1. VCIssuancePlugin +2. DataProviderPlugin + +While they are two types of Issuing Plugins, both types are issuing VCs by connecting to a configured datasource. The two types of Plugins enable Inji Certify to operate differ in where VC Signing happens. + +```mermaid +sequenceDiagram + participant Client as 🌐 Client + box Inji Certify #E6F3FF + participant credential_endpoint as πŸ”— Credential API + participant VelocityEngine as βš™οΈ Template Engine + participant VCSigner as πŸ” VC Signer + participant TemplateDB as πŸ’Ύ Template Store + end + participant VCIssuancePlugin as πŸ”Œ VC Issuance Plugin + participant DataProviderPlugin as πŸ”Œ Data Provider Plugin + + Note over VCIssuancePlugin: External Plugin + Note over DataProviderPlugin: External Plugin + + Client->>credential_endpoint: Request VC Issuance (OIDC4VCI) + alt Using VCIssuancePlugin + credential_endpoint->>VCIssuancePlugin: Forward Request + Note right of VCIssuancePlugin: Internal Process:
1. Get Data
2. Create VC
3. Sign VC + VCIssuancePlugin-->>credential_endpoint: Return Complete Signed VC + + else Using DataProviderPlugin + credential_endpoint->>DataProviderPlugin: Request Data + Note right of DataProviderPlugin: Internal Process:
Get Data + DataProviderPlugin-->>credential_endpoint: Return Raw Data + + credential_endpoint->>TemplateDB: Fetch Credential Template + TemplateDB-->>credential_endpoint: Return Template + + credential_endpoint->>VelocityEngine: Process Template with Raw Data + VelocityEngine-->>credential_endpoint: Return unsigned Credential Data + + credential_endpoint->>VCSigner: Sign Credential + Note right of VCSigner: Sign VC + VCSigner-->>credential_endpoint: Return Signed VC + + + end + credential_endpoint-->>Client: Return Final VC (OIDC4VCI) +``` + +## How to choose to implement either one? + +- An integrator can choose to implement VCIssuancePlugin interface if they want to implement the VC Signing by themselves. This gives more power and control to the VC Plugin authors in choosing to support their own formats, signing algorithms which may or may not be supported by Certify. +- There may be a case, where an integrator might want Certify to deal with fewer aspects of VCIssuance or have a pre-existing VC Issuance stack and may just want a Certify as a OpenID4VCI proxy, in this case the implementors can choose to implement VCIssuancePlugin interface which is supposed to give out a valid VC on it's own or with an external stack. +- If an integrator doesn't have an existing VCIssuance stack pre-deployed, they can choose to let Certify do all the heavy lifting with a DataProviderPlugin. They can choose to use any of the sample plugins present in [this repo](https://github.com/mosip/digital-credential-plugins/) or choose to implement their own. + + +# Doubts? + +If you've further questions, do not hesitate to ask a question about the same in [MOSIP Community](https://community.mosip.io) diff --git a/docs/inji-certify-openapi.yaml b/docs/inji-certify-openapi.yaml index 7ea6f2c1..4dd24dc2 100644 --- a/docs/inji-certify-openapi.yaml +++ b/docs/inji-certify-openapi.yaml @@ -24,7 +24,7 @@ paths: - vd12 - latest default: latest - description: '' + description: 'Get the OpenID wellknown ' responses: '200': description: OK @@ -503,6 +503,187 @@ paths: - benefits - email parameters: [] + /issuance/.well-known/did.json: + get: + summary: Fetch the DID object + description: 'Fetch the DID object as per the URI references & Plugin Mode configured and ' + responses: + '200': + description: A successful response with DID document data. + content: + application/json: + schema: + type: object + properties: + assertionMethod: + type: array + description: List of assertion methods associated with the DID. + example: + - 'did:web:vharsh.github.io:DID:harsh#key-0' + items: + type: string + service: + type: array + description: List of services associated with the DID (empty in this case). + items: + type: object + id: + type: string + description: The DID identifier. + example: 'did:web:vharsh.github.io:DID:harsh' + verificationMethod: + type: array + items: + type: object + properties: + publicKeyMultibase: + type: string + description: The public key in multibase format. + example: z6MkuY7TsbhRsdrhHWWUswDVddNQdiPo7EzPNdQW8S8Ghd8d + controller: + type: string + description: The DID controller. + example: 'did:web:vharsh.github.io:DID:harsh' + id: + type: string + description: The verification method identifier. + example: 'did:web:vharsh.github.io:DID:harsh#key-0' + type: + type: string + description: The type of the verification method. + example: Ed25519VerificationKey2020 + '@context': + type: string + description: The context for the verification method. + example: 'https://w3id.org/security/suites/ed25519-2020/v1' + '@context': + type: array + description: The context for the DID document. + example: + - 'https://www.w3.org/ns/did/v1' + items: + type: string + alsoKnownAs: + type: array + description: Alternate names associated with the DID. + items: + type: string + authentication: + type: array + description: List of authentication methods associated with the DID. + example: + - 'did:web:vharsh.github.io:DID:harsh#key-0' + items: + type: string + '400': + description: unsupported for VCIssuance plugin mode + content: + application/json: + schema: + type: object + properties: + error: + type: string + description: The error code. + example: unsupported_in_current_plugin_mode + error_description: + type: string + description: A detailed description of the error. + example: unsupported_in_current_plugin_mode + headers: + Content-Type: + schema: + type: string + description: application/json + operationId: '' + '/rendering-template/{id}': + get: + summary: Fetch the SVG template + description: A public endpoint to download the rendering template for Verifiable Credentials for rendering a VC + parameters: + - in: path + name: id + required: true + description: A string matching the ID of the template in the DB. + schema: + type: string + responses: + '200': + description: 'the svg template available for download' + content: image/svg+xml + '400': + description: 'invalid template request' + content: + application/json: + schema: + type: object + properties: + responseTime: + type: string + format: date-time + example: "2024-10-21T12:07:06.991Z" + response: + type: 'null' + example: null + errors: + type: array + items: + type: object + properties: + errorCode: + type: string + example: "invalid_request" + errorMessage: + type: string + example: "template_with_id_not_found" + + x-stoplight: + id: rt5t4bbccx6id + parameters: + - schema: + type: string + name: id + in: path + required: true + description: the string id of the template + /system-info/certificate: + get: + summary: Get the Certificate against an applicationId and referenceId + description: A public endpoint to download a Keymanager managed Certificate + parameters: + - in: query + name: applicationId + required: true + description: applicationId of the certificate + schema: + type: string + - in: query + name: referenceId + required: false + description: referenceId of the certificate + schema: + type: string + responses: + '200': + description: Got the Certificate. + content: application/json + x-stoplight: + id: rt5t4bbccx6id + post: + summary: upload a Certificate against an applicationId and referenceId + requestBody: + content: + application/json: + schema: + type: object + properties: + applicationId: + type: string + referenceId: + type: string + default: '' + certificateData: + type: string /issuance/credential: post: summary: Credential Issuance endpoint diff --git a/docs/postman-collections/inji-certify-with-mock-mdoc-vci.postman_collection.json b/docs/postman-collections/inji-certify-with-mock-mdoc-vci.postman_collection.json new file mode 100644 index 00000000..d6b204ee --- /dev/null +++ b/docs/postman-collections/inji-certify-with-mock-mdoc-vci.postman_collection.json @@ -0,0 +1,659 @@ +{ + "info": { + "_postman_id": "c5f84837-c122-44b4-ae04-982be55d58f3", + "name": "Inji Certify Mock MDL VCI", + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", + "_exporter_id": "29153193" + }, + "item": [ + { + "name": "VCI", + "item": [ + { + "name": "Get CSRF token", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "var token = pm.cookies.get(\"XSRF-TOKEN\")", + "pm.environment.set(\"csrf_token\", token);" + ], + "type": "text/javascript" + } + } + ], + "protocolProfileBehavior": { + "disableBodyPruning": true + }, + "request": { + "method": "GET", + "header": [], + "body": { + "mode": "raw", + "raw": "", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{url}}/csrf/token", + "host": [ + "{{url}}" + ], + "path": [ + "csrf", + "token" + ] + } + }, + "response": [] + }, + { + "name": "Authorize / OAuthdetails request V2", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "var btoa = require('btoa');", + "", + "var token = pm.cookies.get(\"XSRF-TOKEN\")", + "pm.environment.set(\"csrf_token\", token);", + "", + "pm.test(\"Validate transactionId\", function () {", + " var jsonData = pm.response.json();", + " pm.expect(jsonData.response.transactionId).not.equals(null);", + " pm.environment.set(\"transaction_id\", jsonData.response.transactionId);", + "});", + "", + "pm.test(\"Validate auth factors\", function () {", + " var jsonData = pm.response.json();", + " pm.expect(jsonData.response.authFactors[0].name).to.eql(pm.environment.get(\"expected_amr\"));", + "});", + "", + "pm.test(\"set oauth-details-hash\", function () {", + " var jsonData = pm.response.json();", + " var sha256Hash = CryptoJS.SHA256(JSON.stringify(jsonData.response));", + " var base64Encoded = sha256Hash.toString(CryptoJS.enc.Base64);", + " // Remove padding characters", + " base64Encoded = base64Encoded.replace(/=+$/, '');", + " // Replace '+' with '-' and '/' with '_' to convert to base64 URL encoding", + " base64Encoded = base64Encoded.replace(/\\+/g, '-').replace(/\\//g, '_');", + " console.log(\"base64Encoded : \" + base64Encoded);", + " pm.environment.set(\"oauth_details_key\", jsonData.response.transactionId);", + " pm.environment.set(\"oauth_details_hash\", base64Encoded);", + "});" + ], + "type": "text/javascript", + "packages": {} + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "eval(pm.globals.get('pmlib_code'))", + "", + "const pkce = pmlib.pkceChallenge();", + "pm.collectionVariables.set(\"codeChallenge\",pkce.code_challenge);", + "pm.collectionVariables.set(\"codeChallengeMethod\",pkce.code_challenge_method);", + "pm.collectionVariables.set(\"codeVerifier\",pkce.code_verifier);" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "X-XSRF-TOKEN", + "value": "{{csrf_token}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"requestTime\": \"{{$isoTimestamp}}\",\n \"request\": {\n \"clientId\": \"{{clientId}}\",\n \"scope\": \"sample_vc_mdoc\",\n \"responseType\": \"code\",\n \"redirectUri\": \"{{redirectionUrl}}\",\n \"display\": \"popup\",\n \"prompt\": \"login\",\n \"acrValues\": \"mosip:idp:acr:generated-code\",\n \"nonce\" : \"{{nonce}}\",\n \"state\" : \"{{state}}\",\n \"claimsLocales\" : \"en\",\n \"codeChallenge\" : \"{{codeChallenge}}\",\n \"codeChallengeMethod\" : \"{{codeChallengeMethod}}\"\n }\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{url}}/authorization/v2/oauth-details", + "host": [ + "{{url}}" + ], + "path": [ + "authorization", + "v2", + "oauth-details" + ] + } + }, + "response": [] + }, + { + "name": "Send OTP", + "request": { + "method": "POST", + "header": [ + { + "key": "X-XSRF-TOKEN", + "value": "{{csrf_token}}", + "type": "text" + }, + { + "key": "oauth-details-key", + "value": "{{oauth_details_key}}", + "type": "text" + }, + { + "key": "oauth-details-hash", + "value": "{{oauth_details_hash}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"requestTime\": \"{{$isoTimestamp}}\",\n \"request\": {\n \"transactionId\": \"{{transaction_id}}\",\n \"individualId\": \"{{individual_id}}\",\n \"otpChannels\" : [\"email\", \"phone\"],\n \"captchaToken\" : \"dummy\"\n }\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{url}}/authorization/send-otp", + "host": [ + "{{url}}" + ], + "path": [ + "authorization", + "send-otp" + ] + } + }, + "response": [] + }, + { + "name": "Authenticate User", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "var token = pm.cookies.get(\"XSRF-TOKEN\")", + "pm.environment.set(\"csrf_token\", token);" + ], + "type": "text/javascript" + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "X-XSRF-TOKEN", + "value": "{{csrf_token}}", + "type": "text" + }, + { + "key": "oauth-details-key", + "value": "{{oauth_details_key}}", + "type": "text" + }, + { + "key": "oauth-details-hash", + "value": "{{oauth_details_hash}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"requestTime\": \"{{$isoTimestamp}}\",\n \"request\": {\n \"transactionId\": \"{{transaction_id}}\",\n \"individualId\": \"{{individual_id}}\",\n \"challengeList\" : [\n {\n \"authFactorType\" : \"OTP\",\n \"challenge\" : \"111111\",\n \"format\" : \"alpha-numeric\"\n }\n ]\n }\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{url}}/authorization/v3/authenticate", + "host": [ + "{{url}}" + ], + "path": [ + "authorization", + "v3", + "authenticate" + ] + } + }, + "response": [] + }, + { + "name": "Authorization Code", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "var token = pm.cookies.get(\"XSRF-TOKEN\")", + "pm.environment.set(\"csrf_token\", token);", + "", + "pm.test(\"Validate code\", function () {", + " var jsonData = pm.response.json();", + " pm.expect(jsonData.response.code).not.equals(null);", + " pm.collectionVariables.set(\"code\", jsonData.response.code);", + "});" + ], + "type": "text/javascript" + } + } + ], + "protocolProfileBehavior": { + "followRedirects": false + }, + "request": { + "method": "POST", + "header": [ + { + "key": "X-XSRF-TOKEN", + "value": "{{csrf_token}}", + "type": "text" + }, + { + "key": "oauth-details-key", + "value": "{{oauth_details_key}}", + "type": "text" + }, + { + "key": "oauth-details-hash", + "value": "{{oauth_details_hash}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"requestTime\": \"{{$isoTimestamp}}\",\n \"request\": {\n \"transactionId\": \"{{transaction_id}}\",\n \"acceptedClaims\": [],\n \"permittedAuthorizeScopes\" : []\n }\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{url}}/authorization/auth-code", + "host": [ + "{{url}}" + ], + "path": [ + "authorization", + "auth-code" + ] + } + }, + "response": [] + }, + { + "name": "Get Tokens V2", + "event": [ + { + "listen": "prerequest", + "script": { + "exec": [ + "eval(pm.globals.get('pmlib_code'))", + "", + "// Set headers for JWT", + "var header = {\t", + "\t\"alg\": \"RS256\"", + "};", + "", + "", + "//sign token", + "//Note: Key pair is generated in \"Create OIDC client\" pre-requests script", + "//generated private and public keys are stored in the postman environment ", + "console.log(\"::::\", pm.environment.get(\"privateKey_jwk\"))", + "const signed_jwt = pmlib.clientAssertPrivateKey(JSON.parse(pm.environment.get(\"privateKey_jwk\")), pm.environment.get('clientId'), pm.environment.get('aud'), exp = 60, \"RS256\");", + "", + "console.log(\"signed_jwt \",signed_jwt)", + "pm.collectionVariables.set(\"client_assertion\",signed_jwt);", + "" + ], + "type": "text/javascript", + "packages": {} + } + }, + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Validate Id-token\", function () {", + " var jsonData = pm.response.json();", + " pm.expect(jsonData.id_token).not.equals(null);", + "});", + "", + "pm.test(\"Validate access-token\", function () {", + " var jsonData = pm.response.json();", + " pm.expect(jsonData.access_token).not.equals(null);", + " pm.environment.set(\"access_token\", jsonData.access_token);", + " console.log(\"jsonData.access_token \",jsonData.access_token)", + "", + " var jwt_parts = pm.environment.get('access_token').split('.'); // header.payload.signature", + " var jwt_payload = JSON.parse(atob(jwt_parts[1]));", + " pm.environment.set(\"c_nonce\", jwt_payload.c_nonce);", + "});" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "urlencoded", + "urlencoded": [ + { + "key": "code", + "value": "{{code}}", + "type": "text" + }, + { + "key": "client_id", + "value": "{{clientId}}", + "type": "text" + }, + { + "key": "redirect_uri", + "value": "{{redirectionUrl}}", + "type": "text" + }, + { + "key": "grant_type", + "value": "authorization_code", + "type": "text" + }, + { + "key": "client_assertion_type", + "value": "urn:ietf:params:oauth:client-assertion-type:jwt-bearer", + "type": "text" + }, + { + "key": "client_assertion", + "value": "{{client_assertion}}", + "type": "text" + }, + { + "key": "code_verifier", + "value": "{{codeVerifier}}", + "type": "text" + } + ] + }, + "url": { + "raw": "{{url}}/oauth/v2/token", + "host": [ + "{{url}}" + ], + "path": [ + "oauth", + "v2", + "token" + ] + } + }, + "response": [] + }, + { + "name": "Get Mdoc Credential", + "event": [ + { + "listen": "prerequest", + "script": { + "exec": [ + "eval(pm.globals.get('pmlib_code'))", + "keyPair = pmlib.rs.KEYUTIL.generateKeypair(\"EC\", \"secp256r1\");", + "jwkPrivateKey = pmlib.rs.KEYUTIL.getJWK(keyPair.prvKeyObj);", + "jwkPublicKey = pmlib.rs.KEYUTIL.getJWK(keyPair.pubKeyObj);", + "jwkPublicKey[\"alg\"] = \"ES256\";", + "jwkPublicKey[\"use\"] = \"sig\";", + "", + "pm.environment.set(\"holder_public_key\", JSON.stringify(jwkPublicKey))", + "pm.environment.set(\"holder_private_key\", JSON.stringify(jwkPrivateKey));", + "", + "// Set headers for JWT", + "var header = {\t", + "\t\"alg\": \"ES256\",", + " \"typ\" : \"openid4vci-proof+jwt\",", + " \"jwk\" : JSON.parse(pm.environment.get(\"holder_public_key\"))", + "};", + "", + "", + "console.log(\"Getting c_nonce >> \" + pm.environment.get('c_nonce'));", + "", + "const signed_jwt = pmlib.jwtSign(JSON.parse(pm.environment.get(\"holder_private_key\")), {", + " // \"aud\" : 'http://localhost:8090',", + " \"aud\": pm.environment.get(\"vci_aud\"),", + "\t\"nonce\": pm.environment.get('c_nonce'),", + " \"iss\" : pm.environment.get('clientId'),", + "}, header, exp=600, alg = \"ES256\")", + "", + "console.log(\"modified aud\")", + "", + "console.log(\"proof - \",signed_jwt)", + "", + "pm.collectionVariables.set(\"proof_jwt\",signed_jwt);", + "" + ], + "type": "text/javascript", + "packages": {} + } + }, + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Validate c_nonce\", function () {", + " var jsonData = pm.response.json();", + " if(jsonData.c_nonce != null) {", + " pm.environment.set(\"c_nonce\", jsonData.c_nonce);", + " console.log(\"setting c_nonce\");", + " } ", + "});" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{access_token}}", + "type": "string" + } + ] + }, + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"format\": \"mso_mdoc\",\n \"doctype\": \"org.iso.18013.5.1.mDL\",\n \"claims\": {\n \"org.iso.18013.5.1\": {\n \"given_name\": {},\n \"family_name\": {},\n \"birth_date\": {},\n \"driving_privileges\":{},\n \"document_number\":{},\n \"issue_date\":{},\n \"issuing_country\":{},\n \"expiry_date\":{}\n }\n },\n \"proof\": {\n \"proof_type\": \"jwt\",\n \"jwt\": \"{{proof_jwt}}\"\n }\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{ceritifyUrl}}/issuance/credential", + "host": [ + "{{ceritifyUrl}}" + ], + "path": [ + "issuance", + "credential" + ] + } + }, + "response": [] + } + ] + } + ], + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + } + ], + "variable": [ + { + "key": "clientId", + "value": "mock-oidc-client" + }, + { + "key": "redirectionUrl", + "value": "https://mosip.io/index.php" + }, + { + "key": "relayingPartyId", + "value": "mock-relaying-party-id" + }, + { + "key": "status", + "value": "\"ACTIVE\"" + }, + { + "key": "acr_values", + "value": "level0 level1" + }, + { + "key": "scope", + "value": "openid profile" + }, + { + "key": "claims_request_param", + "value": "{\n \"userinfo\": {\n \"email\": {\n \"value\": null,\n \"values\": null,\n ..." + }, + { + "key": "nonce", + "value": "2erwER34WW" + }, + { + "key": "state", + "value": "ptOO76SD" + }, + { + "key": "expected_amr", + "value": "\"pin\"" + }, + { + "key": "transaction_id", + "value": "ece56bfa-d0c2-46ce-a5a2-8500dfb393a7" + }, + { + "key": "individual_id", + "value": "8267411571" + }, + { + "key": "auth_pin", + "value": "34789" + }, + { + "key": "url", + "value": "http://localhost:8088/v1/idp" + }, + { + "key": "url", + "value": "" + }, + { + "key": "code", + "value": "" + }, + { + "key": "client_assertion", + "value": "" + }, + { + "key": "access_token", + "value": "" + }, + { + "key": "linkTransactionId", + "value": "" + }, + { + "key": "wla_challenge", + "value": "" + }, + { + "key": "client_secret", + "value": "JfoG3eLWLW7iSZDt" + }, + { + "key": "client_secret", + "value": "" + }, + { + "key": "csrf_token", + "value": "08a17840-da3c-4b93-9ab3-83d9b297ac68" + }, + { + "key": "proof_jwt", + "value": "" + }, + { + "key": "codeChallenge", + "value": "" + }, + { + "key": "codeChallengeMethod", + "value": "" + }, + { + "key": "codeVerifier", + "value": "" + }, + { + "key": "proof_cwt", + "value": "" + } + ] +} diff --git a/pom.xml b/pom.xml index aecc473e..14671a35 100644 --- a/pom.xml +++ b/pom.xml @@ -100,7 +100,7 @@ 21 0.6.5 1.3.0-beta.1 - 1.3.0-beta.2-SNAPSHOT + 1.3.0-SNAPSHOT 0.5.0 2.5.0 1.7