From 683fcdf160dcec321dece4a537f11bbdafa32a3c Mon Sep 17 00:00:00 2001 From: Rakshitha650 <76676196+Rakshitha650@users.noreply.github.com> Date: Mon, 3 Apr 2023 12:43:02 +0530 Subject: [PATCH 01/61] [DSD-2409] updated the images (#176) --- helm/esignet/values.yaml | 4 ++-- helm/oidc-ui/values.yaml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/helm/esignet/values.yaml b/helm/esignet/values.yaml index b6fa6351c..7e9d11ffd 100644 --- a/helm/esignet/values.yaml +++ b/helm/esignet/values.yaml @@ -52,8 +52,8 @@ service: image: registry: docker.io - repository: mosipdev/esignet - tag: develop + repository: mosipqa/esignet + tag: 1.0.0 ## Specify a imagePullPolicy ## Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent' ## ref: http://kubernetes.io/docs/user-guide/images/#pre-pulling-images diff --git a/helm/oidc-ui/values.yaml b/helm/oidc-ui/values.yaml index d6c472ea4..cd4b92633 100755 --- a/helm/oidc-ui/values.yaml +++ b/helm/oidc-ui/values.yaml @@ -51,8 +51,8 @@ service: image: registry: docker.io - repository: mosipdev/oidc-ui - tag: MOSIP-25524 + repository: mosipqa/oidc-ui + tag: 1.0.0 ## Specify a imagePullPolicy ## Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent' From 1b50479c4ab2a48928fc132a6f185ce1b5cd70c2 Mon Sep 17 00:00:00 2001 From: ase-101 <> Date: Thu, 6 Apr 2023 08:01:10 +0530 Subject: [PATCH 02/61] MOSIP-26802 --- .../esignet/services/OAuthServiceImpl.java | 2 +- .../esignet/services/OAuthServiceTest.java | 75 ++++++++++++++++++- 2 files changed, 75 insertions(+), 2 deletions(-) diff --git a/oidc-service-impl/src/main/java/io/mosip/esignet/services/OAuthServiceImpl.java b/oidc-service-impl/src/main/java/io/mosip/esignet/services/OAuthServiceImpl.java index cd7abed0a..d3672cae0 100644 --- a/oidc-service-impl/src/main/java/io/mosip/esignet/services/OAuthServiceImpl.java +++ b/oidc-service-impl/src/main/java/io/mosip/esignet/services/OAuthServiceImpl.java @@ -75,7 +75,7 @@ public TokenResponse getTokens(TokenRequest tokenRequest) throws EsignetExceptio if(transaction == null || transaction.getKycToken() == null) throw new InvalidRequestException(ErrorConstants.INVALID_TRANSACTION); - if(StringUtils.isEmpty(tokenRequest.getClient_id()) || !transaction.getClientId().equals(tokenRequest.getClient_id())) + if(StringUtils.hasText(tokenRequest.getClient_id()) && !transaction.getClientId().equals(tokenRequest.getClient_id())) throw new InvalidRequestException(ErrorConstants.INVALID_CLIENT_ID); if(!transaction.getRedirectUri().equals(tokenRequest.getRedirect_uri())) diff --git a/oidc-service-impl/src/test/java/io/mosip/esignet/services/OAuthServiceTest.java b/oidc-service-impl/src/test/java/io/mosip/esignet/services/OAuthServiceTest.java index a05fcdddb..b73c08015 100644 --- a/oidc-service-impl/src/test/java/io/mosip/esignet/services/OAuthServiceTest.java +++ b/oidc-service-impl/src/test/java/io/mosip/esignet/services/OAuthServiceTest.java @@ -114,12 +114,85 @@ public void getTokens_withInvalidAuthCode_thenFail() { } @Test - public void getTokens_withInvalidClientId_thenFail() { + public void getTokens_withNullClientIdInRequest_thenPass() throws KycExchangeException { TokenRequest tokenRequest = new TokenRequest(); tokenRequest.setCode("test-code"); + tokenRequest.setRedirect_uri("https://test-redirect-uri/test-page"); + tokenRequest.setClient_assertion_type(JWT_BEARER_TYPE); + tokenRequest.setClient_assertion("client-assertion"); + + OIDCTransaction oidcTransaction = new OIDCTransaction(); + oidcTransaction.setClientId("client-id"); + oidcTransaction.setKycToken("kyc-token"); + oidcTransaction.setAuthTransactionId("auth-transaction-id"); + oidcTransaction.setRelyingPartyId("rp-id"); + oidcTransaction.setRedirectUri("https://test-redirect-uri/test-page"); + oidcTransaction.setIndividualId("individual-id"); + ClientDetail clientDetail = new ClientDetail(); + clientDetail.setRedirectUris(Arrays.asList("https://test-redirect-uri/**", "http://test-redirect-uri-2")); + KycExchangeResult kycExchangeResult = new KycExchangeResult(); + kycExchangeResult.setEncryptedKyc("encrypted-kyc"); + + Mockito.when(authorizationHelperService.getKeyHash(Mockito.anyString())).thenReturn("code-hash"); + ReflectionTestUtils.setField(authorizationHelperService, "secureIndividualId", false); + Mockito.when(cacheUtilService.getAuthCodeTransaction(Mockito.anyString())).thenReturn(oidcTransaction); + Mockito.when(clientManagementService.getClientDetails(Mockito.anyString())).thenReturn(clientDetail); + Mockito.when(authenticationWrapper.doKycExchange(Mockito.anyString(), Mockito.anyString(), Mockito.any())).thenReturn(kycExchangeResult); + Mockito.when(tokenService.getAccessToken(Mockito.any())).thenReturn("test-access-token"); + Mockito.when(tokenService.getIDToken(Mockito.any())).thenReturn("test-id-token"); + TokenResponse tokenResponse = oAuthService.getTokens(tokenRequest); + Assert.assertNotNull(tokenResponse); + Assert.assertNotNull(tokenResponse.getId_token()); + Assert.assertNotNull(tokenResponse.getAccess_token()); + Assert.assertEquals(BEARER, tokenResponse.getToken_type()); + Assert.assertEquals(kycExchangeResult.getEncryptedKyc(), oidcTransaction.getEncryptedKyc()); + } + + @Test + public void getTokens_withEmptyClientIdInRequest_thenPass() throws KycExchangeException { + TokenRequest tokenRequest = new TokenRequest(); + tokenRequest.setCode("test-code"); + tokenRequest.setClient_id(" "); + tokenRequest.setRedirect_uri("https://test-redirect-uri/test-page"); + tokenRequest.setClient_assertion_type(JWT_BEARER_TYPE); + tokenRequest.setClient_assertion("client-assertion"); + + OIDCTransaction oidcTransaction = new OIDCTransaction(); + oidcTransaction.setClientId("client-id"); + oidcTransaction.setKycToken("kyc-token"); + oidcTransaction.setAuthTransactionId("auth-transaction-id"); + oidcTransaction.setRelyingPartyId("rp-id"); + oidcTransaction.setRedirectUri("https://test-redirect-uri/test-page"); + oidcTransaction.setIndividualId("individual-id"); + ClientDetail clientDetail = new ClientDetail(); + clientDetail.setRedirectUris(Arrays.asList("https://test-redirect-uri/**", "http://test-redirect-uri-2")); + KycExchangeResult kycExchangeResult = new KycExchangeResult(); + kycExchangeResult.setEncryptedKyc("encrypted-kyc"); + + Mockito.when(authorizationHelperService.getKeyHash(Mockito.anyString())).thenReturn("code-hash"); + ReflectionTestUtils.setField(authorizationHelperService, "secureIndividualId", false); + Mockito.when(cacheUtilService.getAuthCodeTransaction(Mockito.anyString())).thenReturn(oidcTransaction); + Mockito.when(clientManagementService.getClientDetails(Mockito.anyString())).thenReturn(clientDetail); + Mockito.when(authenticationWrapper.doKycExchange(Mockito.anyString(), Mockito.anyString(), Mockito.any())).thenReturn(kycExchangeResult); + Mockito.when(tokenService.getAccessToken(Mockito.any())).thenReturn("test-access-token"); + Mockito.when(tokenService.getIDToken(Mockito.any())).thenReturn("test-id-token"); + TokenResponse tokenResponse = oAuthService.getTokens(tokenRequest); + Assert.assertNotNull(tokenResponse); + Assert.assertNotNull(tokenResponse.getId_token()); + Assert.assertNotNull(tokenResponse.getAccess_token()); + Assert.assertEquals(BEARER, tokenResponse.getToken_type()); + Assert.assertEquals(kycExchangeResult.getEncryptedKyc(), oidcTransaction.getEncryptedKyc()); + } + + @Test + public void getTokens_withInvalidClientIdInRequest_thenFail() { + TokenRequest tokenRequest = new TokenRequest(); + tokenRequest.setCode("test-code"); + tokenRequest.setClient_id("t"); OIDCTransaction oidcTransaction = new OIDCTransaction(); oidcTransaction.setKycToken("kyc-token"); + oidcTransaction.setClientId("test-test"); Mockito.when(authorizationHelperService.getKeyHash(Mockito.anyString())).thenReturn("code-hash"); Mockito.when(cacheUtilService.getAuthCodeTransaction(Mockito.anyString())).thenReturn(oidcTransaction); From 120124c650a99ca9ac525ad4068461547a34d913 Mon Sep 17 00:00:00 2001 From: syed salman <72004356+syedsalman3753@users.noreply.github.com> Date: Wed, 12 Apr 2023 12:54:45 +0530 Subject: [PATCH 03/61] [ MOSIP-26666 ] updated README.md (#177) (#181) * [ MOSIP-26666 ] updated README.md (#177) * [ MOSIP-26666 ] updated README.md * [ MOSIP-26666 ] updated README.md * [ MOSIP-26666 ] updated README.md * [ MOSIP-26666 ] updated README.md based on review changes requested * [ MOSIP-26666 ] updated README.md --------- Co-authored-by: syed-salman-technoforte * [ MOSIP-26666 ] Updated esignet scripts --------- Co-authored-by: syed-salman-technoforte --- .github/workflows/release_chart.yml | 2 +- README.md | 52 +++++++++++++++++++++++++++++ db_scripts/README.md | 29 +++++++++++++--- helm/esignet/Chart.yaml | 2 +- helm/esignet/README.md | 6 ++-- helm/esignet/install.sh | 4 +-- helm/oidc-ui/Chart.yaml | 2 +- helm/oidc-ui/install.sh | 8 +++-- helm/redis/install.sh | 2 +- 9 files changed, 90 insertions(+), 17 deletions(-) diff --git a/.github/workflows/release_chart.yml b/.github/workflows/release_chart.yml index 4c9e2158c..98c63f92b 100644 --- a/.github/workflows/release_chart.yml +++ b/.github/workflows/release_chart.yml @@ -19,6 +19,6 @@ jobs: with: token: ${{ secrets.ACTION_PAT }} charts_dir: ./helm - charts_url: https://github.com/mosip + charts_url: https://mosip.github.io/mosip-helm repository: mosip-helm branch: gh-pages diff --git a/README.md b/README.md index 5524b9525..6a7b17c22 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,58 @@ The project requires JDK 11. $ docker build -f Dockerfile ``` +## Installing in k8s cluster using helm +### Pre-requisites +1. Set the kube config file of the Mosip cluster having dependent services is set correctly in PC. +1. Make sure [DB setup](db_scripts/README.md#install-in-existing-mosip-k8-cluster) is done. +1. Add / merge below mentioned properties files into existing config branch: + * [esignet-default.properties](https://github.com/mosip/mosip-config/blob/v1.2.0.1-B3/esignet-default.properties) + * [application-default.properties](https://github.com/mosip/mosip-config/blob/v1.2.0.1-B3/application-default.properties) +1. Below are the dependent services required for esignet service: + | Chart | Chart version | + |---|---| + |[Keycloak](https://github.com/mosip/mosip-infra/tree/v1.2.0.1-B3/deployment/v3/external/iam) | 7.1.18 | + |[Keycloak-init](https://github.com/mosip/mosip-infra/tree/v1.2.0.1-B3/deployment/v3/external/iam) | 12.0.1-B3 | + |[Postgres](https://github.com/mosip/mosip-infra/tree/v1.2.0.1-B3/deployment/v3/external/postgres) | 10.16.2 | + |[Postgres Init](https://github.com/mosip/mosip-infra/tree/v1.2.0.1-B3/deployment/v3/external/postgres) | 12.0.1-B3 | + |[Minio](https://github.com/mosip/mosip-infra/tree/v1.2.0.1-B3/deployment/v3/external/object-store) | 10.1.6 | + |[Kafka](https://github.com/mosip/mosip-infra/tree/v1.2.0.1-B3/deployment/v3/external/kafka) | 0.4.2 | + |[Config-server](https://github.com/mosip/mosip-infra/tree/v1.2.0.1-B3/deployment/v3/mosip/config-server) | 12.0.1-B3 | + |[Websub](https://github.com/mosip/mosip-infra/tree/v1.2.0.1-B3/deployment/v3/mosip/websub) | 12.0.1-B2 | + |[Artifactory server](https://github.com/mosip/mosip-infra/tree/v1.2.0.1-B3/deployment/v3/mosip/artifactory) | 12.0.1-B3 | + |[Keymanager service](https://github.com/mosip/mosip-infra/blob/v1.2.0.1-B3/deployment/v3/mosip/keymanager) | 12.0.1-B2 | + |[Kernel services](https://github.com/mosip/mosip-infra/blob/v1.2.0.1-B3/deployment/v3/mosip/kernel) | 12.0.1-B2 | + |[Biosdk service](https://github.com/mosip/mosip-infra/tree/v1.2.0.1-B3/deployment/v3/mosip/biosdk) | 12.0.1-B3 | + |[Idrepo services](https://github.com/mosip/mosip-infra/blob/v1.2.0.1-B3/deployment/v3/mosip/idrepo) | 12.0.1-B2 | + |[Pms services](https://github.com/mosip/mosip-infra/blob/v1.2.0.1-B3/deployment/v3/mosip/pms) | 12.0.1-B3 | + |[IDA services](https://github.com/mosip/mosip-infra/blob/v1.2.0.1-B3/deployment/v3/mosip/ida) | 12.0.1-B3 | + +### Install +* Install `kubectl` and `helm` utilities. +* Run `install-all.sh` to deploy esignet services. + ``` + cd helm + ./install-all.sh + ``` + +### Delete +* Run `delete-all.sh` to remove esignet services. + ``` + cd helm + ./delete-all.sh + ``` + +### Restart +* Run `restart-all.sh` to restart esignet services. + ``` + cd helm + ./restart-all.sh + ``` + +## Onboard esignet +* Run onboarder's [install.sh](https://github.com/mosip/mosip-infra/blob/v1.2.0.1-B3/deployment/v3/mosip/partner-onboarder) script to exchange jwk certificates. + + ## APIs API documentation is available [here](https://mosip.stoplight.io/docs/identity-provider/branches/main/6f1syzijynu40-identity-provider). diff --git a/db_scripts/README.md b/db_scripts/README.md index db4348ca9..63dc97928 100644 --- a/db_scripts/README.md +++ b/db_scripts/README.md @@ -1,13 +1,32 @@ -# e-Signet +# e-Signet Database Open ID based Identity provider for large scale authentication. +## Overview +This folder containers various SQL scripts to create database and tables in postgres. +The tables are described under `/ddl/`. +Default data that's populated in the tables is present under `/dml` folder. + ## Prerequisites * Make sure DB changes for IDA and PMS are up to date. * If not upgraded, IDA DB using the [release script](https://github.com/mosip/id-authentication/tree/develop/db_release_scripts). * If not upgraded, PMS DB using the [release script](https://github.com/mosip/partner-management-services/tree/develop/db_release_scripts). - -## Initialize esignet DB -* To initialize esignet DB, run below script. +* Command line utilities: + - kubectl + - helm +* Helm repos: ```sh - ./init_db.sh + helm repo add bitnami https://charts.bitnami.com/bitnami + helm repo add mosip https://mosip.github.io/mosip-helm + ``` + +## Install in existing MOSIP K8 Cluster +These scripts are automatically run with below mentioned script in existing k8 cluster with Postgres installed. +### Install +* Set your kube_config file or kube_config variable on PC. +* Update `init_values.yaml` with db-common-password from the postgres namespace in the required field `dbUserPasswords.dbuserPassword` and ensure `databases.mosip_esignet` is enabled. + ``` + ./init_db.sh` ``` + +## Install for developers +Developers may run the SQLs using `/deploy.sh` script. diff --git a/helm/esignet/Chart.yaml b/helm/esignet/Chart.yaml index d82f2d013..37cb783b6 100644 --- a/helm/esignet/Chart.yaml +++ b/helm/esignet/Chart.yaml @@ -2,7 +2,7 @@ apiVersion: v2 name: esignet description: A Helm chart for MOSIP esignet module type: application -version: 0.0.1 +version: 1.0.1 appVersion: "" dependencies: - name: common diff --git a/helm/esignet/README.md b/helm/esignet/README.md index 729a382cd..7c5e2871c 100644 --- a/helm/esignet/README.md +++ b/helm/esignet/README.md @@ -11,7 +11,7 @@ $ helm install my-release mosip/esignet ## Introduction -esignet is part of the esignet modules, but has a separate Helm chart so as to install and manage it in a completely indepedent namespace. +esignet is part of the esignet modules, but has a separate Helm chart so as to install and manage it in a completely independent namespace. ## Prerequisites @@ -23,8 +23,8 @@ esignet is part of the esignet modules, but has a separate Helm chart so as to i ## Overview Refer [Commons](https://docs.mosip.io/1.2.0/modules/commons). -## Initialize keycloak for IDP -* To initialize keycloak for IDP, run below script. +## Initialize keycloak for esignet +* To initialize keycloak for esignet, run below script. ```sh ./keycloak-init.sh ``` diff --git a/helm/esignet/install.sh b/helm/esignet/install.sh index ec6318ee5..c7feb810a 100755 --- a/helm/esignet/install.sh +++ b/helm/esignet/install.sh @@ -7,7 +7,7 @@ if [ $# -ge 1 ] ; then fi NS=esignet -CHART_VERSION=0.0.1 +CHART_VERSION=1.0.1 ./keycloak-init.sh @@ -15,7 +15,7 @@ echo Copy configmaps ./copy_cm.sh echo Installing esignet -helm -n $NS install esignet . --version $CHART_VERSION +helm -n $NS install esignet mosip/esignet --version $CHART_VERSION kubectl -n $NS get deploy -o name | xargs -n1 -t kubectl -n $NS rollout status diff --git a/helm/oidc-ui/Chart.yaml b/helm/oidc-ui/Chart.yaml index d8aa41cb5..9cf547c48 100644 --- a/helm/oidc-ui/Chart.yaml +++ b/helm/oidc-ui/Chart.yaml @@ -2,7 +2,7 @@ apiVersion: v2 name: oidc-ui description: A Helm chart for MOSIP OIDC UI module type: application -version: 12.0.2 +version: 1.0.1 appVersion: "" dependencies: - name: common diff --git a/helm/oidc-ui/install.sh b/helm/oidc-ui/install.sh index b0cdf4d7c..6e250d49c 100755 --- a/helm/oidc-ui/install.sh +++ b/helm/oidc-ui/install.sh @@ -7,14 +7,16 @@ if [ $# -ge 1 ] ; then fi NS=esignet -CHART_VERSION=0.0.1 +CHART_VERSION=1.0.1 echo Create $NS namespace kubectl create ns $NS echo Istio label kubectl label ns $NS istio-injection=enabled --overwrite -helm dependency build + +helm repo add mosip https://mosip.github.io/mosip-helm +helm repo update echo Copy configmaps ./copy_cm.sh @@ -26,7 +28,7 @@ kubectl -n $NS delete --ignore-not-found=true configmap oidc-ui-cm kubectl -n $NS create configmap oidc-ui-cm --from-literal="REACT_APP_API_BASE_URL=http://esignet.$NS/v1/esignet" --from-literal="REACT_APP_SBI_DOMAIN_URI=http://esignet.$NS" echo Installing OIDC UI -helm -n $NS install oidc-ui . --set istio.hosts\[0\]=$ESIGNET_HOST +helm -n $NS install oidc-ui mosip/oidc-ui --set istio.hosts\[0\]=$ESIGNET_HOST kubectl -n $NS get deploy -o name | xargs -n1 -t kubectl -n $NS rollout status diff --git a/helm/redis/install.sh b/helm/redis/install.sh index 75675e755..011da045b 100755 --- a/helm/redis/install.sh +++ b/helm/redis/install.sh @@ -22,7 +22,7 @@ helm repo update echo Installing redis helm -n $NS install redis bitnami/redis --wait --version $CHART_VERSION -./copy_cm_func.sh secret redis redis config-server +../copy_cm_func.sh secret redis redis config-server kubectl -n config-server set env --keys=redis-password --from secret/redis deployment/config-server --prefix=SPRING_CLOUD_CONFIG_SERVER_OVERRIDES_ From 8b92a86ae3a7b18e5cbcb9932660f285c22f9fdf Mon Sep 17 00:00:00 2001 From: syed salman <72004356+syedsalman3753@users.noreply.github.com> Date: Wed, 12 Apr 2023 23:59:51 +0530 Subject: [PATCH 04/61] [ MOSIP-26666 ] added onboarder for esignet and resident oidc (#184) Co-authored-by: syed-salman-technoforte --- README.md | 2 +- partner-onboarder/README.md | 33 ++++++++++++++++ partner-onboarder/copy_cm.sh | 10 +++++ partner-onboarder/copy_cm_func.sh | 33 ++++++++++++++++ partner-onboarder/copy_secrets.sh | 10 +++++ partner-onboarder/delete.sh | 28 +++++++++++++ partner-onboarder/install.sh | 66 +++++++++++++++++++++++++++++++ partner-onboarder/values.yaml | 22 +++++++++++ 8 files changed, 203 insertions(+), 1 deletion(-) create mode 100644 partner-onboarder/README.md create mode 100755 partner-onboarder/copy_cm.sh create mode 100755 partner-onboarder/copy_cm_func.sh create mode 100755 partner-onboarder/copy_secrets.sh create mode 100755 partner-onboarder/delete.sh create mode 100755 partner-onboarder/install.sh create mode 100644 partner-onboarder/values.yaml diff --git a/README.md b/README.md index 6a7b17c22..82b326e17 100644 --- a/README.md +++ b/README.md @@ -78,7 +78,7 @@ The project requires JDK 11. ``` ## Onboard esignet -* Run onboarder's [install.sh](https://github.com/mosip/mosip-infra/blob/v1.2.0.1-B3/deployment/v3/mosip/partner-onboarder) script to exchange jwk certificates. +* Run onboarder's [install.sh](partner-onboarder) script to exchange jwk certificates. ## APIs diff --git a/partner-onboarder/README.md b/partner-onboarder/README.md new file mode 100644 index 000000000..bead756eb --- /dev/null +++ b/partner-onboarder/README.md @@ -0,0 +1,33 @@ +# Partner Onboarder + +## Overview +Loads certs for default partners for sandbox. Refer [mosip-onboarding repo](https://github.com/mosip/mosip-onboarding). + +## Install +* Set `values.yaml` to run onboarder for specific modules. +* run `./install.sh`. +``` +./install.sh +``` +# Troubleshootings + +* After completion of the job, a very detailed `html report` is prepared and stored at https://onboarder.{sandbox_base_url}.mosip.net + +* The user can go and view the same for more information or response messages. + +### Commonly found issues + + 1. KER-ATH-401: Authentication Failed + + Resolution: You need to provide correct secretkey for mosip-deployment-client. + + 2. Certificate dates are not valid + + Resolution: Check with admin regarding adding grace period in configuration. + + 3. Upload of certificate will not be allowed to update other domain certificate + + Resolution: This is expected when you try to upload `ida-cred` certificate twice. It should only run once and if you see this error while uploading a second time it can be ignored as the cert is already present. + + + diff --git a/partner-onboarder/copy_cm.sh b/partner-onboarder/copy_cm.sh new file mode 100755 index 000000000..9d69e0713 --- /dev/null +++ b/partner-onboarder/copy_cm.sh @@ -0,0 +1,10 @@ +#!/bin/bash +# Copy configmaps from other namespaces +# DST_NS: Destination namespace + +COPY_UTIL=./copy_cm_func.sh +DST_NS=esignet + +$COPY_UTIL configmap global default $DST_NS +$COPY_UTIL configmap keycloak-env-vars keycloak $DST_NS +$COPY_UTIL configmap keycloak-host keycloak $DST_NS diff --git a/partner-onboarder/copy_cm_func.sh b/partner-onboarder/copy_cm_func.sh new file mode 100755 index 000000000..7b2259486 --- /dev/null +++ b/partner-onboarder/copy_cm_func.sh @@ -0,0 +1,33 @@ +#!/bin/sh +# Copy configmap and secret from one namespace to another. +# ./copy_cm_func.sh [name] +# Parameters: +# resource: configmap|secret +# name: Optional new name of the configmap or secret in destination namespace. This may be needed if there is +# clash of names + +if [ $1 = "configmap" ] +then + RESOURCE=configmap +elif [ $1 = "secret" ] +then + RESOURCE=secret +else + echo "Incorrect resource $1. Exiting.." + exit 1 +fi + + +if [ $# -ge 5 ] +then + kubectl -n $4 delete --ignore-not-found=true $RESOURCE $5 + kubectl -n $3 get $RESOURCE $2 -o yaml | sed "s/namespace: $3/namespace: $4/g" | sed "s/name: $2/name: $5/g" | kubectl -n $4 create -f - +else + kubectl -n $4 delete --ignore-not-found=true $RESOURCE $2 + kubectl -n $3 get $RESOURCE $2 -o yaml | sed "s/namespace: $3/namespace: $4/g" | kubectl -n $4 create -f - +fi + + + + + diff --git a/partner-onboarder/copy_secrets.sh b/partner-onboarder/copy_secrets.sh new file mode 100755 index 000000000..0438ce7e4 --- /dev/null +++ b/partner-onboarder/copy_secrets.sh @@ -0,0 +1,10 @@ +#!/bin/bash +# Copy secrets from other namespaces +# DST_NS: Destination namespace + +COPY_UTIL=./copy_cm_func.sh +DST_NS=esignet + +$COPY_UTIL secret s3 s3 $DST_NS +$COPY_UTIL secret keycloak keycloak $DST_NS +$COPY_UTIL secret keycloak-client-secrets keycloak $DST_NS diff --git a/partner-onboarder/delete.sh b/partner-onboarder/delete.sh new file mode 100755 index 000000000..e94f6f86b --- /dev/null +++ b/partner-onboarder/delete.sh @@ -0,0 +1,28 @@ +#!/bin/bash +# Uninstalls partner-onboarder helm +## Usage: ./delete.sh [kubeconfig] + +if [ $# -ge 1 ] ; then + export KUBECONFIG=$1 +fi + +function deleting_onboarder() { + NS=esignet + while true; do + read -p "Are you sure you want to delete all partner-onboarder ?(Y/n) " yn + if [ $yn = "Y" ]; then + echo Deleting esignet-resident-oidc-partner-onboarder helm + helm -n $NS delete esignet-resident-oidc-partner-onboarder + break + fi + done + return 0 +} + +# set commands for error handling. +set -e +set -o errexit ## set -e : exit the script if any statement returns a non-true return value +set -o nounset ## set -u : exit the script if you try to use an uninitialised variable +set -o errtrace # trace ERR through 'time command' and other functions +set -o pipefail # trace ERR through pipes +deleting_onboarder # calling function diff --git a/partner-onboarder/install.sh b/partner-onboarder/install.sh new file mode 100755 index 000000000..ae22f1174 --- /dev/null +++ b/partner-onboarder/install.sh @@ -0,0 +1,66 @@ +#!/bin/bash +# Onboards default partners +## Usage: ./install.sh [kubeconfig] + +if [ $# -ge 1 ] ; then + export KUBECONFIG=$1 +fi + +echo "Do you have public domain & valid SSL? (Y/n) " +echo "Y: if you have public domain & valid ssl certificate" +echo "n: if you don't have public domain & valid ssl certificate" +read -p "" flag + +if [ -z "$flag" ]; then + echo "'flag' was provided; EXITING;" + exit 1; +fi +ENABLE_INSECURE='' +if [ "$flag" = "n" ]; then + ENABLE_INSECURE='--set onboarding.enableInsecure=true'; +fi + +NS=esignet +CHART_VERSION=12.0.1-B3 + +echo Create $NS namespace +kubectl create ns $NS + +function installing_onboarder() { + + read -p "Is values.yaml for onboarder chart set correctly as part of Pre-requisites?(Y/n) " yn; + if [ $yn = "Y" ]; then + echo Istio label + kubectl label ns $NS istio-injection=disabled --overwrite + helm repo update + + echo Copy configmaps + kubectl -n $NS --ignore-not-found=true delete cm s3 + sed -i 's/\r$//' copy_cm.sh + ./copy_cm.sh + + echo Copy secrets + sed -i 's/\r$//' copy_secrets.sh + ./copy_secrets.sh + + echo Onboarding default partners + helm -n $NS install esignet-resident-oidc-partner-onboarder mosip/partner-onboarder \ + --set onboarding.configmaps.s3.s3-host='http://minio.minio:9000' \ + --set onboarding.configmaps.s3.s3-user-key='admin' \ + --set onboarding.configmaps.s3.s3-region='' \ + $ENABLE_INSECURE \ + -f values.yaml \ + --version $CHART_VERSION + + echo Reports are moved to S3 under onboarder bucket + return 0 + fi +} + +# set commands for error handling. +set -e +set -o errexit ## set -e : exit the script if any statement returns a non-true return value +set -o nounset ## set -u : exit the script if you try to use an uninitialised variable +set -o errtrace # trace ERR through 'time command' and other functions +set -o pipefail # trace ERR through pipes +installing_onboarder # calling function diff --git a/partner-onboarder/values.yaml b/partner-onboarder/values.yaml new file mode 100644 index 000000000..bd9865c88 --- /dev/null +++ b/partner-onboarder/values.yaml @@ -0,0 +1,22 @@ +onboarding: + modules: + - name: ida + enabled: false + - name: print + enabled: false + - name: abis + enabled: false + - name: resident + enabled: false + - name: mobileid + enabled: false + - name: digitalcard + enabled: false + - name: esignet + enabled: true + - name: resident-oidc + enabled: true + - name: demo-oidc + enabled: false + - name: mimoto-keybinding + enabled: false \ No newline at end of file From 87f22aff7b7d2ba49d73789d65d734f1873a6336 Mon Sep 17 00:00:00 2001 From: ase-101 <> Date: Tue, 18 Apr 2023 18:43:04 +0530 Subject: [PATCH 05/61] Updated the postman env --- docs/Esignet.postman_environment.json | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/docs/Esignet.postman_environment.json b/docs/Esignet.postman_environment.json index fda24995f..8e016b910 100644 --- a/docs/Esignet.postman_environment.json +++ b/docs/Esignet.postman_environment.json @@ -9,7 +9,7 @@ }, { "key": "relayingPartyId", - "value": "mpartner-default-idp-relyparty-new", + "value": "mpartner-default-esignet", "enabled": true }, { @@ -29,7 +29,7 @@ }, { "key": "claims", - "value": "{\n \"userinfo\": {\n \"given_name\": {\n \"essential\": true\n },\n \"phone_number\": null,\n ...", + "value": "{\"userinfo\":{\"given_name\":{\"essential\":true},\"phone_number\":{\"essential\":false},\"email\":{\"essential\":true},\"picture\":{\"essential\":false},\"gender\":{\"essential\":false},\"birthdate\":{\"essential\":false},\"address\":{\"essential\":false}},\"id_token\":{}}", "enabled": true }, { @@ -44,17 +44,12 @@ }, { "key": "url", - "value": "https://api.dev.mosip.net/v1/idp", + "value": "https://esignet.dev.mosip.net/v1/esignet", "enabled": true }, { "key": "aud", - "value": "https://api.dev.mosip.net/v1/idp/oauth/token", - "enabled": true - }, - { - "key": "csrf_token", - "value": "", + "value": "https://esignet.dev.mosip.net/v1/esignet/oauth/token", "enabled": true }, { From c257fa14d4bb1bbf1c61915806d8e49fcbba066f Mon Sep 17 00:00:00 2001 From: KONIJETI YASWANTHA NAGARJUNA <50859121+YaswanthNagarjuna@users.noreply.github.com> Date: Wed, 10 May 2023 17:03:03 +0530 Subject: [PATCH 06/61] otp length configurable --- oidc-ui/.env | 4 +++- oidc-ui/src/components/OtpVerify.js | 22 +++++++++++++--------- oidc-ui/src/constants/clientConstants.js | 1 + 3 files changed, 17 insertions(+), 10 deletions(-) diff --git a/oidc-ui/.env b/oidc-ui/.env index 6a7282874..a5ec6831c 100644 --- a/oidc-ui/.env +++ b/oidc-ui/.env @@ -34,4 +34,6 @@ REACT_APP_CAPTCHA_ENABLE="OTP" #site key for testing purposes only REACT_APP_CAPTCHA_SITE_KEY="6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI" -REACT_APP_AUTH_TXN_ID_LENGTH=10 \ No newline at end of file +REACT_APP_AUTH_TXN_ID_LENGTH=10 + +REACT_APP_OTP_LENGTH=6 \ No newline at end of file diff --git a/oidc-ui/src/components/OtpVerify.js b/oidc-ui/src/components/OtpVerify.js index 30cef3963..b3d4ea55e 100644 --- a/oidc-ui/src/components/OtpVerify.js +++ b/oidc-ui/src/components/OtpVerify.js @@ -37,6 +37,10 @@ export default function OtpVerify({ const commaSeparatedChannels = openIDConnectService.getEsignetConfiguration(configurationKeys.sendOtpChannels) ?? process.env.REACT_APP_SEND_OTP_CHANNELS; + const otpLengthValue = + openIDConnectService.getEsignetConfiguration(configurationKeys.otpLength) ?? + process.env.REACT_APP_OTP_LENGTH; + const otpLength = parseInt(otpLengthValue); const [loginState, setLoginState] = useState(fieldsState); const [error, setError] = useState(null); @@ -234,7 +238,7 @@ export default function OtpVerify({
{ setOtpValue(value); @@ -265,18 +269,18 @@ export default function OtpVerify({ {otpSentEmail && otpSentMobile ? t("otp_sent_msg", { - otpChannels: t("mobile_email_placeholder", { - mobileNumber: otpSentMobile, - emailAddress: otpSentEmail, - }), - }) + otpChannels: t("mobile_email_placeholder", { + mobileNumber: otpSentMobile, + emailAddress: otpSentEmail, + }), + }) : otpSentEmail - ? t("otp_sent_msg", { + ? t("otp_sent_msg", { otpChannels: t("email_placeholder", { emailAddress: otpSentEmail, }), }) - : t("otp_sent_msg", { + : t("otp_sent_msg", { otpChannels: t("mobile_placeholder", { mobileNumber: otpSentMobile, }), @@ -298,7 +302,7 @@ export default function OtpVerify({
diff --git a/oidc-ui/src/constants/clientConstants.js b/oidc-ui/src/constants/clientConstants.js index 402c8fdf5..8f66eb419 100644 --- a/oidc-ui/src/constants/clientConstants.js +++ b/oidc-ui/src/constants/clientConstants.js @@ -67,6 +67,7 @@ const configurationKeys = { appDownloadURI: "mosip.esignet.qr-code.download-uri", signInWithQRCodeEnable: "mosip.esignet.qr-code.enable", authTxnIdLength: "auth.txnid.length", + otpLength: "otp.length", }; export { From 44a20c940f9135105b2617829909ebf9804b3052 Mon Sep 17 00:00:00 2001 From: KONIJETI YASWANTHA NAGARJUNA <50859121+YaswanthNagarjuna@users.noreply.github.com> Date: Wed, 10 May 2023 18:21:03 +0530 Subject: [PATCH 07/61] Login with Password Added --- oidc-ui/public/locales/ar.json | 13 +- oidc-ui/public/locales/en.json | 15 ++- oidc-ui/src/components/Password.js | 160 +++++++++++++++++++++++ oidc-ui/src/components/SignInOptions.js | 1 + oidc-ui/src/constants/clientConstants.js | 3 + oidc-ui/src/constants/formFields.js | 29 +++- oidc-ui/src/pages/Login.js | 18 ++- 7 files changed, 233 insertions(+), 6 deletions(-) create mode 100644 oidc-ui/src/components/Password.js diff --git a/oidc-ui/public/locales/ar.json b/oidc-ui/public/locales/ar.json index fb1171de8..82e651a93 100644 --- a/oidc-ui/public/locales/ar.json +++ b/oidc-ui/public/locales/ar.json @@ -60,6 +60,16 @@ "uin_placeholder": "UIN أو VID", "pin_placeholder": "أدخل رقم التعريف الشخصي" }, + "password": { + "sign_in_with_password": "تسجيل الدخول باستخدام كلمة المرور", + "remember_me": "تذكرنى", + "login": "تسجيل الدخول", + "uin_label_text": "أدخل VID الخاص بك", + "password_label_text": "أدخل كلمة المرور", + "uin_placeholder": "VID", + "password_placeholder": "كلمة المرور", + "password_error_msg": "رمز مرور خاطئ" + }, "LoginQRCode": { "sign_in_with_inji": "تسجيل الدخول باستخدام Inji", "scan_with_inji": "امسح باستخدام تطبيق Inji لتسجيل الدخول", @@ -97,7 +107,8 @@ "BIO": "القياسات الحيوية", "QRCode": "رمز الاستجابة السريعة", "WALLET": "إنجي", - "OTP": "OTP" + "OTP": "OTP", + "PWD": "كلمة المرور" }, "esignetDetails": { "esignet_details_heading": "واجهات برمجة التطبيقات Esignet معروفة جيدا", diff --git a/oidc-ui/public/locales/en.json b/oidc-ui/public/locales/en.json index 43aa1105e..29195cfe5 100644 --- a/oidc-ui/public/locales/en.json +++ b/oidc-ui/public/locales/en.json @@ -60,6 +60,16 @@ "uin_placeholder": "UIN or VID", "pin_placeholder": "Enter PIN" }, + "password": { + "sign_in_with_password": "Login with Password", + "remember_me": "Remember Me", + "login": "Login", + "uin_label_text": "Enter your VID", + "password_label_text": "Enter Password", + "uin_placeholder": "VID", + "password_placeholder": "Password", + "password_error_msg": "Invalid Password" + }, "LoginQRCode": { "sign_in_with_inji": "Login with Inji", "scan_with_inji": "Scan with Inji App to Log In", @@ -97,7 +107,8 @@ "BIO": "Biometrics", "QRCode": "QR Code", "WALLET": "Inji", - "OTP": "OTP" + "OTP": "OTP", + "PWD": "Password" }, "esignetDetails": { "esignet_details_heading": "Esignet wellknown APIs", @@ -213,7 +224,7 @@ "sha256_thumbprint_header_missing": "Missing x5t#S256 header in WLA token.", "invalid_challenge_format": "Invalid Authentication challenge format found.", "link_code_limit_reached": "Number of allowed Link code per transaction limit reached.", - "failed_to_generate_header_hash":"Failed to generate oauth-details-hash http header value.", + "failed_to_generate_header_hash": "Failed to generate oauth-details-hash http header value.", "invalid_individual_id": "Invalid Individual ID", "invalid_pin": "Invalid Pin", "invalid_email": "Invalid Email ID", diff --git a/oidc-ui/src/components/Password.js b/oidc-ui/src/components/Password.js new file mode 100644 index 000000000..db5028c4e --- /dev/null +++ b/oidc-ui/src/components/Password.js @@ -0,0 +1,160 @@ +import { useState } from "react"; +import { useTranslation } from "react-i18next"; +import { useNavigate } from "react-router-dom"; +import ErrorIndicator from "../common/ErrorIndicator"; +import LoadingIndicator from "../common/LoadingIndicator"; +import { + buttonTypes, + challengeFormats, + challengeTypes, +} from "../constants/clientConstants"; +import { passwordFields } from "../constants/formFields"; +import { LoadingStates as states } from "../constants/states"; +import FormAction from "./FormAction"; +import InputWithImage from "./InputWithImage"; + +const fields = passwordFields; +let fieldsState = {}; +fields.forEach((field) => (fieldsState["Password" + field.id] = "")); + +export default function Password({ + param, + authService, + openIDConnectService, + i18nKeyPrefix = "password", +}) { + const { t } = useTranslation("translation", { keyPrefix: i18nKeyPrefix }); + + const fields = param; + const post_AuthenticateUser = authService.post_AuthenticateUser; + const buildRedirectParams = authService.buildRedirectParams; + + const [loginState, setLoginState] = useState(fieldsState); + const [error, setError] = useState(null); + const [status, setStatus] = useState(states.LOADED); + + const navigate = useNavigate(); + + const handleChange = (e) => { + setLoginState({ ...loginState, [e.target.id]: e.target.value }); + }; + + const handleSubmit = (e) => { + e.preventDefault(); + authenticateUser(); + }; + + //Handle Login API Integration here + const authenticateUser = async () => { + try { + let transactionId = openIDConnectService.getTransactionId(); + + let uin = loginState["Password_mosip-uin"]; + let challengeType = challengeTypes.pwd; + let challenge = loginState["Password_password"]; + let challengeFormat = challengeFormats.pwd; + + const passwordRegex = /[0-9a-zA-Z]{8,}$/; + if (!passwordRegex.test(challenge)) { + setError({ + defaultMsg: t("password_error_msg") + }); + return; + } + + let challengeList = [ + { + authFactorType: challengeType, + challenge: challenge, + format: challengeFormat, + }, + ]; + + setStatus(states.LOADING); + const authenticateResponse = await post_AuthenticateUser( + transactionId, + uin, + challengeList + ); + + setStatus(states.LOADED); + + const { errors } = authenticateResponse; + + if (errors != null && errors.length > 0) { + setError({ + prefix: "authentication_failed_msg", + errorCode: errors[0].errorCode, + defaultMsg: errors[0].errorMessage, + }); + return; + } else { + setError(null); + + let nonce = openIDConnectService.getNonce(); + let state = openIDConnectService.getState(); + + let params = buildRedirectParams( + nonce, + state, + openIDConnectService.getOAuthDetails() + ); + + navigate("/consent" + params, { + replace: true, + }); + } + } catch (error) { + setError({ + prefix: "authentication_failed_msg", + errorCode: error.message, + defaultMsg: error.message, + }); + setStatus(states.ERROR); + } + }; + + return ( + <> +

+ {t("sign_in_with_password")} +

+
+ {fields.map((field) => ( +
+ +
+ ))} + + + + {status === states.LOADING && ( +
+ +
+ )} + {status !== states.LOADING && error && ( + + )} + + ); +} diff --git a/oidc-ui/src/components/SignInOptions.js b/oidc-ui/src/components/SignInOptions.js index 79620be07..6e1e55b8b 100644 --- a/oidc-ui/src/components/SignInOptions.js +++ b/oidc-ui/src/components/SignInOptions.js @@ -19,6 +19,7 @@ export default function SignInOptions({ OTP: "images/sign_in_with_otp.png", WALLET: "images/Sign in with Inji.png", BIO: "images/Sign in with fingerprint.png", + PWD: "images/sign_in_with_otp.png" }; useEffect(() => { diff --git a/oidc-ui/src/constants/clientConstants.js b/oidc-ui/src/constants/clientConstants.js index 8f66eb419..ed41a1f84 100644 --- a/oidc-ui/src/constants/clientConstants.js +++ b/oidc-ui/src/constants/clientConstants.js @@ -9,6 +9,7 @@ const challengeTypes = { pin: "PIN", otp: "OTP", wallet: "WALLET", + pwd: "PWD" }; const challengeFormats = { @@ -16,6 +17,7 @@ const challengeFormats = { pin: "number", otp: "alpha-numeric", wallet: "jwt", + pwd: "alpha-numeric" }; @@ -23,6 +25,7 @@ const validAuthFactors = { PIN: "PIN", OTP: "OTP", BIO: "BIO", + PWD: "PWD" }; const buttonTypes = { diff --git a/oidc-ui/src/constants/formFields.js b/oidc-ui/src/constants/formFields.js index ab118030e..50701acab 100644 --- a/oidc-ui/src/constants/formFields.js +++ b/oidc-ui/src/constants/formFields.js @@ -20,6 +20,28 @@ const pinFields = [ placeholder: "pin_placeholder", //translation key for pin namespace }, ]; +const passwordFields = [ + { + labelText: "uin_label_text", //translation key for password namespace + labelFor: "Mosip Uin", + id: "mosip-uin", + name: "uin", + type: "text", + autoComplete: "uin", + isRequired: true, + placeholder: "uin_placeholder", //translation key for password namespace + }, + { + labelText: "password_label_text", + labelFor: "password", + id: "password", + name: "password", + type: "password", + autoComplete: "", + isRequired: true, + placeholder: "password_placeholder", //translation key for password namespace + }, +]; const otpFields = [ { @@ -109,6 +131,11 @@ const tabList = [ icon: "bio_capture", comp: "Biometrics", }, + { + name: "password_tab_name", //translation key for tabs namespace + icon: "space-shuttle", + comp: "Password", + } ]; -export { pinFields, otpFields, signupFields, tabList, bioLoginFields }; +export { pinFields, otpFields, signupFields, tabList, bioLoginFields, passwordFields }; diff --git a/oidc-ui/src/pages/Login.js b/oidc-ui/src/pages/Login.js index 09c946686..da8508a19 100644 --- a/oidc-ui/src/pages/Login.js +++ b/oidc-ui/src/pages/Login.js @@ -1,7 +1,7 @@ import React, { useEffect, useState } from "react"; import Otp from "../components/Otp"; import Pin from "../components/Pin"; -import { otpFields, pinFields, bioLoginFields } from "../constants/formFields"; +import { otpFields, pinFields, bioLoginFields, passwordFields } from "../constants/formFields"; import L1Biometrics from "../components/L1Biometrics"; import { useTranslation } from "react-i18next"; import authService from "../services/authService"; @@ -19,12 +19,14 @@ import { useLocation, useSearchParams } from "react-router-dom"; import { Buffer } from "buffer"; import openIDConnectService from "../services/openIDConnectService"; import DefaultError from "../components/DefaultError"; +import Password from "../components/Password"; //authFactorComponentMapping const comp = { PIN: Pin, OTP: Otp, BIO: L1Biometrics, + PWD: Password }; function InitiateL1Biometrics(openIDConnectService) { @@ -45,6 +47,14 @@ function InitiatePin(openIDConnectService) { }); } +function InitiatePassword(openIDConnectService) { + return React.createElement(Password, { + param: passwordFields, + authService: new authService(openIDConnectService), + openIDConnectService: openIDConnectService, + }); +} + function InitiateOtp(openIDConnectService) { return React.createElement(Otp, { param: otpFields, @@ -90,6 +100,10 @@ function createDynamicLoginElements(inst, oidcService) { return InitiateL1Biometrics(oidcService); } + if (comp[inst] === Password) { + return InitiatePassword(oidcService); + } + return React.createElement(comp[inst]); } @@ -150,7 +164,7 @@ export default function LoginPage({ i18nKeyPrefix = "header" }) { const loadComponent = () => { setAppDownloadURI( oidcService.getEsignetConfiguration(configurationKeys.appDownloadURI) ?? - process.env.REACT_APP_QRCODE_APP_DOWNLOAD_URI + process.env.REACT_APP_QRCODE_APP_DOWNLOAD_URI ); let oAuthDetailResponse = oidcService.getOAuthDetails(); From 2d341feeacf2c2097ecc48e502b5d5df7b4d3030 Mon Sep 17 00:00:00 2001 From: KONIJETI YASWANTHA NAGARJUNA <50859121+YaswanthNagarjuna@users.noreply.github.com> Date: Wed, 10 May 2023 19:25:58 +0530 Subject: [PATCH 08/61] ES-50 Login with Password is added --- oidc-ui/.env | 4 +++- oidc-ui/src/components/Password.js | 8 +++++++- oidc-ui/src/constants/clientConstants.js | 1 + 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/oidc-ui/.env b/oidc-ui/.env index a5ec6831c..fe7a1c1cf 100644 --- a/oidc-ui/.env +++ b/oidc-ui/.env @@ -36,4 +36,6 @@ REACT_APP_CAPTCHA_SITE_KEY="6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI" REACT_APP_AUTH_TXN_ID_LENGTH=10 -REACT_APP_OTP_LENGTH=6 \ No newline at end of file +REACT_APP_OTP_LENGTH=6 + +REACT_APP_PASSWORD_REGEX="/[0-9a-zA-Z]{8,}$/" \ No newline at end of file diff --git a/oidc-ui/src/components/Password.js b/oidc-ui/src/components/Password.js index db5028c4e..e861b3060 100644 --- a/oidc-ui/src/components/Password.js +++ b/oidc-ui/src/components/Password.js @@ -7,6 +7,7 @@ import { buttonTypes, challengeFormats, challengeTypes, + configurationKeys, } from "../constants/clientConstants"; import { passwordFields } from "../constants/formFields"; import { LoadingStates as states } from "../constants/states"; @@ -33,6 +34,12 @@ export default function Password({ const [error, setError] = useState(null); const [status, setStatus] = useState(states.LOADED); + const passwordRegexValue = + openIDConnectService.getEsignetConfiguration(configurationKeys.passwordRegex) ?? + process.env.REACT_APP_PASSWORD_REGEX; + + const passwordRegex = new RegExp(passwordRegexValue) + const navigate = useNavigate(); const handleChange = (e) => { @@ -54,7 +61,6 @@ export default function Password({ let challenge = loginState["Password_password"]; let challengeFormat = challengeFormats.pwd; - const passwordRegex = /[0-9a-zA-Z]{8,}$/; if (!passwordRegex.test(challenge)) { setError({ defaultMsg: t("password_error_msg") diff --git a/oidc-ui/src/constants/clientConstants.js b/oidc-ui/src/constants/clientConstants.js index ed41a1f84..48e7342fd 100644 --- a/oidc-ui/src/constants/clientConstants.js +++ b/oidc-ui/src/constants/clientConstants.js @@ -71,6 +71,7 @@ const configurationKeys = { signInWithQRCodeEnable: "mosip.esignet.qr-code.enable", authTxnIdLength: "auth.txnid.length", otpLength: "otp.length", + passwordRegex : "mosip.esignet.password.regex" }; export { From 412661252377c0435d4400a6668a8e8c246ad324 Mon Sep 17 00:00:00 2001 From: KONIJETI YASWANTHA NAGARJUNA <50859121+YaswanthNagarjuna@users.noreply.github.com> Date: Tue, 16 May 2023 12:06:01 +0530 Subject: [PATCH 09/61] MultiLang for error message corrected --- oidc-ui/.env | 2 +- oidc-ui/public/locales/ar.json | 4 ++-- oidc-ui/public/locales/en.json | 4 ++-- oidc-ui/src/components/Password.js | 3 ++- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/oidc-ui/.env b/oidc-ui/.env index fe7a1c1cf..ac2154bbc 100644 --- a/oidc-ui/.env +++ b/oidc-ui/.env @@ -38,4 +38,4 @@ REACT_APP_AUTH_TXN_ID_LENGTH=10 REACT_APP_OTP_LENGTH=6 -REACT_APP_PASSWORD_REGEX="/[0-9a-zA-Z]{8,}$/" \ No newline at end of file +REACT_APP_PASSWORD_REGEX="" \ No newline at end of file diff --git a/oidc-ui/public/locales/ar.json b/oidc-ui/public/locales/ar.json index 82e651a93..7f169f4ed 100644 --- a/oidc-ui/public/locales/ar.json +++ b/oidc-ui/public/locales/ar.json @@ -67,8 +67,7 @@ "uin_label_text": "أدخل VID الخاص بك", "password_label_text": "أدخل كلمة المرور", "uin_placeholder": "VID", - "password_placeholder": "كلمة المرور", - "password_error_msg": "رمز مرور خاطئ" + "password_placeholder": "كلمة المرور" }, "LoginQRCode": { "sign_in_with_inji": "تسجيل الدخول باستخدام Inji", @@ -243,6 +242,7 @@ "invalid_version": "نسخة غير صالحة", "invalid_value": "قيمة غير صالحة", "duplicate_individual_id": "المعرف الفردي موجود بالفعل.", + "password_error_msg": "رمز مرور خاطئ", "0": "النجاح", "100": "الجهاز غير مسجل", "101": "غير قادر على الكشف عن كائن القياسات الحيوية", diff --git a/oidc-ui/public/locales/en.json b/oidc-ui/public/locales/en.json index 29195cfe5..a210b6c2e 100644 --- a/oidc-ui/public/locales/en.json +++ b/oidc-ui/public/locales/en.json @@ -67,8 +67,7 @@ "uin_label_text": "Enter your VID", "password_label_text": "Enter Password", "uin_placeholder": "VID", - "password_placeholder": "Password", - "password_error_msg": "Invalid Password" + "password_placeholder": "Password" }, "LoginQRCode": { "sign_in_with_inji": "Login with Inji", @@ -243,6 +242,7 @@ "invalid_version": "Invalid version", "invalid_value": "Invalid value", "duplicate_individual_id": "Individual ID already exists.", + "password_error_msg": "Invalid Password", "0": "Success", "100": "Device Not Registered", "101": "Unable to Detect a Biometrics", diff --git a/oidc-ui/src/components/Password.js b/oidc-ui/src/components/Password.js index e861b3060..90bfc3d0c 100644 --- a/oidc-ui/src/components/Password.js +++ b/oidc-ui/src/components/Password.js @@ -63,7 +63,8 @@ export default function Password({ if (!passwordRegex.test(challenge)) { setError({ - defaultMsg: t("password_error_msg") + defaultMsg: "Password Invalid", + errorCode:"password_error_msg" }); return; } From e1e335c9120359c42da6b13a7a682977bd7510a0 Mon Sep 17 00:00:00 2001 From: KONIJETI YASWANTHA NAGARJUNA <50859121+YaswanthNagarjuna@users.noreply.github.com> Date: Tue, 16 May 2023 12:57:19 +0530 Subject: [PATCH 10/61] Scan image from password filed is removed --- oidc-ui/src/components/InputWithImage.js | 8 +++++--- oidc-ui/src/components/Password.js | 7 ++++--- oidc-ui/src/constants/clientConstants.js | 2 +- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/oidc-ui/src/components/InputWithImage.js b/oidc-ui/src/components/InputWithImage.js index 627825f95..6574a197d 100644 --- a/oidc-ui/src/components/InputWithImage.js +++ b/oidc-ui/src/components/InputWithImage.js @@ -41,9 +41,11 @@ export default function InputWithImage({ )}
-
- -
+ {imgPath && +
+ +
+ } + imgPath={ + field.type === "password" ? null : "images/photo_scan.png" + } />
))} diff --git a/oidc-ui/src/constants/clientConstants.js b/oidc-ui/src/constants/clientConstants.js index 48e7342fd..fa93a626b 100644 --- a/oidc-ui/src/constants/clientConstants.js +++ b/oidc-ui/src/constants/clientConstants.js @@ -71,7 +71,7 @@ const configurationKeys = { signInWithQRCodeEnable: "mosip.esignet.qr-code.enable", authTxnIdLength: "auth.txnid.length", otpLength: "otp.length", - passwordRegex : "mosip.esignet.password.regex" + passwordRegex : "password.regex" }; export { From a026e68a222a76874f0df4ef2c4099be9152848f Mon Sep 17 00:00:00 2001 From: Akila Lakshmanan <77330852+akilalakshmanan@users.noreply.github.com> Date: Wed, 17 May 2023 18:31:36 +0530 Subject: [PATCH 11/61] [MOSIP-25835] Added script to generate esignet misp partner license key (#180) * [MOSIP-25835] Added script to generate esignet misp partner license key * [MOSIP-25835] Updated secret name to onboarder-keys * [MOSIP-25835] Updated chart version * Delete misp_key.sh * Removed redundant misk key.sh script --------- Co-authored-by: akilalakshmanan --- helm/esignet/install.sh | 16 ++++++++++++++ helm/esignet/misp_key.sh | 47 ++++++++++++++++++++++++++++++++++++++++ helm/install-all.sh | 10 +++++++++ 3 files changed, 73 insertions(+) create mode 100644 helm/esignet/misp_key.sh diff --git a/helm/esignet/install.sh b/helm/esignet/install.sh index c7feb810a..64e584ff5 100755 --- a/helm/esignet/install.sh +++ b/helm/esignet/install.sh @@ -9,11 +9,27 @@ fi NS=esignet CHART_VERSION=1.0.1 +kubectl create ns $NS + +helm repo update + ./keycloak-init.sh echo Copy configmaps ./copy_cm.sh +MISPKEY=$(bash misp_key.sh) +echo "MISP License key is: $MISPKEY" + +echo Setting up onboarder-keys secrets +kubectl -n $NS create secret generic onboarder-keys --from-literal=mosip-esignet-misp-key=$MISPKEY --dry-run=client -o yaml | kubectl apply -f - + +./copy_cm_func.sh secret onboarder-keys esignet config-server + +kubectl -n config-server set env --keys=mosip-esignet-misp-key --from secret/onboarder-keys deployment/config-server --prefix=SPRING_CLOUD_CONFIG_SERVER_OVERRIDES_ + +kubectl -n config-server get deploy -o name | xargs -n1 -t kubectl -n config-server rollout status + echo Installing esignet helm -n $NS install esignet mosip/esignet --version $CHART_VERSION diff --git a/helm/esignet/misp_key.sh b/helm/esignet/misp_key.sh new file mode 100644 index 000000000..5cae10fa7 --- /dev/null +++ b/helm/esignet/misp_key.sh @@ -0,0 +1,47 @@ +#!/usr/bin/env bash + +#get date +date=$(date --utc +%FT%T.%3NZ) +AUTHMANAGER_URL="https://$(kubectl get configmap global -o json | jq -r '.data."mosip-api-internal-host"')" +KEYCLOAK_CLIENT_ID=mosip-pms-client +KEYCLOAK_CLIENT_SECRET="$(kubectl get secret keycloak-client-secrets -n keycloak -o json | jq -r '.data."mosip_pms_client_secret"' | base64 --decode)" +AUTH_APP_ID=partner +MISP_PARTNER_ID=mpartner-default-esignet + + +#echo -e "\n Generating misp license Keys \n"; +#echo "AUTHMANAGER URL : $AUTHMANAGER_URL" +#echo "$MISP_PARTNER_ID" +#echo "* Request for authorization" +curl -s -D - -o /dev/null -X "POST" \ + "$AUTHMANAGER_URL/v1/authmanager/authenticate/clientidsecretkey" \ + -H "accept: */*" \ + -H "Content-Type: application/json" \ + -d '{ + "id": "string", + "version": "string", + "requesttime": "'$date'", + "metadata": {}, + "request": { + "clientId": "'$KEYCLOAK_CLIENT_ID'", + "secretKey": "'$KEYCLOAK_CLIENT_SECRET'", + "appId": "'$AUTH_APP_ID'" + } +}' > temp.txt 2>&1 & + +sleep 10 +TOKEN=$( cat temp.txt | awk '/[aA]uthorization:/{print $2}' | sed -z 's/\n//g' | sed -z 's/\r//g') + +if [[ -z $TOKEN ]]; then + echo "Unable to Authenticate with authmanager. \"TOKEN\" is empty; EXITING"; + exit 1; +fi + +#echo -e "\nGot Authorization token from authmanager" + +curl -X "GET" \ + -H "Accept: application/json" \ + --cookie "Authorization=$TOKEN" \ + "$AUTHMANAGER_URL/v1/partnermanager/misps/$MISP_PARTNER_ID/licenseKey" > result.txt + +cat result.txt | jq -r '.response.licenseKey' \ No newline at end of file diff --git a/helm/install-all.sh b/helm/install-all.sh index db1cf0627..fd488240d 100755 --- a/helm/install-all.sh +++ b/helm/install-all.sh @@ -24,14 +24,24 @@ echo Installing Softhsm for esignet helm -n $SOFTHSM_NS install softhsm-esignet mosip/softhsm -f softhsm-values.yaml --version $SOFTHSM_CHART_VERSION --wait echo Installed Softhsm for esignet +cd esignet +MISPKEY=$(bash misp_key.sh) +echo "MISP License key is: $MISPKEY" + +echo Setting up onboarder-keys secrets +kubectl -n $NS create secret generic onboarder-keys --from-literal=mosip-esignet-misp-key=$MISPKEY --dry-run=client -o yaml | kubectl apply -f - +cd .. + echo Copy configmaps ./copy_cm_func.sh configmap global default config-server echo Copy secrets ./copy_cm_func.sh secret softhsm-esignet softhsm config-server +./copy_cm_func.sh secret onboarder-keys esignet config-server kubectl -n config-server set env --keys=mosip-esignet-host --from configmap/global deployment/config-server --prefix=SPRING_CLOUD_CONFIG_SERVER_OVERRIDES_ kubectl -n config-server set env --keys=security-pin --from secret/softhsm-esignet deployment/config-server --prefix=SPRING_CLOUD_CONFIG_SERVER_OVERRIDES_SOFTHSM_ESIGNET_ +kubectl -n config-server set env --keys=mosip-esignet-misp-key --from secret/onboarder-keys deployment/config-server --prefix=SPRING_CLOUD_CONFIG_SERVER_OVERRIDES_ kubectl -n config-server get deploy -o name | xargs -n1 -t kubectl -n config-server rollout status From 41560b5076d2521ccb0e2fc2bd058335caea6544 Mon Sep 17 00:00:00 2001 From: Hitesh C Date: Fri, 19 May 2023 17:40:46 +0530 Subject: [PATCH 12/61] [ES-34] (#209) * ES-34 Bug fix for incorrect validation of accepted claims the following checks are performed for claims accepted Claims should be subset of requested claims essential Claims should be a subset of accepted claims Additional tests to validate the flow added * [CHORES] code cleanup * [ADDED] additional test cases --- .../services/AuthorizationHelperService.java | 36 ++++++-- .../AuthorizationHelperServiceTest.java | 82 +++++++++++++++++++ 2 files changed, 110 insertions(+), 8 deletions(-) diff --git a/oidc-service-impl/src/main/java/io/mosip/esignet/services/AuthorizationHelperService.java b/oidc-service-impl/src/main/java/io/mosip/esignet/services/AuthorizationHelperService.java index 9e14e7c5d..74993b7c9 100644 --- a/oidc-service-impl/src/main/java/io/mosip/esignet/services/AuthorizationHelperService.java +++ b/oidc-service-impl/src/main/java/io/mosip/esignet/services/AuthorizationHelperService.java @@ -189,18 +189,38 @@ protected KycAuthResult delegateAuthenticateRequest(String transactionId, String return kycAuthResult; } + /** + * This method is used to validate the requested claims against the accepted claims + *
    + *
  • Checks Performed
  • + *
      + *
    • accepted Claims should be subset of requested claims
    • + *
    • essential Claims should be a subset of accepted claims
    • + *
    + *
+ * + * @param transaction object containg OIDC transaction details + * @param acceptedClaims list of accepted claims + * @throws EsignetException + * + */ protected void validateAcceptedClaims(OIDCTransaction transaction, List acceptedClaims) throws EsignetException { - if(CollectionUtils.isEmpty(acceptedClaims)) - return; + Map userinfo = Optional.ofNullable(transaction.getRequestedClaims()) + .map(Claims::getUserinfo) + .orElse(Collections.emptyMap()); - if(CollectionUtils.isEmpty(transaction.getRequestedClaims().getUserinfo())) - throw new EsignetException(INVALID_ACCEPTED_CLAIM); + List essentialClaims = userinfo.entrySet().stream() + .filter(e -> Optional.ofNullable(e.getValue()).map(ClaimDetail::isEssential).orElse(false)) + .map(Map.Entry::getKey) + .collect(Collectors.toList()); - if(acceptedClaims.stream() - .allMatch( claim -> transaction.getRequestedClaims().getUserinfo().containsKey(claim) )) - return; + Set allRequestedClaims = userinfo.keySet(); + Set acceptedClaimsSet = new HashSet<>(Optional.ofNullable(acceptedClaims).orElse(Collections.emptyList())); - throw new EsignetException(INVALID_ACCEPTED_CLAIM); + if (essentialClaims.stream().anyMatch(c -> !acceptedClaimsSet.contains(c)) + || !allRequestedClaims.containsAll(acceptedClaimsSet)) { + throw new EsignetException(INVALID_ACCEPTED_CLAIM); + } } protected void validateAuthorizeScopes(OIDCTransaction transaction, List authorizeScopes) throws EsignetException { diff --git a/oidc-service-impl/src/test/java/io/mosip/esignet/services/AuthorizationHelperServiceTest.java b/oidc-service-impl/src/test/java/io/mosip/esignet/services/AuthorizationHelperServiceTest.java index f73e1d20c..0786a3a7d 100644 --- a/oidc-service-impl/src/test/java/io/mosip/esignet/services/AuthorizationHelperServiceTest.java +++ b/oidc-service-impl/src/test/java/io/mosip/esignet/services/AuthorizationHelperServiceTest.java @@ -250,6 +250,18 @@ public void validateAcceptedClaims_withEmptyAcceptedClaims_thenPass() { authorizationHelperService.validateAcceptedClaims(new OIDCTransaction(), new ArrayList<>()); } + @Test + public void validateAcceptedClaims_withNullRequestedClaims_thenFail() { + + try { + authorizationHelperService.validateAcceptedClaims( + new OIDCTransaction(), Arrays.asList("name", "gender") + ); + Assert.fail(); + } catch (EsignetException e) { + Assert.assertEquals(INVALID_ACCEPTED_CLAIM, e.getErrorCode()); + } + } @Test public void validateAcceptedClaims_withEmptyRequestedClaims_thenFail() { Claims resolvedClaims = new Claims(); @@ -284,6 +296,76 @@ public void validateAcceptedClaims_withInvalidAcceptedClaims_thenFail() { } } + @Test + public void validateAcceptedClaims_withValidAcceptedEssentialClaims_thenPass() { + Claims resolvedClaims = new Claims(); + resolvedClaims.setUserinfo(new HashMap<>()); + Map userinfoClaims = new HashMap<>(); + userinfoClaims.put("name", new ClaimDetail(null, null, true)); + userinfoClaims.put("birthdate", new ClaimDetail(null, null, true)); + userinfoClaims.put("address", new ClaimDetail(null, null, false)); + userinfoClaims.put("gender", null); + resolvedClaims.setUserinfo(userinfoClaims); + OIDCTransaction oidcTransaction = new OIDCTransaction(); + oidcTransaction.setRequestedClaims(resolvedClaims); + authorizationHelperService.validateAcceptedClaims(oidcTransaction, Arrays.asList("name", "birthdate")); + } + + @Test + public void validateAcceptedClaims_withAllOptionalClaimsNotAccepted_thenPass() { + Claims resolvedClaims = new Claims(); + resolvedClaims.setUserinfo(new HashMap<>()); + Map userinfoClaims = new HashMap<>(); + userinfoClaims.put("name", new ClaimDetail(null, null, false)); + userinfoClaims.put("birthdate", new ClaimDetail(null, null, false)); + userinfoClaims.put("address", new ClaimDetail(null, null, false)); + userinfoClaims.put("gender", null); + resolvedClaims.setUserinfo(userinfoClaims); + OIDCTransaction oidcTransaction = new OIDCTransaction(); + oidcTransaction.setRequestedClaims(resolvedClaims); + authorizationHelperService.validateAcceptedClaims(oidcTransaction, List.of()); + } + + @Test + public void validateAcceptedClaims_withSomeValidAcceptedEssentialClaims_thenFail() { + Claims resolvedClaims = new Claims(); + resolvedClaims.setUserinfo(new HashMap<>()); + Map userinfoClaims = new HashMap<>(); + userinfoClaims.put("name", new ClaimDetail(null, null, true)); + userinfoClaims.put("birthdate", new ClaimDetail(null, null, true)); + userinfoClaims.put("address", new ClaimDetail(null, null, false)); + userinfoClaims.put("gender", null); + resolvedClaims.setUserinfo(userinfoClaims); + OIDCTransaction oidcTransaction = new OIDCTransaction(); + oidcTransaction.setRequestedClaims(resolvedClaims); + try { + authorizationHelperService.validateAcceptedClaims(oidcTransaction, Arrays.asList("name", "address")); + Assert.fail(); + } catch (EsignetException e) { + Assert.assertEquals(INVALID_ACCEPTED_CLAIM, e.getErrorCode()); + } + } + + @Test + public void validateAcceptedClaims_withAllOptionalClaims_thenFail() { + Claims resolvedClaims = new Claims(); + resolvedClaims.setUserinfo(new HashMap<>()); + Map userinfoClaims = new HashMap<>(); + userinfoClaims.put("name", new ClaimDetail(null, null, false)); + userinfoClaims.put("birthdate", new ClaimDetail(null, null, false)); + userinfoClaims.put("address", new ClaimDetail(null, null, false)); + userinfoClaims.put("gender", null); + resolvedClaims.setUserinfo(userinfoClaims); + OIDCTransaction oidcTransaction = new OIDCTransaction(); + oidcTransaction.setRequestedClaims(resolvedClaims); + try { + authorizationHelperService.validateAcceptedClaims(oidcTransaction, Arrays.asList("email", "phone_number")); + Assert.fail(); + } catch (EsignetException e) { + Assert.assertEquals(INVALID_ACCEPTED_CLAIM, e.getErrorCode()); + } + } + @Test public void validateAuthorizeScopes_withEmptyAcceptedScopes_thenPass() { OIDCTransaction oidcTransaction = new OIDCTransaction(); From bc359a0c5d0a9d3b875f726fe78792fd718cc0af Mon Sep 17 00:00:00 2001 From: syed salman <72004356+syedsalman3753@users.noreply.github.com> Date: Tue, 30 May 2023 19:37:41 +0530 Subject: [PATCH 13/61] [MOSIP-27593] Added initContainers to download & add self-signed ssl certs to the pods (#210) * [MOSIP-24332] updated install.sh * [MOSIP-27593] Added initContainers to download & add self-signed ssl to pods * [MOSIP-27593] Updated README.md * [MOSIP-27593] Updated install.sh & README.md * [MOSIP-27593] Updated esignet helm chart * [MOSIP-27593] Updated README.md --------- Signed-off-by: syed salman <72004356+syedsalman3753@users.noreply.github.com> Co-authored-by: syed-salman-technoforte --- README.md | 4 +++ helm/esignet/install.sh | 16 +++++++++++- helm/esignet/templates/deployment.yaml | 13 +++++++++- helm/esignet/values.yaml | 35 +++++++++++++++++++++++++- helm/install-all.sh | 1 + partner-onboarder/install.sh | 5 ++-- 6 files changed, 69 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 82b326e17..7a06b323f 100644 --- a/README.md +++ b/README.md @@ -62,6 +62,10 @@ The project requires JDK 11. cd helm ./install-all.sh ``` +* During the execution of the `install-all.sh` script, a prompt appears requesting information regarding the presence of a public domain and a valid SSL certificate on the server. +* If the server lacks a public domain and a valid SSL certificate, it is advisable to select the `n` option. Opting it will enable the `init-container` with an `emptyDir` volume and include it in the deployment process. +* The init-container will proceed to download the server's self-signed SSL certificate and mount it to the specified location within the container's Java keystore (i.e., `cacerts`) file. +* This particular functionality caters to scenarios where the script needs to be employed on a server utilizing self-signed SSL certificates. ### Delete * Run `delete-all.sh` to remove esignet services. diff --git a/helm/esignet/install.sh b/helm/esignet/install.sh index 64e584ff5..2bfab4af6 100755 --- a/helm/esignet/install.sh +++ b/helm/esignet/install.sh @@ -18,6 +18,20 @@ helm repo update echo Copy configmaps ./copy_cm.sh +echo "Do you have public domain & valid SSL? (Y/n) " +echo "Y: if you have public domain & valid ssl certificate" +echo "n: If you don't have a public domain and a valid SSL certificate. Note: It is recommended to use this option only in development environments." +read -p "" flag + +if [ -z "$flag" ]; then + echo "'flag' was provided; EXITING;" + exit 1; +fi +ENABLE_INSECURE='' +if [ "$flag" = "n" ]; then + ENABLE_INSECURE='--set enable_insecure=true'; +fi + MISPKEY=$(bash misp_key.sh) echo "MISP License key is: $MISPKEY" @@ -31,7 +45,7 @@ kubectl -n config-server set env --keys=mosip-esignet-misp-key --from secret/onb kubectl -n config-server get deploy -o name | xargs -n1 -t kubectl -n config-server rollout status echo Installing esignet -helm -n $NS install esignet mosip/esignet --version $CHART_VERSION +helm -n $NS install esignet mosip/esignet --version $CHART_VERSION $ENABLE_INSECURE kubectl -n $NS get deploy -o name | xargs -n1 -t kubectl -n $NS rollout status diff --git a/helm/esignet/templates/deployment.yaml b/helm/esignet/templates/deployment.yaml index 9fef2a1c9..ca588c994 100644 --- a/helm/esignet/templates/deployment.yaml +++ b/helm/esignet/templates/deployment.yaml @@ -70,7 +70,7 @@ spec: - name: foo mountPath: bar {{- end }} - {{- if .Values.initContainers }} + {{- if .Values.enable_insecure }} {{- include "common.tplvalues.render" (dict "value" .Values.initContainers "context" $) | nindent 8 }} {{- end }} containers: @@ -130,6 +130,17 @@ spec: {{- else if .Values.customReadinessProbe }} readinessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.customReadinessProbe "context" $) | nindent 12 }} {{- end }} + volumeMounts: + {{- if .Values.enable_insecure }} + - mountPath: /usr/local/openjdk-11/lib/security/cacerts + name: cacerts + subPath: cacerts + {{- end }} {{- if .Values.sidecars }} {{- include "common.tplvalues.render" ( dict "value" .Values.sidecars "context" $) | nindent 8 }} {{- end }} + volumes: + {{- if .Values.enable_insecure }} + - name: cacerts + emptyDir: {} + {{- end }} diff --git a/helm/esignet/values.yaml b/helm/esignet/values.yaml index 7e9d11ffd..29213d153 100644 --- a/helm/esignet/values.yaml +++ b/helm/esignet/values.yaml @@ -272,7 +272,38 @@ extraVolumeMounts: [] ## - name: portname ## containerPort: 1234 ## -initContainers: {} +initContainers: + - command: + - /bin/bash + - -c + - if [ "$ENABLE_INSECURE" = "true" ]; then HOST=$( env | grep "mosip-api-internal-host" + |sed "s/mosip-api-internal-host=//g"); if [ -z "$HOST" ]; then echo "HOST + $HOST is empty; EXITING"; exit 1; fi; openssl s_client -servername "$HOST" + -connect "$HOST":443 > "$HOST.cer" 2>/dev/null & sleep 2 ; sed -i -ne '/-BEGIN + CERTIFICATE-/,/-END CERTIFICATE-/p' "$HOST.cer"; cat "$HOST.cer"; /usr/local/openjdk-11/bin/keytool + -delete -alias "$HOST" -keystore $JAVA_HOME/lib/security/cacerts -storepass + changeit; /usr/local/openjdk-11/bin/keytool -trustcacerts -keystore "$JAVA_HOME/lib/security/cacerts" + -storepass changeit -noprompt -importcert -alias "$HOST" -file "$HOST.cer" + ; if [ $? -gt 0 ]; then echo "Failed to add SSL certificate for host $host; + EXITING"; exit 1; fi; cp /usr/local/openjdk-11/lib/security/cacerts /cacerts; + fi + env: + - name: ENABLE_INSECURE + value: "true" + envFrom: + - configMapRef: + name: global + image: docker.io/openjdk:11-jre + imagePullPolicy: Always + name: cacerts + resources: {} + securityContext: + runAsUser: 0 + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: File + volumeMounts: + - mountPath: /cacerts + name: cacerts ## Add sidecars to the pods. ## Example: @@ -421,3 +452,5 @@ istio: - istio-system/public - istio-system/internal prefix: /v1/esignet/ + +enable_insecure: false diff --git a/helm/install-all.sh b/helm/install-all.sh index fd488240d..6d5a6fe3f 100755 --- a/helm/install-all.sh +++ b/helm/install-all.sh @@ -42,6 +42,7 @@ echo Copy secrets kubectl -n config-server set env --keys=mosip-esignet-host --from configmap/global deployment/config-server --prefix=SPRING_CLOUD_CONFIG_SERVER_OVERRIDES_ kubectl -n config-server set env --keys=security-pin --from secret/softhsm-esignet deployment/config-server --prefix=SPRING_CLOUD_CONFIG_SERVER_OVERRIDES_SOFTHSM_ESIGNET_ kubectl -n config-server set env --keys=mosip-esignet-misp-key --from secret/onboarder-keys deployment/config-server --prefix=SPRING_CLOUD_CONFIG_SERVER_OVERRIDES_ +kubectl -n config-server rollout restart deploy config-server kubectl -n config-server get deploy -o name | xargs -n1 -t kubectl -n config-server rollout status diff --git a/partner-onboarder/install.sh b/partner-onboarder/install.sh index ae22f1174..62d44488f 100755 --- a/partner-onboarder/install.sh +++ b/partner-onboarder/install.sh @@ -8,7 +8,7 @@ fi echo "Do you have public domain & valid SSL? (Y/n) " echo "Y: if you have public domain & valid ssl certificate" -echo "n: if you don't have public domain & valid ssl certificate" +echo "n: If you don't have a public domain and a valid SSL certificate. Note: It is recommended to use this option only in development environments." read -p "" flag if [ -z "$flag" ]; then @@ -17,7 +17,7 @@ if [ -z "$flag" ]; then fi ENABLE_INSECURE='' if [ "$flag" = "n" ]; then - ENABLE_INSECURE='--set onboarding.enableInsecure=true'; + ENABLE_INSECURE='--set onboarding.configmaps.onboarding.ENABLE_INSECURE=true'; fi NS=esignet @@ -38,6 +38,7 @@ function installing_onboarder() { kubectl -n $NS --ignore-not-found=true delete cm s3 sed -i 's/\r$//' copy_cm.sh ./copy_cm.sh + kubectl -n $NS delete cm --ignore-not-found=true onboarding echo Copy secrets sed -i 's/\r$//' copy_secrets.sh From 50371b9449244ca2faa0843e5e63b8ae2fb65263 Mon Sep 17 00:00:00 2001 From: Akila Lakshmanan <77330852+akilalakshmanan@users.noreply.github.com> Date: Wed, 7 Jun 2023 09:15:08 +0530 Subject: [PATCH 14/61] [MOSIP-25835] Updated Readme file for adding misp partner license key (#222) * [MOSIP-25835] Updated Readme file for adding misp partner license key module * [MOSIP-25835] Updated Readme file * [MOSIP-25835] Updated Readme file * [MOSIP-25835] Moved esignet misp license key automation script to esignet partner-onboarder * [MOSIP-25835] Removed the check condition to add misp key * [MOSIP-25835] Updated print statements --------- Co-authored-by: akilalakshmanan --- helm/esignet/README.md | 1 + helm/esignet/install.sh | 12 ------------ helm/install-all.sh | 10 ---------- partner-onboarder/README.md | 6 ++++++ partner-onboarder/install.sh | 15 +++++++++++++++ {helm/esignet => partner-onboarder}/misp_key.sh | 0 6 files changed, 22 insertions(+), 22 deletions(-) rename {helm/esignet => partner-onboarder}/misp_key.sh (100%) diff --git a/helm/esignet/README.md b/helm/esignet/README.md index 7c5e2871c..4c232ac38 100644 --- a/helm/esignet/README.md +++ b/helm/esignet/README.md @@ -33,6 +33,7 @@ Refer [Commons](https://docs.mosip.io/1.2.0/modules/commons). ``` ./install.sh ``` + ## Uninstall ``` ./delete.sh diff --git a/helm/esignet/install.sh b/helm/esignet/install.sh index 2bfab4af6..b8229b6e2 100755 --- a/helm/esignet/install.sh +++ b/helm/esignet/install.sh @@ -32,18 +32,6 @@ if [ "$flag" = "n" ]; then ENABLE_INSECURE='--set enable_insecure=true'; fi -MISPKEY=$(bash misp_key.sh) -echo "MISP License key is: $MISPKEY" - -echo Setting up onboarder-keys secrets -kubectl -n $NS create secret generic onboarder-keys --from-literal=mosip-esignet-misp-key=$MISPKEY --dry-run=client -o yaml | kubectl apply -f - - -./copy_cm_func.sh secret onboarder-keys esignet config-server - -kubectl -n config-server set env --keys=mosip-esignet-misp-key --from secret/onboarder-keys deployment/config-server --prefix=SPRING_CLOUD_CONFIG_SERVER_OVERRIDES_ - -kubectl -n config-server get deploy -o name | xargs -n1 -t kubectl -n config-server rollout status - echo Installing esignet helm -n $NS install esignet mosip/esignet --version $CHART_VERSION $ENABLE_INSECURE diff --git a/helm/install-all.sh b/helm/install-all.sh index 6d5a6fe3f..920bb810c 100755 --- a/helm/install-all.sh +++ b/helm/install-all.sh @@ -24,24 +24,14 @@ echo Installing Softhsm for esignet helm -n $SOFTHSM_NS install softhsm-esignet mosip/softhsm -f softhsm-values.yaml --version $SOFTHSM_CHART_VERSION --wait echo Installed Softhsm for esignet -cd esignet -MISPKEY=$(bash misp_key.sh) -echo "MISP License key is: $MISPKEY" - -echo Setting up onboarder-keys secrets -kubectl -n $NS create secret generic onboarder-keys --from-literal=mosip-esignet-misp-key=$MISPKEY --dry-run=client -o yaml | kubectl apply -f - -cd .. - echo Copy configmaps ./copy_cm_func.sh configmap global default config-server echo Copy secrets ./copy_cm_func.sh secret softhsm-esignet softhsm config-server -./copy_cm_func.sh secret onboarder-keys esignet config-server kubectl -n config-server set env --keys=mosip-esignet-host --from configmap/global deployment/config-server --prefix=SPRING_CLOUD_CONFIG_SERVER_OVERRIDES_ kubectl -n config-server set env --keys=security-pin --from secret/softhsm-esignet deployment/config-server --prefix=SPRING_CLOUD_CONFIG_SERVER_OVERRIDES_SOFTHSM_ESIGNET_ -kubectl -n config-server set env --keys=mosip-esignet-misp-key --from secret/onboarder-keys deployment/config-server --prefix=SPRING_CLOUD_CONFIG_SERVER_OVERRIDES_ kubectl -n config-server rollout restart deploy config-server kubectl -n config-server get deploy -o name | xargs -n1 -t kubectl -n config-server rollout status diff --git a/partner-onboarder/README.md b/partner-onboarder/README.md index bead756eb..6768f5bc7 100644 --- a/partner-onboarder/README.md +++ b/partner-onboarder/README.md @@ -9,6 +9,12 @@ Loads certs for default partners for sandbox. Refer [mosip-onboarding repo](http ``` ./install.sh ``` +## Automating MISP Partner License key for e-Signet module +* Added `misp_key.sh` script through which the MISP license key is obtained with the following endpoint: + `v1/partnermanager/misps/$MISP_PARTNER_ID/licenseKey` +* The above license key is passed through the `config-server` as placeholder named `mosip.esignet.misp.key` in `esignet-default.properties` file and then saved as a secret called `onboarder-keys` in the kubernetes environment. +* This change is a part of the `install.sh` script of partner-onboarder. + # Troubleshootings * After completion of the job, a very detailed `html report` is prepared and stored at https://onboarder.{sandbox_base_url}.mosip.net diff --git a/partner-onboarder/install.sh b/partner-onboarder/install.sh index 62d44488f..974fc017e 100755 --- a/partner-onboarder/install.sh +++ b/partner-onboarder/install.sh @@ -54,6 +54,21 @@ function installing_onboarder() { --version $CHART_VERSION echo Reports are moved to S3 under onboarder bucket + + echo Updating esignet misp license key to secrets + MISPKEY=$(bash misp_key.sh) + echo "MISP License key is: $MISPKEY" + + echo Setting up onboarder-keys secrets + kubectl -n $NS create secret generic onboarder-keys --from-literal=mosip-esignet-misp-key=$MISPKEY --dry-run=client -o yaml | kubectl apply -f - + + ./copy_cm_func.sh secret onboarder-keys esignet config-server + + kubectl -n config-server set env --keys=mosip-esignet-misp-key --from secret/onboarder-keys deployment/config-server --prefix=SPRING_CLOUD_CONFIG_SERVER_OVERRIDES_ + + kubectl -n config-server get deploy -o name | xargs -n1 -t kubectl -n config-server rollout status + echo E-signet MISP License Key successfully updated + return 0 fi } diff --git a/helm/esignet/misp_key.sh b/partner-onboarder/misp_key.sh similarity index 100% rename from helm/esignet/misp_key.sh rename to partner-onboarder/misp_key.sh From 8c65ec26fe857f29939b5c0260b5b70777bddaca Mon Sep 17 00:00:00 2001 From: syed salman <72004356+syedsalman3753@users.noreply.github.com> Date: Wed, 7 Jun 2023 13:04:30 +0530 Subject: [PATCH 15/61] [DSD-2763] Updated onboarder scripts to configure S3 objects (#232) Co-authored-by: syed-salman-technoforte --- partner-onboarder/install.sh | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/partner-onboarder/install.sh b/partner-onboarder/install.sh index 974fc017e..f9012d242 100755 --- a/partner-onboarder/install.sh +++ b/partner-onboarder/install.sh @@ -44,11 +44,35 @@ function installing_onboarder() { sed -i 's/\r$//' copy_secrets.sh ./copy_secrets.sh + read -p "Provide onboarder bucket name : " s3_bucket + if [[ -z $s3_bucket ]]; then + echo "s3_bucket not provided; EXITING;"; + exit 1; + fi + if [[ $s3_bucket == *[' !@#$%^&*()+']* ]]; then + echo "s3_bucket should not contain spaces / any special character; EXITING"; + exit 1; + fi + read -p "Provide onboarder s3 bucket region : " s3_region + if [[ $s3_region == *[' !@#$%^&*()+']* ]]; then + echo "s3_region should not contain spaces / any special character; EXITING"; + exit 1; + fi + + read -p "Provide S3 URL : " s3_url + if [[ -z $s3_url ]]; then + echo "s3_url not provided; EXITING;" + exit 1; + fi + + s3_user_key=$( kubectl -n s3 get cm s3 -o json | jq -r '.data."s3-user-key"' ) + echo Onboarding default partners helm -n $NS install esignet-resident-oidc-partner-onboarder mosip/partner-onboarder \ - --set onboarding.configmaps.s3.s3-host='http://minio.minio:9000' \ - --set onboarding.configmaps.s3.s3-user-key='admin' \ - --set onboarding.configmaps.s3.s3-region='' \ + --set onboarding.configmaps.s3.s3-host="$s3_url" \ + --set onboarding.configmaps.s3.s3-user-key="$s3_user_key" \ + --set onboarding.configmaps.s3.s3-region="$s3_region" \ + --set onboarding.configmaps.s3.s3-bucket-name="$s3_bucket" \ $ENABLE_INSECURE \ -f values.yaml \ --version $CHART_VERSION From d76a1763e69f5cb3fa218e125bd50614e6f1f6ef Mon Sep 17 00:00:00 2001 From: KONIJETI YASWANTHA NAGARJUNA <50859121+YaswanthNagarjuna@users.noreply.github.com> Date: Wed, 7 Jun 2023 20:05:39 +0530 Subject: [PATCH 16/61] [MOSIP-27821] id's added for UI elements --- oidc-ui/src/components/Background.js | 4 ++++ oidc-ui/src/components/Consent.js | 1 + oidc-ui/src/components/FormAction.js | 4 ++++ oidc-ui/src/components/L1Biometrics.js | 1 + oidc-ui/src/components/OtpGet.js | 1 + oidc-ui/src/components/OtpVerify.js | 2 ++ oidc-ui/src/components/Password.js | 2 +- oidc-ui/src/components/Pin.js | 2 +- oidc-ui/src/components/SignInOptions.js | 2 +- 9 files changed, 16 insertions(+), 3 deletions(-) diff --git a/oidc-ui/src/components/Background.js b/oidc-ui/src/components/Background.js index 68d9fa80f..0e177870b 100644 --- a/oidc-ui/src/components/Background.js +++ b/oidc-ui/src/components/Background.js @@ -17,9 +17,11 @@ export default function Background({ }) { const tabs = [ { + id:"wallet_tab_id", name: "inji_tab_name", }, { + id:"here_tab_id", name: "here_tab_name", }, ]; @@ -69,6 +71,7 @@ export default function Background({ className="-mb-px flex-auto text-center" >
)} diff --git a/oidc-ui/src/components/FormAction.js b/oidc-ui/src/components/FormAction.js index 7e9df356b..620f8481b 100644 --- a/oidc-ui/src/components/FormAction.js +++ b/oidc-ui/src/components/FormAction.js @@ -5,6 +5,7 @@ export default function FormAction({ type = "Button", //valid values: Button, Submit and Reset text, disabled = false, + id }) { const className = "flex justify-center w-full font-medium rounded-lg text-sm px-5 py-2 text-center border border-2 "; @@ -23,6 +24,7 @@ export default function FormAction({ } onClick={handleClick} disabled={disabled} + id={id} > {text} @@ -39,6 +41,7 @@ export default function FormAction({ } onSubmit={handleClick} disabled={disabled} + id={id} > {text} @@ -71,6 +74,7 @@ export default function FormAction({ } onClick={handleClick} disabled={disabled} + id="cancel" > {text} diff --git a/oidc-ui/src/components/L1Biometrics.js b/oidc-ui/src/components/L1Biometrics.js index ec7316d07..4b2bc9fa1 100644 --- a/oidc-ui/src/components/L1Biometrics.js +++ b/oidc-ui/src/components/L1Biometrics.js @@ -398,6 +398,7 @@ export default function L1Biometrics({ type={buttonTypes.submit} text={t("scan_and_verify")} disabled={!loginState["sbi_mosip-vid"]?.trim()} + id="scan_and_verify" /> diff --git a/oidc-ui/src/components/OtpGet.js b/oidc-ui/src/components/OtpGet.js index 74bef2d16..af9fa415a 100644 --- a/oidc-ui/src/components/OtpGet.js +++ b/oidc-ui/src/components/OtpGet.js @@ -151,6 +151,7 @@ export default function OtpGet({ type={buttonTypes.button} text={t("get_otp")} handleClick={sendOTP} + id="get_otp" disabled={!loginState["Otp_mosip-vid"]?.trim() || (showCaptcha && captchaToken === null)} /> diff --git a/oidc-ui/src/components/OtpVerify.js b/oidc-ui/src/components/OtpVerify.js index b3d4ea55e..4f49f52c1 100644 --- a/oidc-ui/src/components/OtpVerify.js +++ b/oidc-ui/src/components/OtpVerify.js @@ -305,6 +305,7 @@ export default function OtpVerify({ disabled={otpValue.length !== otpLength} type={buttonTypes.submit} text={t("verify")} + id="verify_otp" /> {showTimer && ( @@ -316,6 +317,7 @@ export default function OtpVerify({ type={buttonTypes.button} text={t("resend_otp")} handleClick={handleSendOtp} + id="resend_otp" /> )} diff --git a/oidc-ui/src/components/Password.js b/oidc-ui/src/components/Password.js index e501f4582..66968cd02 100644 --- a/oidc-ui/src/components/Password.js +++ b/oidc-ui/src/components/Password.js @@ -149,7 +149,7 @@ export default function Password({ ))} - + {status === states.LOADING && (
diff --git a/oidc-ui/src/components/Pin.js b/oidc-ui/src/components/Pin.js index 5f9b60880..fd41f46ab 100644 --- a/oidc-ui/src/components/Pin.js +++ b/oidc-ui/src/components/Pin.js @@ -148,7 +148,7 @@ export default function Pin({
- + {status === states.LOADING && (
diff --git a/oidc-ui/src/components/SignInOptions.js b/oidc-ui/src/components/SignInOptions.js index 6e1e55b8b..8da9e6b71 100644 --- a/oidc-ui/src/components/SignInOptions.js +++ b/oidc-ui/src/components/SignInOptions.js @@ -61,7 +61,7 @@ export default function SignInOptions({ {singinOptions.map((option, idx) => (
diff --git a/oidc-ui/src/components/L1Biometrics.js b/oidc-ui/src/components/L1Biometrics.js index 4b2bc9fa1..de0295359 100644 --- a/oidc-ui/src/components/L1Biometrics.js +++ b/oidc-ui/src/components/L1Biometrics.js @@ -383,9 +383,11 @@ export default function L1Biometrics({ {e.text}
)} + id="sbi_dropdown" />
diff --git a/oidc-ui/src/components/OtpVerify.js b/oidc-ui/src/components/OtpVerify.js index 4f49f52c1..47faf63fb 100644 --- a/oidc-ui/src/components/OtpVerify.js +++ b/oidc-ui/src/components/OtpVerify.js @@ -236,7 +236,7 @@ export default function OtpVerify({ ))} -
+
Date: Tue, 13 Jun 2023 11:19:07 +0530 Subject: [PATCH 18/61] [ADDED] master toggle button for consent's scope & claims --- oidc-ui/src/components/Consent.js | 187 ++++++++++++++++++++++-------- 1 file changed, 140 insertions(+), 47 deletions(-) diff --git a/oidc-ui/src/components/Consent.js b/oidc-ui/src/components/Consent.js index 9a78a4454..cd2e239a0 100644 --- a/oidc-ui/src/components/Consent.js +++ b/oidc-ui/src/components/Consent.js @@ -1,5 +1,5 @@ import i18next from "i18next"; -import { useEffect, useState } from "react"; +import { useEffect, useState, useRef } from "react"; import { useTranslation } from "react-i18next"; import { Tooltip as ReactTooltip } from "react-tooltip"; import LoadingIndicator from "../common/LoadingIndicator"; @@ -17,6 +17,7 @@ export default function Consent({ const post_AuthCode = authService.post_AuthCode; + const firstRender = useRef(true); const [status, setStatus] = useState(states.LOADED); const [claims, setClaims] = useState([]); const [scope, setScope] = useState([]); @@ -24,6 +25,15 @@ export default function Consent({ const [clientLogoPath, setClientLogoPath] = useState(""); const [claimsScopes, setClaimsScopes] = useState([]); + const hasAllElement = (mainArray, subArray) => + subArray.every((ele) => mainArray.includes(ele)); + + const union = (mainArray, subArray) => + Array.from(new Set([...mainArray, ...subArray])); + + const difference = (mainArray, subArray) => + mainArray.filter((el) => !subArray.includes(el)); + const handleScopeChange = (e) => { let id = e.target.id; @@ -54,6 +64,68 @@ export default function Consent({ setClaims(resultArray); }; + const selectUnselectAllScopeClaim = (e, claimScope, main = false) => { + if (main) { + if (claimScope.type === "scope") { + setScope( + e.target.checked + ? union(scope, claimScope?.values) + : difference(scope, claimScope?.values) + ); + } else { + setClaims( + e.target.checked + ? union(claims, claimScope?.values) + : difference(claims, claimScope?.values) + ); + } + } else { + if (claimScope.type === "scope") { + handleScopeChange(e); + } else { + handleClaimChange(e); + } + } + }; + + const elementChecked = (id, value) => { + let el = document.getElementById(id); + if (el) { + el.checked = value; + } + }; + + const scopeClaimChanges = () => { + const ids = { + check: { + scope: [], + claim: [], + }, + uncheck: { + scope: [], + claim: [], + }, + }; + claimsScopes.forEach((claimScope) => { + if (!claimScope?.required) { + const data = claimScope.type === "scope" ? scope : claims; + const hasAll = hasAllElement(data, claimScope?.values); + const diff = difference(claimScope?.values, data); + ids.check[claimScope.type] = hasAll + ? [...data, claimScope.label] + : data; + ids.uncheck[claimScope.type] = hasAll + ? diff + : [...diff, claimScope.label]; + } + }); + + ids.check.scope.forEach((_) => elementChecked(_, true)); + ids.uncheck.scope.forEach((_) => elementChecked(_, false)); + ids.check.claim.forEach((_) => elementChecked(_, true)); + ids.uncheck.claim.forEach((_) => elementChecked(_, false)); + }; + useEffect(() => { const initialize = async () => { let oAuthDetails = openIDConnectService.getOAuthDetails(); @@ -89,8 +161,13 @@ export default function Consent({ setClaims(oAuthDetails?.essentialClaims); }; - initialize(); - }, []); + if (firstRender.current) { + firstRender.current = false; + initialize(); + return; + } + scopeClaimChanges(); + }, [scope, claims]); const handleSubmit = (e) => { e.preventDefault(); @@ -172,6 +249,35 @@ export default function Consent({ window.location.replace(redirect_uri + params); }; + const sliderButtonDiv = (item, handleOnchange, main = false) => ( +
+ +
+ ); + return (
@@ -192,21 +298,33 @@ export default function Consent({ (claimScope) => claimScope?.values?.length > 0 && (
-
- {t(claimScope.label)} - - +
+
+
+ {t(claimScope.label)} + + +
+
+
+ {!claimScope?.required && + sliderButtonDiv( + claimScope.label, + (e) => + selectUnselectAllScopeClaim(e, claimScope, true), + true + )} +
@@ -227,35 +345,10 @@ export default function Consent({ {t("required")} )} - {!claimScope?.required && ( -
- -
- )} + {!claimScope?.required && + sliderButtonDiv(item, (e) => + selectUnselectAllScopeClaim(e, claimScope) + )}
From a057d45cb9b33b00681ad5c768383e90f5209fb5 Mon Sep 17 00:00:00 2001 From: anshulv1401 Date: Wed, 14 Jun 2023 16:40:31 +0530 Subject: [PATCH 19/61] Config script updated to deploy of signIn plugin --- oidc-ui/Dockerfile | 2 ++ oidc-ui/configure_start.sh | 25 ++++++++++++++++++++++--- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/oidc-ui/Dockerfile b/oidc-ui/Dockerfile index a35fab3b1..6c5019498 100644 --- a/oidc-ui/Dockerfile +++ b/oidc-ui/Dockerfile @@ -30,6 +30,8 @@ ARG container_user_gid=1001 ENV base_path=/usr/share/nginx/html ENV i18n_path=${base_path}/locales +ENV plugins_path=${base_path}/plugins +ENV plugins_format=iife # can be passed during Docker build as build time environment for artifactory URL ARG artifactory_url diff --git a/oidc-ui/configure_start.sh b/oidc-ui/configure_start.sh index 2d9c1723a..3a440850e 100644 --- a/oidc-ui/configure_start.sh +++ b/oidc-ui/configure_start.sh @@ -3,15 +3,34 @@ #installs the pre-requisites. set -e -echo "Downloading pre-requisites install scripts" +echo "Downloading pre-requisites started." + +#i18n bundle +echo "Downloading i18n bundle files" wget --no-check-certificate --no-cache --no-cookies $artifactory_url_env/artifactory/libs-release-local/i18n/esignet-i18n-bundle.zip -O $i18n_path/esignet-i18n-bundle.zip -echo "unzip pre-requisites.." +echo "unzip i18n bundle files.." chmod 775 $i18n_path/* cd $i18n_path unzip -o esignet-i18n-bundle.zip -echo "unzip pre-requisites completed." +#sign-in-button-plugin +echo "Downloading plugins" +mkdir $plugins_path/temp +wget --no-check-certificate --no-cache --no-cookies $artifactory_url_env/artifactory/libs-release-local/esignet-plugins/sign-in-with-esignet.zip -O $plugins_path/temp/sign-in-button-plugin.zip + +echo "unzip plugins.." +cd $plugins_path/temp +unzip -o sign-in-button-plugin.zip + +#move the required js file +mv $plugins_path/temp/sign-in-with-esignet/$plugins_format/index.js $plugins_path/sign-in-button-plugin.js + +# delete temp folder +cd $plugins_path +rm -r temp + +echo "Pre-requisites download completed." exec "$@" \ No newline at end of file From b41970815f64a97bf2ef7295f73e536e41b6e64c Mon Sep 17 00:00:00 2001 From: Zeeshan Mehboob Date: Wed, 14 Jun 2023 18:09:07 +0530 Subject: [PATCH 20/61] [MODIFIED] master toggle button align with other toggle button --- oidc-ui/src/components/Consent.js | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/oidc-ui/src/components/Consent.js b/oidc-ui/src/components/Consent.js index cd2e239a0..9fc598abb 100644 --- a/oidc-ui/src/components/Consent.js +++ b/oidc-ui/src/components/Consent.js @@ -249,14 +249,11 @@ export default function Consent({ window.location.replace(redirect_uri + params); }; - const sliderButtonDiv = (item, handleOnchange, main = false) => ( + const sliderButtonDiv = (item, handleOnchange) => (
From c30956b99cb57c1d6a7a2a1c4a72db2519a2916b Mon Sep 17 00:00:00 2001 From: Zeeshan Mehboob Date: Thu, 15 Jun 2023 11:13:28 +0530 Subject: [PATCH 21/61] [MODIFIED] integrated secure-biometric-interface-integrator library in esignet oidc-ui --- oidc-ui/package.json | 5 +- oidc-ui/src/components/L1Biometrics.js | 311 ++++++------------------- 2 files changed, 71 insertions(+), 245 deletions(-) diff --git a/oidc-ui/package.json b/oidc-ui/package.json index 7731a8ee2..5d307f69f 100644 --- a/oidc-ui/package.json +++ b/oidc-ui/package.json @@ -5,7 +5,7 @@ "dependencies": { "@emotion/react": "^11.10.4", "@tailwindcss/line-clamp": "^0.4.2", - "axios": "^0.27.2", + "axios": "^1.4.0", "buffer": "^6.0.3", "cra-template": "1.1.3", "crypto-js": "^4.1.1", @@ -13,9 +13,10 @@ "i18next-browser-languagedetector": "^7.0.0", "i18next-http-backend": "^2.0.1", "jose": "^4.9.3", + "secure-biometric-interface-integrator": "^0.1.0", "qrcode": "^1.5.1", "react": "^18.2.0", - "react-dom": "^18.0.0", + "react-dom": "^18.2.0", "react-google-recaptcha": "^2.1.0", "react-i18next": "^11.18.6", "react-pin-input": "^1.3.0", diff --git a/oidc-ui/src/components/L1Biometrics.js b/oidc-ui/src/components/L1Biometrics.js index ec7316d07..47504513a 100644 --- a/oidc-ui/src/components/L1Biometrics.js +++ b/oidc-ui/src/components/L1Biometrics.js @@ -1,51 +1,35 @@ -import React, { useEffect } from "react"; -import { useState } from "react"; +import React, { useEffect, useState, useRef } from "react"; import { useNavigate } from "react-router-dom"; import LoadingIndicator from "../common/LoadingIndicator"; import { - buttonTypes, challengeFormats, challengeTypes, configurationKeys, } from "../constants/clientConstants"; import { LoadingStates as states } from "../constants/states"; import InputWithImage from "./InputWithImage"; -import Select from "react-select"; import ErrorIndicator from "../common/ErrorIndicator"; import { useTranslation } from "react-i18next"; -import FormAction from "./FormAction"; +import { init, propChange } from "secure-biometric-interface-integrator"; let fieldsState = {}; -const host = "http://127.0.0.1"; - -const modalityIconPath = { - Face: "images/Sign in with face.png", - Finger: "images/Sign in with fingerprint.png", - Iris: "images/Sign in with Iris.png", -}; export default function L1Biometrics({ param, authService, - localStorageService, openIDConnectService, - sbiService, i18nKeyPrefix = "l1Biometrics", }) { - const { t } = useTranslation("translation", { keyPrefix: i18nKeyPrefix }); + const { t } = useTranslation("translation", { + keyPrefix: i18nKeyPrefix, + }); - const inputFields = param.inputFields; + const firstRender = useRef(true); + const transactionId = openIDConnectService.getTransactionId(); - const capture_Auth = sbiService.capture_Auth; - const mosipdisc_DiscoverDevicesAsync = - sbiService.mosipdisc_DiscoverDevicesAsync; + const inputFields = param.inputFields; - const post_AuthenticateUser = authService.post_AuthenticateUser; - const buildRedirectParams = authService.buildRedirectParams; - - const { getDeviceInfos } = { - ...localStorageService, - }; + const { post_AuthenticateUser, buildRedirectParams } = authService; inputFields.forEach((field) => (fieldsState["sbi_" + field.id] = "")); const [loginState, setLoginState] = useState(fieldsState); @@ -58,9 +42,6 @@ export default function L1Biometrics({ const navigate = useNavigate(); - const [modalityDevices, setModalityDevices] = useState(null); - const [selectedDevice, setSelectedDevice] = useState(null); - const authTxnIdLengthValue = openIDConnectService.getEsignetConfiguration( configurationKeys.authTxnIdLength @@ -68,91 +49,33 @@ export default function L1Biometrics({ const authTxnIdLength = parseInt(authTxnIdLengthValue); - // handle onChange event of the dropdown - const handleDeviceChange = (device) => { - setSelectedDevice(device); - }; - const handleInputChange = (e) => { setLoginState({ ...loginState, [e.target.id]: e.target.value }); }; - const submitHandler = (e) => { - e.preventDefault(); - startCapture(); - }; - - const startCapture = async () => { + /* authenticate method after removing startCapture + * which have capturing & authenticate as well + */ + const authenticateBiometricResponse = async (biometricResponse) => { setError(null); - - let transactionId = getSBIAuthTransactionId( - openIDConnectService.getTransactionId() - ); - - let vid = loginState["sbi_mosip-vid"]; - - if (selectedDevice === null) { - setError({ - errorCode: "device_not_found_msg", - }); - return; - } - - let biometricResponse = null; - - try { - setStatus({ - state: states.AUTHENTICATING, - msg: "capture_initiated_msg", - msgParam: { - modality: t(selectedDevice.type), - deviceModel: selectedDevice.model, - }, - }); - - biometricResponse = await capture_Auth( - host, - selectedDevice.port, - transactionId, - selectedDevice.specVersion, - selectedDevice.type, - selectedDevice.deviceId - ); - - let { errorCode, defaultMsg } = - validateBiometricResponse(biometricResponse); - - setStatus({ state: states.LOADED, msg: "" }); - - if (errorCode !== null) { + setStatus({ state: states.LOADED, msg: "" }); + const { errorCode } = validateBiometricResponse(biometricResponse); + + const vid = loginState["sbi_mosip-vid"]; + if (errorCode === null) { + try { + await Authenticate( + transactionId, + vid, + openIDConnectService.encodeBase64(biometricResponse["biometrics"]) + ); + } catch (error) { setError({ - prefix: "biometric_capture_failed_msg", - errorCode: errorCode, - defaultMsg: defaultMsg, + prefix: "authentication_failed_msg", + errorCode: error.message, + defaultMsg: error.message, }); - return; } - } catch (error) { - setError({ - prefix: "biometric_capture_failed_msg", - errorCode: error.message, - defaultMsg: error.message, - }); - return; - } - - try { - await Authenticate( - openIDConnectService.getTransactionId(), - vid, - openIDConnectService.encodeBase64(biometricResponse["biometrics"]) - ); - } catch (error) { - setError({ - prefix: "authentication_failed_msg", - errorCode: error.message, - defaultMsg: error.message, - }); } }; @@ -200,15 +123,11 @@ export default function L1Biometrics({ }; const Authenticate = async (transactionId, uin, bioValue) => { - let challengeType = challengeTypes.bio; - let challenge = bioValue; - let challengeFormat = challengeFormats.bio; - - let challengeList = [ + const challengeList = [ { - authFactorType: challengeType, - challenge: challenge, - format: challengeFormat, + authFactorType: challengeTypes.bio, + challenge: bioValue, + format: challengeFormats.bio, }, ]; @@ -234,12 +153,9 @@ export default function L1Biometrics({ defaultMsg: errors[0].errorMessage, }); } else { - let nonce = openIDConnectService.getNonce(); - let state = openIDConnectService.getState(); - - let params = buildRedirectParams( - nonce, - state, + const params = buildRedirectParams( + openIDConnectService.getNonce(), + openIDConnectService.getState(), openIDConnectService.getOAuthDetails() ); @@ -249,81 +165,43 @@ export default function L1Biometrics({ } }; - const handleScan = (e) => { - e.preventDefault(); - scanDevices(); + const mosipProp = { + container: document.getElementById( + "secure-biometric-interface-integration" + ), + buttonLabel: "scan_and_verify", + transactionId: getSBIAuthTransactionId(transactionId), + sbiEnv: { + env: "Staging", + captureTimeout: 30, + irisBioSubtypes: "UNKNOWN", + fingerBioSubtypes: "UNKNOWN", + faceCaptureCount: 1, + faceCaptureScore: 70, + fingerCaptureCount: 1, + fingerCaptureScore: 70, + irisCaptureCount: 1, + irisCaptureScore: 70, + portRange: "4501-4512", + discTimeout: 15, + dinfoTimeout: 30, + domainUri: `${window.origin}`, + }, + disable: true, + onErrored: setError, }; useEffect(() => { - scanDevices(); - }, []); - - const scanDevices = () => { - setError(null); - try { - setStatus({ - state: states.LOADING, - msg: "scanning_devices_msg", - }); - - mosipdisc_DiscoverDevicesAsync(host).then(() => { - setStatus({ state: states.LOADED, msg: "" }); - refreshDeviceList(); - }); - } catch (error) { - setError({ - prefix: "device_disc_failed", - errorCode: error.message, - defaultMsg: error.message, - }); - } - }; - - const refreshDeviceList = () => { - let deviceInfosPortsWise = getDeviceInfos(); - - if (!deviceInfosPortsWise) { - setModalityDevices(null); - setError({ - errorCode: "no_devices_found_msg", - }); + if (firstRender.current) { + firstRender.current = false; + init(mosipProp); return; } - - let modalitydevices = []; - - Object.keys(deviceInfosPortsWise).map((port) => { - let deviceInfos = deviceInfosPortsWise[port]; - - deviceInfos?.forEach((deviceInfo) => { - let deviceDetail = { - port: port, - specVersion: deviceInfo.specVersion[0], - type: deviceInfo.digitalId.type, - deviceId: deviceInfo.deviceId, - model: deviceInfo.digitalId.model, - serialNo: deviceInfo.digitalId.serialNo, - text: deviceInfo.digitalId.make + "-" + deviceInfo.digitalId.model, - value: deviceInfo.digitalId.serialNo, - icon: modalityIconPath[deviceInfo.digitalId.type], - }; - - modalitydevices.push(deviceDetail); - }); + propChange({ + disable: !loginState["sbi_mosip-vid"].length, + onCapture: (e) => authenticateBiometricResponse(e), }); - - setModalityDevices(modalitydevices); - - if (modalitydevices.length === 0) { - setError({ - errorCode: "no_devices_found_msg", - }); - return; - } - - let selectedDevice = modalitydevices[0]; - setSelectedDevice(selectedDevice); - }; + }, [loginState]); return ( <> @@ -333,7 +211,7 @@ export default function L1Biometrics({ > {t("sign_in_with_biometric")} -
+
{inputFields.map((field) => ( )} - {(status.state === states.LOADED || - status.state === states.AUTHENTICATING) && - modalityDevices && ( - <> - {selectedDevice && ( - <> -
- -
- ( -
- - {e.text} -
- )} - id="sbi_dropdown" - /> - -
-
-
- -
- - )} - - )} +
{error && (
@@ -415,15 +245,6 @@ export default function L1Biometrics({ errorCode={error.errorCode} defaultMsg={error.defaultMsg} /> - -
)} {status.state === states.AUTHENTICATING && error === null && ( From cbbe4a212ad135a9dfe21901903b7969a2b2c04a Mon Sep 17 00:00:00 2001 From: Zeeshan Mehboob Date: Thu, 15 Jun 2023 11:42:15 +0530 Subject: [PATCH 23/61] [FIXES] language changes --- oidc-ui/src/components/L1Biometrics.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/oidc-ui/src/components/L1Biometrics.js b/oidc-ui/src/components/L1Biometrics.js index 47504513a..fc9a7ab4c 100644 --- a/oidc-ui/src/components/L1Biometrics.js +++ b/oidc-ui/src/components/L1Biometrics.js @@ -20,7 +20,7 @@ export default function L1Biometrics({ openIDConnectService, i18nKeyPrefix = "l1Biometrics", }) { - const { t } = useTranslation("translation", { + const { i18n, t } = useTranslation("translation", { keyPrefix: i18nKeyPrefix, }); @@ -187,6 +187,7 @@ export default function L1Biometrics({ dinfoTimeout: 30, domainUri: `${window.origin}`, }, + langCode: i18n.language, disable: true, onErrored: setError, }; @@ -195,6 +196,9 @@ export default function L1Biometrics({ if (firstRender.current) { firstRender.current = false; init(mosipProp); + i18n.on("languageChanged", () => { + propChange({ langCode: i18n.language }); + }); return; } propChange({ From 111239d77f286db5c21b8436c27d98de863f5d73 Mon Sep 17 00:00:00 2001 From: anshulv1401 <31562315+anshulv1401@users.noreply.github.com> Date: Fri, 16 Jun 2023 16:56:24 +0530 Subject: [PATCH 24/61] Update Dockerfile (#238) install python failing Signed-off-by: anshulv1401 <31562315+anshulv1401@users.noreply.github.com> --- oidc-ui/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/oidc-ui/Dockerfile b/oidc-ui/Dockerfile index 6c5019498..0aa5bcb1e 100644 --- a/oidc-ui/Dockerfile +++ b/oidc-ui/Dockerfile @@ -44,7 +44,7 @@ WORKDIR /home/${container_user} # install packages and create user RUN apt-get -y update \ - && apt-get install -y curl npm python wget unzip zip \ + && apt-get install -y curl npm wget unzip zip \ && groupadd -g ${container_user_gid} ${container_user_group} \ && useradd -u ${container_user_uid} -g ${container_user_group} -s /bin/sh -m ${container_user} \ && mkdir -p /var/run/nginx /var/tmp/nginx ${base_path}/locales \ From d4839fae6c4c83409e330b13743d4aa1c38c3b61 Mon Sep 17 00:00:00 2001 From: anshulv1401 <31562315+anshulv1401@users.noreply.github.com> Date: Fri, 16 Jun 2023 18:41:55 +0530 Subject: [PATCH 25/61] plugin path creation added in docker file (#239) --- oidc-ui/Dockerfile | 4 ++-- oidc-ui/configure_start.sh | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/oidc-ui/Dockerfile b/oidc-ui/Dockerfile index 0aa5bcb1e..c6e38597c 100644 --- a/oidc-ui/Dockerfile +++ b/oidc-ui/Dockerfile @@ -47,8 +47,8 @@ RUN apt-get -y update \ && apt-get install -y curl npm wget unzip zip \ && groupadd -g ${container_user_gid} ${container_user_group} \ && useradd -u ${container_user_uid} -g ${container_user_group} -s /bin/sh -m ${container_user} \ - && mkdir -p /var/run/nginx /var/tmp/nginx ${base_path}/locales \ - && chown -R ${container_user}:${container_user} /usr/share/nginx /var/run/nginx /var/tmp/nginx ${base_path}/locales + && mkdir -p /var/run/nginx /var/tmp/nginx ${base_path}/locales ${base_path}/plugins \ + && chown -R ${container_user}:${container_user} /usr/share/nginx /var/run/nginx /var/tmp/nginx ${base_path}/locales ${base_path}/plugins ADD configure_start.sh configure_start.sh diff --git a/oidc-ui/configure_start.sh b/oidc-ui/configure_start.sh index 3a440850e..9ac0c9781 100644 --- a/oidc-ui/configure_start.sh +++ b/oidc-ui/configure_start.sh @@ -17,6 +17,8 @@ unzip -o esignet-i18n-bundle.zip #sign-in-button-plugin echo "Downloading plugins" +chmod 775 $plugins_path/* + mkdir $plugins_path/temp wget --no-check-certificate --no-cache --no-cookies $artifactory_url_env/artifactory/libs-release-local/esignet-plugins/sign-in-with-esignet.zip -O $plugins_path/temp/sign-in-button-plugin.zip From c7e39ec71f54542c231b63a385e9334209ec7cbf Mon Sep 17 00:00:00 2001 From: anshulv1401 <31562315+anshulv1401@users.noreply.github.com> Date: Fri, 16 Jun 2023 19:36:47 +0530 Subject: [PATCH 26/61] mkdir cmd moved to docker from config file (#243) --- oidc-ui/Dockerfile | 4 ++-- oidc-ui/configure_start.sh | 2 -- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/oidc-ui/Dockerfile b/oidc-ui/Dockerfile index c6e38597c..b22f4af27 100644 --- a/oidc-ui/Dockerfile +++ b/oidc-ui/Dockerfile @@ -47,8 +47,8 @@ RUN apt-get -y update \ && apt-get install -y curl npm wget unzip zip \ && groupadd -g ${container_user_gid} ${container_user_group} \ && useradd -u ${container_user_uid} -g ${container_user_group} -s /bin/sh -m ${container_user} \ - && mkdir -p /var/run/nginx /var/tmp/nginx ${base_path}/locales ${base_path}/plugins \ - && chown -R ${container_user}:${container_user} /usr/share/nginx /var/run/nginx /var/tmp/nginx ${base_path}/locales ${base_path}/plugins + && mkdir -p /var/run/nginx /var/tmp/nginx ${base_path}/locales ${base_path}/plugins ${base_path}/plugins/temp \ + && chown -R ${container_user}:${container_user} /usr/share/nginx /var/run/nginx /var/tmp/nginx ${base_path}/locales ${base_path}/plugins ${base_path}/plugins/temp ADD configure_start.sh configure_start.sh diff --git a/oidc-ui/configure_start.sh b/oidc-ui/configure_start.sh index 9ac0c9781..e4f2650c1 100644 --- a/oidc-ui/configure_start.sh +++ b/oidc-ui/configure_start.sh @@ -17,9 +17,7 @@ unzip -o esignet-i18n-bundle.zip #sign-in-button-plugin echo "Downloading plugins" -chmod 775 $plugins_path/* -mkdir $plugins_path/temp wget --no-check-certificate --no-cache --no-cookies $artifactory_url_env/artifactory/libs-release-local/esignet-plugins/sign-in-with-esignet.zip -O $plugins_path/temp/sign-in-button-plugin.zip echo "unzip plugins.." From 76d2735ada46a017b422d26329ade5848aba02b0 Mon Sep 17 00:00:00 2001 From: Hitesh C Date: Mon, 19 Jun 2023 10:26:24 +0530 Subject: [PATCH 27/61] [BUGFIX] updated kernel.keymanager depenency version to resolve build issues (#240) --- esignet-core/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esignet-core/pom.xml b/esignet-core/pom.xml index 1433838f7..bf99f9f3c 100644 --- a/esignet-core/pom.xml +++ b/esignet-core/pom.xml @@ -25,7 +25,7 @@ 2.12.0 2.12.0 2.12.0 - 1.2.1-SNAPSHOT + 1.2.0.1-B2 3.27.0-GA 4.13.2 2.22.0 From 08d04e5999f1aefe667f2cfd67a6b28aced65658 Mon Sep 17 00:00:00 2001 From: KONIJETI YASWANTHA NAGARJUNA <50859121+YaswanthNagarjuna@users.noreply.github.com> Date: Mon, 19 Jun 2023 15:58:38 +0530 Subject: [PATCH 28/61] sanity testing fixes --- oidc-ui/src/components/Background.js | 2 +- oidc-ui/src/components/Consent.js | 1 + oidc-ui/src/components/SignInOptions.js | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/oidc-ui/src/components/Background.js b/oidc-ui/src/components/Background.js index 8aaeb8718..f3892706d 100644 --- a/oidc-ui/src/components/Background.js +++ b/oidc-ui/src/components/Background.js @@ -53,7 +53,7 @@ export default function Background({ {t("logo_alt")}
-

+

{heading}

diff --git a/oidc-ui/src/components/Consent.js b/oidc-ui/src/components/Consent.js index 71bd70d85..aa0f0a559 100644 --- a/oidc-ui/src/components/Consent.js +++ b/oidc-ui/src/components/Consent.js @@ -300,6 +300,7 @@ export default function Consent({
{t(claimScope.label)}
); diff --git a/oidc-ui/src/constants/clientConstants.js b/oidc-ui/src/constants/clientConstants.js index fa93a626b..0403844de 100644 --- a/oidc-ui/src/constants/clientConstants.js +++ b/oidc-ui/src/constants/clientConstants.js @@ -71,7 +71,8 @@ const configurationKeys = { signInWithQRCodeEnable: "mosip.esignet.qr-code.enable", authTxnIdLength: "auth.txnid.length", otpLength: "otp.length", - passwordRegex : "password.regex" + passwordRegex: "password.regex", + consentScreenExpireInSec: "mosip.esignet.authentication-expire-in-secs" }; export { From b60da9372a0c1cd68f1ff1ba038e7ea7173993f0 Mon Sep 17 00:00:00 2001 From: KONIJETI YASWANTHA NAGARJUNA <50859121+YaswanthNagarjuna@users.noreply.github.com> Date: Wed, 12 Jul 2023 13:05:51 +0530 Subject: [PATCH 41/61] Added transaction expiry details with a timer on the consent page --- .../resources/application-local.properties | 3 +- oidc-ui/.env | 4 ++- oidc-ui/src/components/Consent.js | 34 +++++++++++++------ oidc-ui/src/constants/clientConstants.js | 3 +- oidc-ui/src/services/authService.js | 6 ++-- 5 files changed, 34 insertions(+), 16 deletions(-) diff --git a/esignet-service/src/main/resources/application-local.properties b/esignet-service/src/main/resources/application-local.properties index bba08cd4a..c02028dc2 100644 --- a/esignet-service/src/main/resources/application-local.properties +++ b/esignet-service/src/main/resources/application-local.properties @@ -236,4 +236,5 @@ crypto.PrependThumbprint.enable=true 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':${mosip.esignet.authentication-expire-in-secs}} \ No newline at end of file + 'send.otp.channels':'email,phone', 'consent.screen.timeout-in-secs':${mosip.esignet.authentication-expire-in-secs}, \ + 'consent.screen.timeout-buffer-in-secs': 5} \ No newline at end of file diff --git a/oidc-ui/.env b/oidc-ui/.env index e2d8834d3..92b38a73d 100644 --- a/oidc-ui/.env +++ b/oidc-ui/.env @@ -39,4 +39,6 @@ REACT_APP_AUTH_TXN_ID_LENGTH=10 REACT_APP_OTP_LENGTH=6 -REACT_APP_PASSWORD_REGEX="" \ No newline at end of file +REACT_APP_PASSWORD_REGEX="" + +REACT_APP_CONSENT_SCREEN_TIME_OUT_BUFFER_IN_SEC=5 \ No newline at end of file diff --git a/oidc-ui/src/components/Consent.js b/oidc-ui/src/components/Consent.js index 2ada8b392..74384038d 100644 --- a/oidc-ui/src/components/Consent.js +++ b/oidc-ui/src/components/Consent.js @@ -23,7 +23,12 @@ export default function Consent({ configurationKeys.consentScreenExpireInSec ) ?? process.env.REACT_APP_CONSENT_SCREEN_EXPIRE_IN_SEC; - const timeoutBuffer = 5; // in seconds + // The transaction timer will be derived from the configuration file of e-Signet so buffer of -5 sec is added in the timer. + const timeoutBuffer = + openIDConnectService.getEsignetConfiguration( + configurationKeys.consentScreenTimeOutBufferInSec + ) ?? process.env.REACT_APP_CONSENT_SCREEN_TIME_OUT_BUFFER_IN_SEC; + const transactionTimeoutWithBuffer = authenticationExpireInSec - timeoutBuffer; const firstRender = useRef(true); @@ -33,7 +38,7 @@ export default function Consent({ const [clientName, setClientName] = useState(""); const [clientLogoPath, setClientLogoPath] = useState(""); const [claimsScopes, setClaimsScopes] = useState([]); - const [timeLeft, setTimeLeft] = useState(transactionTimeoutWithBuffer); + const [timeLeft, setTimeLeft] = useState(null); const [consentScreenTimer, setConsentScreenTimer] = useState(null); const hasAllElement = (mainArray, subArray) => @@ -186,17 +191,26 @@ export default function Consent({ return; } scopeClaimChanges(); - startConsentScreenTimer(); }, [scope, claims]); - const startConsentScreenTimer = async () => { + useEffect(() => { + const currentTime = Math.floor(new Date().getTime() / 1000); + const searchParams = new URLSearchParams(window.location.search); + const authTime = searchParams.get("authenticationTime"); + if (authTime) { + let timePassed = currentTime - authTime; + startConsentScreenTimer(timePassed); + } + }, []) + + const startConsentScreenTimer = async (timePassed) => { clearInterval(consentScreenTimer); - let timePassed = 0 + let tLeft = transactionTimeoutWithBuffer - timePassed; + setTimeLeft(tLeft); + const interval = setInterval(() => { - timePassed++ - let tLeft = transactionTimeoutWithBuffer - timePassed; - setTimeLeft(tLeft); - if (tLeft === 0) { + setTimeLeft(--tLeft); + if (tLeft <= 0) { clearInterval(interval); onError("invalid_transaction", t("invalid_transaction")); } @@ -427,7 +441,7 @@ export default function Consent({ )}
- {timeLeft > 0 && status !== LoadingStates.LOADING && ( + {timeLeft && timeLeft > 0 && status !== LoadingStates.LOADING && (

{t("transaction_timeout_msg")}

{formatTime(timeLeft)}

diff --git a/oidc-ui/src/constants/clientConstants.js b/oidc-ui/src/constants/clientConstants.js index 0403844de..3a8065fb9 100644 --- a/oidc-ui/src/constants/clientConstants.js +++ b/oidc-ui/src/constants/clientConstants.js @@ -72,7 +72,8 @@ const configurationKeys = { authTxnIdLength: "auth.txnid.length", otpLength: "otp.length", passwordRegex: "password.regex", - consentScreenExpireInSec: "mosip.esignet.authentication-expire-in-secs" + consentScreenExpireInSec: "consent.screen.timeout-in-secs", + consentScreenTimeOutBufferInSec: "consent.screen.timeout-buffer-in-secs" }; export { diff --git a/oidc-ui/src/services/authService.js b/oidc-ui/src/services/authService.js index 34a6d63a0..f246b1964 100644 --- a/oidc-ui/src/services/authService.js +++ b/oidc-ui/src/services/authService.js @@ -210,6 +210,8 @@ class authService { */ buildRedirectParams = (nonce, state, oauthReponse, consentAction) => { let params = "?"; + let authenticationTime = Math.floor(new Date().getTime() / 1000); + if (nonce) { params = params + "nonce=" + nonce + "&"; } @@ -219,13 +221,11 @@ class authService { if (consentAction) { params = params + "consentAction=" + consentAction + "&"; } - //removing last "&" or "?" character - params = params.substring(0, params.length - 1); + params = params + "authenticationTime=" + authenticationTime; let responseStr = JSON.stringify(oauthReponse); let responseB64 = Buffer.from(responseStr).toString("base64"); params = params + "#" + responseB64; - return params; }; } From 646058d822f07417722d83668a5fe2ca7a697187 Mon Sep 17 00:00:00 2001 From: KONIJETI YASWANTHA NAGARJUNA <50859121+YaswanthNagarjuna@users.noreply.github.com> Date: Thu, 13 Jul 2023 15:09:09 +0530 Subject: [PATCH 42/61] Added transaction expiry details with a timer on the consent page using setTimeout --- oidc-ui/src/components/Consent.js | 40 +++++++++++++++---------------- oidc-ui/src/pages/Consent.js | 3 +++ 2 files changed, 23 insertions(+), 20 deletions(-) diff --git a/oidc-ui/src/components/Consent.js b/oidc-ui/src/components/Consent.js index 74384038d..1f51adc3d 100644 --- a/oidc-ui/src/components/Consent.js +++ b/oidc-ui/src/components/Consent.js @@ -10,6 +10,7 @@ import FormAction from "./FormAction"; export default function Consent({ authService, consentAction, + authTime, openIDConnectService, logoPath = "logo.png", i18nKeyPrefix = "consent", @@ -39,7 +40,6 @@ export default function Consent({ const [clientLogoPath, setClientLogoPath] = useState(""); const [claimsScopes, setClaimsScopes] = useState([]); const [timeLeft, setTimeLeft] = useState(null); - const [consentScreenTimer, setConsentScreenTimer] = useState(null); const hasAllElement = (mainArray, subArray) => subArray.every((ele) => mainArray.includes(ele)); @@ -194,29 +194,29 @@ export default function Consent({ }, [scope, claims]); useEffect(() => { - const currentTime = Math.floor(new Date().getTime() / 1000); - const searchParams = new URLSearchParams(window.location.search); - const authTime = searchParams.get("authenticationTime"); - if (authTime) { + const timer = setTimeout(() => { + let currentTime = Math.floor(new Date().getTime() / 1000); let timePassed = currentTime - authTime; - startConsentScreenTimer(timePassed); - } - }, []) - - const startConsentScreenTimer = async (timePassed) => { - clearInterval(consentScreenTimer); - let tLeft = transactionTimeoutWithBuffer - timePassed; - setTimeLeft(tLeft); - - const interval = setInterval(() => { - setTimeLeft(--tLeft); + let tLeft = transactionTimeoutWithBuffer - timePassed; if (tLeft <= 0) { - clearInterval(interval); onError("invalid_transaction", t("invalid_transaction")); + return; } + setTimeLeft(tLeft); }, 1000); - setConsentScreenTimer(interval); - } + return () => { + clearTimeout(timer); + }; + }, [timeLeft]); + + useEffect(() => { + if (authTime) { + let currentTime = Math.floor(new Date().getTime() / 1000); + let timePassed = currentTime - authTime; + let tLeft = transactionTimeoutWithBuffer - timePassed; + setTimeLeft(tLeft); + } + }, []) function formatTime(time) { const minutes = Math.floor(time / 60).toString().padStart(2, "0"); @@ -363,7 +363,7 @@ export default function Consent({
{t(claimScope.label)} - +
From eeaff9dea2e3eaea0a9cafdec429a0ced9492f02 Mon Sep 17 00:00:00 2001 From: KONIJETI YASWANTHA NAGARJUNA <50859121+YaswanthNagarjuna@users.noreply.github.com> Date: Tue, 18 Jul 2023 17:19:42 +0530 Subject: [PATCH 46/61] Updated IDP UI config in application.propreties (#267) --- .../src/main/resources/application-local.properties | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/esignet-service/src/main/resources/application-local.properties b/esignet-service/src/main/resources/application-local.properties index 90fedb3bc..9e91ab7a4 100644 --- a/esignet-service/src/main/resources/application-local.properties +++ b/esignet-service/src/main/resources/application-local.properties @@ -237,4 +237,9 @@ mosip.esignet.ui.config.key-values={'sbi.env': 'Developer', 'sbi.timeout.DISC': '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, 'wallet.logo-url': 'inji_logo.png', \ 'send.otp.channels':'email,phone', 'consent.screen.timeout-in-secs':${mosip.esignet.authentication-expire-in-secs}, \ - 'consent.screen.timeout-buffer-in-secs': 5} \ No newline at end of file + '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': 'OTP', 'captcha.sitekey': '6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI', \ + 'mosip.esignet.link-auth-code-expire-in-secs': 120, 'mosip.esignet.link-status-deferred-response-timeout-secs': 25, \ + 'mosip.esignet.qr-code.deep-link-uri': 'inji://landing-page-name?linkCode=LINK_CODE&linkExpireDateTime=LINK_EXPIRE_DT', \ + 'mosip.esignet.qr-code.download-uri': '#', 'mosip.esignet.qr-code.enable': 'true', 'auth.txnid.length': 10, \ + 'otp.length': 6, 'password.regex': ''} \ No newline at end of file From c5abaa066e9753d8223ac29f345f9ca82c71d6c3 Mon Sep 17 00:00:00 2001 From: Hitesh C Date: Wed, 19 Jul 2023 15:29:21 +0530 Subject: [PATCH 47/61] [ES-157] (#263) (#271) updated postman collection to include v2 api --- ...Esignet Collection.postman_collection.json | 246 +++++++++++++++++- 1 file changed, 244 insertions(+), 2 deletions(-) diff --git a/docs/Esignet Collection.postman_collection.json b/docs/Esignet Collection.postman_collection.json index e471463f3..87c50a1c0 100644 --- a/docs/Esignet Collection.postman_collection.json +++ b/docs/Esignet Collection.postman_collection.json @@ -1,9 +1,9 @@ { "info": { - "_postman_id": "2bbed2fa-e3f2-4820-9abd-64ef5e1accee", + "_postman_id": "496855d4-693e-43f6-b0be-dd22c2cd3fa1", "name": "MOSIP e-Signet Collection", "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", - "_exporter_id": "20579541" + "_exporter_id": "6039892" }, "item": [ { @@ -464,6 +464,71 @@ }, "response": [] }, + { + "name": "Authenticate User V2", + "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/v2/authenticate", + "host": [ + "{{url}}" + ], + "path": [ + "authorization", + "v2", + "authenticate" + ] + } + }, + "response": [] + }, { "name": "Authorization Code", "event": [ @@ -854,6 +919,86 @@ }, "response": [] }, + { + "name": "Link Authenticate User (wallet) -V2", + "event": [ + { + "listen": "prerequest", + "script": { + "exec": [ + "eval(pm.globals.get('pmlib_code'))", + "", + "//sign token", + "const private_key_jwk = {", + " \"p\": \"xZDfG1GbHpd7C81k2au8ntvFsTCXj96iyimsHXBzgvKL9WdZfwVVjw5sWCZwSTqt6gL7wCTGxxUeQsN4IKfCalCAmHzFkvDANLi-7LmT2ZJM992j-E7oEOQOv7H4VRqBuir7bECpeeSRoI0qVs07olA5RCKUZpF4iBlecjVVD3M\",", + " \"kty\": \"RSA\",", + " \"q\": \"qGRtmjha2uqCwmGRZS19qWD3ICeLE8NjNgmqx6pI0SLEzD5uQS98T8JOWZxTUjyOm5LtisWBfhloZdT9UNnRX6yMFIswLovTKcYo38yD5fQ9K2gpqzD0K9_ngST08aTDOPY_IlCGe2RZeeHhulyA71MpFhSZLaU2rG2u5exwxBc\",", + " \"d\": \"Of0lDpdIXY3jyhcKuatsw1N6zQpn20UQHxzMdZH2XHSHMzC1vYvbOQD2JmoSahggu2or0n5JeAMbs2k1BlabSqHM65TaJMgKjJVWIiSEAPBhPbqJqGF7nZKrHNk6jVgVYDI_rFGdo7DwNw8-RS0QSiuLBCbmCgCM9wiFWarn2pE9MpK9n_xEmRVNrSFhlvWyPmCCsr5TVVOrXF_7ERYevPDN22uZC0cYgdEtPI80AUZy5ofJnSnIZ0n0fZFO5I7rUFU_MDMuM7W2plKS__fT9UWCBk4mGCgqgqfIzBGFGT2sRDs1kMgVhMMoNFDlc8Hy3KptHmOOOGeb3rwYUixb0Q\",", + " \"e\": \"AQAB\",", + " \"use\": \"sig\",", + " \"qi\": \"bLWOocu5x-RCoxh1MXtJ4Dkahk7vjdQ2iUGiRjmJEL61tKIV1NQk7D5yUl5BFlWanMBwdajRlwcg81ZYV81v2aE2qczOm8X23S8K1QQOSlb2-3p_cGCxaOb9LqV6kDcNetVp2sAxJ-naQLPstE0LQiLGnmij-LwarZFbrpQVVb8\",", + " \"dp\": \"I5De-TYJrMosVoWVQDJQdHCv-CP9ROMZfzddSrdxtAMh-v2t-NXm_yfjjULuN-CeamA7He4A8tn0ZqR1vbs1npn7bHgZwUgh8dvIUyldWm-h94Uo_YyG7nN_zDans_pfnDocpPJHEDB7nuGK27F6qM-0X3WyLXzGrAmVHQ5Iz80\",", + " \"alg\": \"RS256\",", + " \"dq\": \"QJCBFaiV7WoNSMpwHQMcM11iY4nF4YYA_C8os_WuhcF3A3jMfWHfoBU4RVOS_u0JIM1tFtAznk3PoXvQxLc_eBeIfjf_-VjTVikMcwLPb9P9wC7oCyNx-4CWGwY4hI5P6_8-pcGKTrVjOUBKdFITfa-9CSJMuRunouVLMg0-D3E\",", + " \"n\": \"gfSTlsfcU4hCChv8FZ-ffFfNlPesknqVsZubLOlPKB5JHEHEhyy4yRjRmUQK9hzgsSKNyNVrqJIePZnCBKdjs1wxR3uM895hCLfJTQXU1p1hON0VfX0lbG2-y-ZLD6zTkUbn3JNLFc1mxWn4IAiXeKmpXlBqUM3QPCKQWp95lmhfq45UkbdEPkCssdeqYoShkCJWd7GFhC5qOoMLfbNT71q5s3L7VoqKnEpbCsKhvN6BkT4jE1m4xy4jCpc80uZR6bnKG1gryN_LSjeubrodjWpfUrDKCXT23R-RKhMRjCK3sJQbnERJkzpIQ8b_GcOhRzL07BNAoXafRqhrsMhvVQ\"", + "}", + "", + "// Set headers for JWT", + "var certificate = eval(pm.environment.get('bind_certificate'));", + "var public_key_jwk = pmlib.rs.KEYUTIL.getJWK(certificate);", + "// Set headers for JWT", + "var header = {", + " \"x5t#S256\" : public_key_jwk['x5t#S256'],", + "\t\"alg\": \"RS256\"", + "};", + "", + "//const signed_jwt = pmlib.clientAssertPrivateKey(private_key_jwk, pm.environment.get('individual_id'), pm.environment.get('wla_aud'), exp = 60, \"RS256\");", + "", + "const signed_jwt = pmlib.jwtSign(private_key_jwk, {", + " \"aud\" : pm.environment.get('wla_aud'),", + "\t\"sub\": pm.environment.get('individual_id'),", + " \"iss\" : \"postman-inji\"", + "}, header, exp=600, alg = \"RS256\")", + "", + "pm.collectionVariables.set(\"wla_challenge\",signed_jwt);", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "X-XSRF-TOKEN", + "value": "{{csrf_token}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"requestTime\": \"{{$isoTimestamp}}\",\n \"request\": {\n \"linkedTransactionId\": \"{{linkTransactionId}}\",\n \"individualId\": \"{{individual_id}}\",\n \"challengeList\" : [\n {\n \"authFactorType\" : \"WLA\",\n \"challenge\" : \"{{wla_challenge}}\",\n \"format\" : \"jwt\"\n }\n ]\n }\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{url}}/linked-authorization/v2/authenticate", + "host": [ + "{{url}}" + ], + "path": [ + "linked-authorization", + "v2", + "authenticate" + ] + } + }, + "response": [] + }, { "name": "Link Consent Request (wallet)", "event": [ @@ -905,6 +1050,103 @@ }, "response": [] }, + { + "name": "Link Consent Request (wallet) - V2", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "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" + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "eval(pm.globals.get('pmlib_code'));", + "", + "const private_key_jwk = {", + " \"p\": \"xZDfG1GbHpd7C81k2au8ntvFsTCXj96iyimsHXBzgvKL9WdZfwVVjw5sWCZwSTqt6gL7wCTGxxUeQsN4IKfCalCAmHzFkvDANLi-7LmT2ZJM992j-E7oEOQOv7H4VRqBuir7bECpeeSRoI0qVs07olA5RCKUZpF4iBlecjVVD3M\",", + " \"kty\": \"RSA\",", + " \"q\": \"qGRtmjha2uqCwmGRZS19qWD3ICeLE8NjNgmqx6pI0SLEzD5uQS98T8JOWZxTUjyOm5LtisWBfhloZdT9UNnRX6yMFIswLovTKcYo38yD5fQ9K2gpqzD0K9_ngST08aTDOPY_IlCGe2RZeeHhulyA71MpFhSZLaU2rG2u5exwxBc\",", + " \"d\": \"Of0lDpdIXY3jyhcKuatsw1N6zQpn20UQHxzMdZH2XHSHMzC1vYvbOQD2JmoSahggu2or0n5JeAMbs2k1BlabSqHM65TaJMgKjJVWIiSEAPBhPbqJqGF7nZKrHNk6jVgVYDI_rFGdo7DwNw8-RS0QSiuLBCbmCgCM9wiFWarn2pE9MpK9n_xEmRVNrSFhlvWyPmCCsr5TVVOrXF_7ERYevPDN22uZC0cYgdEtPI80AUZy5ofJnSnIZ0n0fZFO5I7rUFU_MDMuM7W2plKS__fT9UWCBk4mGCgqgqfIzBGFGT2sRDs1kMgVhMMoNFDlc8Hy3KptHmOOOGeb3rwYUixb0Q\",", + " \"e\": \"AQAB\",", + " \"use\": \"sig\",", + " \"qi\": \"bLWOocu5x-RCoxh1MXtJ4Dkahk7vjdQ2iUGiRjmJEL61tKIV1NQk7D5yUl5BFlWanMBwdajRlwcg81ZYV81v2aE2qczOm8X23S8K1QQOSlb2-3p_cGCxaOb9LqV6kDcNetVp2sAxJ-naQLPstE0LQiLGnmij-LwarZFbrpQVVb8\",", + " \"dp\": \"I5De-TYJrMosVoWVQDJQdHCv-CP9ROMZfzddSrdxtAMh-v2t-NXm_yfjjULuN-CeamA7He4A8tn0ZqR1vbs1npn7bHgZwUgh8dvIUyldWm-h94Uo_YyG7nN_zDans_pfnDocpPJHEDB7nuGK27F6qM-0X3WyLXzGrAmVHQ5Iz80\",", + " \"alg\": \"RS256\",", + " \"dq\": \"QJCBFaiV7WoNSMpwHQMcM11iY4nF4YYA_C8os_WuhcF3A3jMfWHfoBU4RVOS_u0JIM1tFtAznk3PoXvQxLc_eBeIfjf_-VjTVikMcwLPb9P9wC7oCyNx-4CWGwY4hI5P6_8-pcGKTrVjOUBKdFITfa-9CSJMuRunouVLMg0-D3E\",", + " \"n\": \"gfSTlsfcU4hCChv8FZ-ffFfNlPesknqVsZubLOlPKB5JHEHEhyy4yRjRmUQK9hzgsSKNyNVrqJIePZnCBKdjs1wxR3uM895hCLfJTQXU1p1hON0VfX0lbG2-y-ZLD6zTkUbn3JNLFc1mxWn4IAiXeKmpXlBqUM3QPCKQWp95lmhfq45UkbdEPkCssdeqYoShkCJWd7GFhC5qOoMLfbNT71q5s3L7VoqKnEpbCsKhvN6BkT4jE1m4xy4jCpc80uZR6bnKG1gryN_LSjeubrodjWpfUrDKCXT23R-RKhMRjCK3sJQbnERJkzpIQ8b_GcOhRzL07BNAoXafRqhrsMhvVQ\"", + "};", + "var certificate = eval(pm.environment.get('bind_certificate'));", + "var public_key_jwk = pmlib.rs.KEYUTIL.getJWK(certificate);", + "// Set headers for JWT", + "var header = {", + " \"x5t#S256\" : public_key_jwk['x5t#S256'],", + "\t\"alg\": \"RS256\"", + "};", + "var payload = {}", + "var acceptedClaims = pm.environment.get('acceptedClaims');", + "if(acceptedClaims != undefined && Array.isArray(acceptedClaims)){", + " payload[\"acceptedClaims\"] = acceptedClaims.sort()", + "}", + "var permittedAuthorizedScopes = eval(pm.environment.get('permittedAuthorizedScopes'));", + "if(permittedAuthorizedScopes != undefined && Array.isArray(permittedAuthorizedScopes)){", + " payload[\"permittedAuthorizedScopes\"] = permittedAuthorizedScopes.sort()", + "}", + "const signedPayload = pmlib.rs.jws.JWS.sign(", + " null, header, payload, private_key_jwk", + ");", + "var parts = signedPayload.split(\".\");", + "var detachedSignature = parts[0] + \".\" + parts[2];", + "pm.environment.set(\"detachedSignature\", detachedSignature);" + ], + "type": "text/javascript" + } + } + ], + "protocolProfileBehavior": { + "followRedirects": false + }, + "request": { + "method": "POST", + "header": [ + { + "key": "X-XSRF-TOKEN", + "value": "{{csrf_token}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"requestTime\": \"{{$isoTimestamp}}\",\n \"request\": {\n \"linkedTransactionId\": \"{{linkTransactionId}}\",\n \"acceptedClaims\": {{acceptedClaims}},\n \"signature\": \"{{detachedSignature}}\"\n }\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{url}}/linked-authorization/v2/consent", + "host": [ + "{{url}}" + ], + "path": [ + "linked-authorization", + "v2", + "consent" + ] + } + }, + "response": [] + }, { "name": "Link auth code request", "event": [ From 30fd17b40da59b929629d5b304ac3950f6dda90b Mon Sep 17 00:00:00 2001 From: anshulv1401 <31562315+anshulv1401@users.noreply.github.com> Date: Wed, 19 Jul 2023 15:45:00 +0530 Subject: [PATCH 48/61] number check added (#269) --- oidc-ui/src/components/Consent.js | 18 +++++++++++------- oidc-ui/src/services/authService.js | 7 ++++++- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/oidc-ui/src/components/Consent.js b/oidc-ui/src/components/Consent.js index c80d95241..284582b25 100644 --- a/oidc-ui/src/components/Consent.js +++ b/oidc-ui/src/components/Consent.js @@ -24,7 +24,7 @@ export default function Consent({ configurationKeys.consentScreenExpireInSec ) ?? process.env.REACT_APP_CONSENT_SCREEN_EXPIRE_IN_SEC; - // The transaction timer will be derived from the configuration file of e-Signet so buffer of -5 sec is added in the timer. + // The transaction timer will be derived from the configuration file of e-Signet so buffer of -5 sec is added in the timer. const timeoutBuffer = openIDConnectService.getEsignetConfiguration( configurationKeys.consentScreenTimeOutBufferInSec @@ -194,6 +194,9 @@ export default function Consent({ }, [scope, claims]); useEffect(() => { + if (isNaN(authTime)) { + return; + } const timer = setTimeout(() => { let currentTime = Math.floor(new Date().getTime() / 1000); let timePassed = currentTime - authTime; @@ -210,13 +213,14 @@ export default function Consent({ }, [timeLeft]); useEffect(() => { - if (authTime) { - let currentTime = Math.floor(new Date().getTime() / 1000); - let timePassed = currentTime - authTime; - let tLeft = transactionTimeoutWithBuffer - timePassed; - setTimeLeft(tLeft); + if (isNaN(authTime)) { + return; } - }, []) + let currentTime = Math.floor(new Date().getTime() / 1000); + let timePassed = currentTime - authTime; + let tLeft = transactionTimeoutWithBuffer - timePassed; + setTimeLeft(tLeft); + }, []); function formatTime(time) { const minutes = Math.floor(time / 60).toString().padStart(2, "0"); diff --git a/oidc-ui/src/services/authService.js b/oidc-ui/src/services/authService.js index f246b1964..0a276cf40 100644 --- a/oidc-ui/src/services/authService.js +++ b/oidc-ui/src/services/authService.js @@ -215,13 +215,18 @@ class authService { if (nonce) { params = params + "nonce=" + nonce + "&"; } + if (state) { params = params + "state=" + state + "&"; } + if (consentAction) { params = params + "consentAction=" + consentAction + "&"; + params = params + "authenticationTime=" + authenticationTime + "&"; } - params = params + "authenticationTime=" + authenticationTime; + + //removing last "&" character + params = params.substring(0, params.length - 1); let responseStr = JSON.stringify(oauthReponse); let responseB64 = Buffer.from(responseStr).toString("base64"); From 94b0c323ab03e5625341b9901150eb2158da4ecc Mon Sep 17 00:00:00 2001 From: KONIJETI YASWANTHA NAGARJUNA <50859121+YaswanthNagarjuna@users.noreply.github.com> Date: Wed, 19 Jul 2023 19:08:41 +0530 Subject: [PATCH 49/61] added format in test cases (#272) --- .../src/test/java/io/mosip/esignet/KeyBindingServiceTest.java | 1 + 1 file changed, 1 insertion(+) diff --git a/binding-service-impl/src/test/java/io/mosip/esignet/KeyBindingServiceTest.java b/binding-service-impl/src/test/java/io/mosip/esignet/KeyBindingServiceTest.java index cd56a241d..b139602b7 100644 --- a/binding-service-impl/src/test/java/io/mosip/esignet/KeyBindingServiceTest.java +++ b/binding-service-impl/src/test/java/io/mosip/esignet/KeyBindingServiceTest.java @@ -201,6 +201,7 @@ public void bindWallet_withUnsupportedFormat_thenFail() throws EsignetException, AuthChallenge authChallenge = new AuthChallenge(); authChallenge.setAuthFactorType("OTP"); authChallenge.setChallenge("111111"); + authChallenge.setFormat("alpha-numeric"); List authChallengeList = new ArrayList(); authChallengeList.add(authChallenge); walletBindingRequest.setChallengeList(authChallengeList); From e16bb028fbd266830b5e06de34b9151dd27c9c8f Mon Sep 17 00:00:00 2001 From: Hitesh C Date: Mon, 24 Jul 2023 13:05:18 +0530 Subject: [PATCH 50/61] [ES-177] (#279) * [ES-176] [ES-177] (#270) * [ES-177] * [MOIFIED] github actions * [CHANGES] review comment changes * [ES-177] (#278) * [ES-177] * [MOIFIED] github actions * [CHANGES] review comment changes * Updated test cases and added audit logs --- .github/workflows/push_trigger.yml | 1 + .../mosip/esignet/KeyBindingServiceTest.java | 2 +- .../esignet/repository/ConsentRepository.java | 1 + .../esignet/services/ConsentServiceImpl.java | 6 ++ .../esignet/ConsentDetailRepositoryTest.java | 32 +++++++++ .../mosip/esignet/ConsentServiceImplTest.java | 8 +++ .../esignet/core/dto/OIDCTransaction.java | 2 + .../esignet/core/spi/ConsentService.java | 7 ++ .../io/mosip/esignet/api/util/Action.java | 3 +- .../services/AuthorizationServiceImpl.java | 5 +- .../services/ConsentHelperService.java | 38 ++++++++-- .../LinkedAuthorizationServiceImpl.java | 3 +- .../services/ConsentHelperServiceTest.java | 71 +++++++++++++++++-- 13 files changed, 160 insertions(+), 19 deletions(-) diff --git a/.github/workflows/push_trigger.yml b/.github/workflows/push_trigger.yml index f5038f38f..dc6d7ae94 100644 --- a/.github/workflows/push_trigger.yml +++ b/.github/workflows/push_trigger.yml @@ -10,6 +10,7 @@ on: - 1.* - develop - main + - bugfix-ES-177 jobs: call-workflow-codeql-analysis: diff --git a/binding-service-impl/src/test/java/io/mosip/esignet/KeyBindingServiceTest.java b/binding-service-impl/src/test/java/io/mosip/esignet/KeyBindingServiceTest.java index b139602b7..193a7c549 100644 --- a/binding-service-impl/src/test/java/io/mosip/esignet/KeyBindingServiceTest.java +++ b/binding-service-impl/src/test/java/io/mosip/esignet/KeyBindingServiceTest.java @@ -211,7 +211,7 @@ public void bindWallet_withUnsupportedFormat_thenFail() throws EsignetException, Assert.assertNotNull(keyBindingService.bindWallet(walletBindingRequest, new HashMap<>())); Assert.fail(); } catch (EsignetException e) { - Assert.assertTrue(e.getErrorCode().equals(ErrorConstants.INVALID_CHALLENGE_FORMAT)); + Assert.assertTrue(e.getErrorCode().equals(ErrorConstants.INVALID_AUTH_FACTOR_TYPE_OR_CHALLENGE_FORMAT)); } } diff --git a/consent-service-impl/src/main/java/io/mosip/esignet/repository/ConsentRepository.java b/consent-service-impl/src/main/java/io/mosip/esignet/repository/ConsentRepository.java index a66553ea8..80b49a94f 100644 --- a/consent-service-impl/src/main/java/io/mosip/esignet/repository/ConsentRepository.java +++ b/consent-service-impl/src/main/java/io/mosip/esignet/repository/ConsentRepository.java @@ -12,6 +12,7 @@ import java.util.UUID; @Repository public interface ConsentRepository extends JpaRepository { + boolean existsByClientIdAndPsuToken(String clientId, String psuToken); Optional findByClientIdAndPsuToken(String clientId, String psuToken); void deleteByClientIdAndPsuToken(String clientId, String psuToken); diff --git a/consent-service-impl/src/main/java/io/mosip/esignet/services/ConsentServiceImpl.java b/consent-service-impl/src/main/java/io/mosip/esignet/services/ConsentServiceImpl.java index 8dfbd576d..ec0c48a9d 100644 --- a/consent-service-impl/src/main/java/io/mosip/esignet/services/ConsentServiceImpl.java +++ b/consent-service-impl/src/main/java/io/mosip/esignet/services/ConsentServiceImpl.java @@ -86,4 +86,10 @@ public ConsentDetail saveUserConsent(UserConsent userConsent) { AuditHelper.buildAuditDto(userConsent.getClientId()), null); return consentDetailDto; } + + @Override + @Transactional + public void deleteUserConsent(String clientId, String psuToken) { + consentRepository.deleteByClientIdAndPsuToken(clientId, psuToken); + } } diff --git a/consent-service-impl/src/test/java/io/mosip/esignet/ConsentDetailRepositoryTest.java b/consent-service-impl/src/test/java/io/mosip/esignet/ConsentDetailRepositoryTest.java index 4375cfb35..52b810330 100644 --- a/consent-service-impl/src/test/java/io/mosip/esignet/ConsentDetailRepositoryTest.java +++ b/consent-service-impl/src/test/java/io/mosip/esignet/ConsentDetailRepositoryTest.java @@ -173,4 +173,36 @@ public void createConsent_withNullCreatedtimes_thenFail() { Assert.fail(); } + @Test + public void createAndDeleteConsent_withValidDetail_thenPass() { + + ConsentDetail consentDetail =new ConsentDetail(); + UUID uuid=UUID.randomUUID(); + LocalDateTime date = LocalDateTime.of(2019, 12, 12, 12, 12, 12); + consentDetail.setClientId("123"); + consentDetail.setPsuToken("abc"); + consentDetail.setClaims("claims"); + consentDetail.setAuthorizationScopes("authorizationScopes"); + consentDetail.setCreatedtimes(date); + consentDetail.setExpiredtimes(LocalDateTime.now()); + consentDetail.setSignature("signature"); + consentDetail.setHash("hash"); + consentDetail.setAcceptedClaims("claim"); + consentDetail.setPermittedScopes("scope"); + consentDetail =consentRepository.save(consentDetail); + Assert.assertNotNull(consentDetail); + + Optional result; + + result = consentRepository.findByClientIdAndPsuToken("123", "abc"); + Assert.assertTrue(result.isPresent()); + + result = consentRepository.findByClientIdAndPsuToken("123", "abcd"); + Assert.assertFalse(result.isPresent()); + consentRepository.deleteByClientIdAndPsuToken(consentDetail.getClientId(),consentDetail.getPsuToken()); + consentRepository.flush(); + Optional consentDetailOptional = consentRepository.findByClientIdAndPsuToken("123", "abc"); + Assert.assertFalse(consentDetailOptional.isPresent()); + } + } diff --git a/consent-service-impl/src/test/java/io/mosip/esignet/ConsentServiceImplTest.java b/consent-service-impl/src/test/java/io/mosip/esignet/ConsentServiceImplTest.java index 4e22c42cf..9fe489724 100644 --- a/consent-service-impl/src/test/java/io/mosip/esignet/ConsentServiceImplTest.java +++ b/consent-service-impl/src/test/java/io/mosip/esignet/ConsentServiceImplTest.java @@ -139,5 +139,13 @@ public void saveUserConsent_withValidDetails_thenPass() throws Exception{ } + @Test + public void deleteConsentByClientIdAndPsuToken_thenPass(){ + String clientId = "test-client-id"; + String psuToken = "test-psu-token"; + consentService.deleteUserConsent(clientId,psuToken); + Mockito.verify(consentRepository).deleteByClientIdAndPsuToken(clientId, psuToken); + } + } diff --git a/esignet-core/src/main/java/io/mosip/esignet/core/dto/OIDCTransaction.java b/esignet-core/src/main/java/io/mosip/esignet/core/dto/OIDCTransaction.java index b0e857119..4ede0e067 100644 --- a/esignet-core/src/main/java/io/mosip/esignet/core/dto/OIDCTransaction.java +++ b/esignet-core/src/main/java/io/mosip/esignet/core/dto/OIDCTransaction.java @@ -21,6 +21,8 @@ public class OIDCTransaction implements Serializable { String relyingPartyId; String redirectUri; Claims requestedClaims; + List essentialClaims; + List voluntaryClaims; List requestedAuthorizeScopes; String[] claimsLocales; String authTransactionId; diff --git a/esignet-core/src/main/java/io/mosip/esignet/core/spi/ConsentService.java b/esignet-core/src/main/java/io/mosip/esignet/core/spi/ConsentService.java index 08d310e7a..029ed6a49 100644 --- a/esignet-core/src/main/java/io/mosip/esignet/core/spi/ConsentService.java +++ b/esignet-core/src/main/java/io/mosip/esignet/core/spi/ConsentService.java @@ -24,4 +24,11 @@ public interface ConsentService { * */ ConsentDetail saveUserConsent(UserConsent userConsent) throws EsignetException; + + /** + * Api to delete user consent from Consent Registry + * @param psuToken + * @param clientId + */ + void deleteUserConsent(String clientId, String psuToken); } diff --git a/esignet-integration-api/src/main/java/io/mosip/esignet/api/util/Action.java b/esignet-integration-api/src/main/java/io/mosip/esignet/api/util/Action.java index e99dbe396..6979351c7 100644 --- a/esignet-integration-api/src/main/java/io/mosip/esignet/api/util/Action.java +++ b/esignet-integration-api/src/main/java/io/mosip/esignet/api/util/Action.java @@ -22,5 +22,6 @@ public enum Action { LINK_SEND_OTP, LINK_AUTH_CODE, GET_USER_CONSENT, - SAVE_USER_CONSENT + SAVE_USER_CONSENT, + UPDATE_USER_CONSENT } diff --git a/oidc-service-impl/src/main/java/io/mosip/esignet/services/AuthorizationServiceImpl.java b/oidc-service-impl/src/main/java/io/mosip/esignet/services/AuthorizationServiceImpl.java index 2c730e87d..5f436f22a 100644 --- a/oidc-service-impl/src/main/java/io/mosip/esignet/services/AuthorizationServiceImpl.java +++ b/oidc-service-impl/src/main/java/io/mosip/esignet/services/AuthorizationServiceImpl.java @@ -29,7 +29,6 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.annotation.Primary; import org.springframework.stereotype.Service; import java.util.*; @@ -114,6 +113,8 @@ public OAuthDetailResponse getOauthDetails(OAuthDetailRequest oauthDetailReqDto) //Cache the transaction OIDCTransaction oidcTransaction = new OIDCTransaction(); + oidcTransaction.setEssentialClaims(oauthDetailResponse.getEssentialClaims()); + oidcTransaction.setVoluntaryClaims(oauthDetailResponse.getVoluntaryClaims()); oidcTransaction.setRedirectUri(oauthDetailReqDto.getRedirectUri()); oidcTransaction.setRelyingPartyId(clientDetailDto.getRpId()); oidcTransaction.setClientId(clientDetailDto.getId()); @@ -224,7 +225,7 @@ public AuthCodeResponse getAuthCode(AuthCodeRequest authCodeRequest) throws Esig transaction.setCodeHash(authorizationHelperService.getKeyHash(authCode)); transaction.setAcceptedClaims(acceptedClaims); transaction.setPermittedScopes(acceptedScopes); - consentHelperService.addUserConsent(transaction, false, null); + consentHelperService.updateUserConsent(transaction, false, null); transaction = cacheUtilService.setAuthCodeGeneratedTransaction(authCodeRequest.getTransactionId(), transaction); auditWrapper.logAudit(Action.GET_AUTH_CODE, ActionStatus.SUCCESS, AuditHelper.buildAuditDto(authCodeRequest.getTransactionId(), transaction), null); diff --git a/oidc-service-impl/src/main/java/io/mosip/esignet/services/ConsentHelperService.java b/oidc-service-impl/src/main/java/io/mosip/esignet/services/ConsentHelperService.java index 75813cada..1e41ec774 100644 --- a/oidc-service-impl/src/main/java/io/mosip/esignet/services/ConsentHelperService.java +++ b/oidc-service-impl/src/main/java/io/mosip/esignet/services/ConsentHelperService.java @@ -8,6 +8,9 @@ import com.fasterxml.jackson.core.JsonProcessingException; import io.mosip.esignet.api.dto.ClaimDetail; import io.mosip.esignet.api.dto.Claims; +import io.mosip.esignet.api.spi.AuditPlugin; +import io.mosip.esignet.api.util.Action; +import io.mosip.esignet.api.util.ActionStatus; import io.mosip.esignet.api.util.ConsentAction; import io.mosip.esignet.core.constants.ErrorConstants; import io.mosip.esignet.core.dto.ConsentDetail; @@ -16,10 +19,12 @@ import io.mosip.esignet.core.dto.UserConsentRequest; import io.mosip.esignet.core.exception.EsignetException; import io.mosip.esignet.core.spi.ConsentService; +import io.mosip.esignet.core.util.AuditHelper; import io.mosip.esignet.core.util.IdentityProviderUtil; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; import java.util.*; import java.util.function.Function; @@ -33,24 +38,44 @@ public class ConsentHelperService { @Autowired private ConsentService consentService; + @Autowired + private AuditPlugin auditWrapper; + public void processConsent(OIDCTransaction transaction, boolean linked) { UserConsentRequest userConsentRequest = new UserConsentRequest(); userConsentRequest.setClientId(transaction.getClientId()); userConsentRequest.setPsuToken(transaction.getPartnerSpecificUserToken()); Optional consent = consentService.getUserConsent(userConsentRequest); - ConsentAction consentAction = consent.isEmpty() ? ConsentAction.CAPTURE : evaluateConsentAction(transaction,consent.get(), linked); + if(CollectionUtils.isEmpty(transaction.getVoluntaryClaims()) + && CollectionUtils.isEmpty(transaction.getEssentialClaims()) + && CollectionUtils.isEmpty(transaction.getRequestedAuthorizeScopes())){ + transaction.setConsentAction(ConsentAction.NOCAPTURE); + transaction.setAcceptedClaims(List.of()); + transaction.setPermittedScopes(List.of()); + } else { + ConsentAction consentAction = consent.isEmpty() ? ConsentAction.CAPTURE : evaluateConsentAction(transaction, consent.get(), linked); - transaction.setConsentAction(consentAction); + transaction.setConsentAction(consentAction); - if(consentAction.equals(ConsentAction.NOCAPTURE)) { - transaction.setAcceptedClaims(consent.get().getAcceptedClaims()); //NOSONAR consent is already evaluated to be not null - transaction.setPermittedScopes(consent.get().getPermittedScopes()); //NOSONAR consent is already evaluated to be not null + if (consentAction.equals(ConsentAction.NOCAPTURE)) { + transaction.setAcceptedClaims(consent.get().getAcceptedClaims()); //NOSONAR consent is already evaluated to be not null + transaction.setPermittedScopes(consent.get().getPermittedScopes()); //NOSONAR consent is already evaluated to be not null + } } } - public void addUserConsent(OIDCTransaction transaction, boolean linked, String signature) { + public void updateUserConsent(OIDCTransaction transaction, boolean linked, String signature) { + if(ConsentAction.NOCAPTURE.equals(transaction.getConsentAction()) + && transaction.getEssentialClaims().isEmpty() + && transaction.getVoluntaryClaims().isEmpty() + && transaction.getRequestedAuthorizeScopes().isEmpty() + ){ + //delete old consent if it exists since this scenario doesn't require capture of consent. + consentService.deleteUserConsent(transaction.getClientId(),transaction.getPartnerSpecificUserToken()); + auditWrapper.logAudit(Action.UPDATE_USER_CONSENT, ActionStatus.SUCCESS, AuditHelper.buildAuditDto(transaction.getAuthTransactionId(),transaction),null); + } if(ConsentAction.CAPTURE.equals(transaction.getConsentAction())){ UserConsent userConsent = new UserConsent(); userConsent.setClientId(transaction.getClientId()); @@ -76,6 +101,7 @@ public void addUserConsent(OIDCTransaction transaction, boolean linked, String s throw new EsignetException(ErrorConstants.INVALID_CLAIM); } consentService.saveUserConsent(userConsent); + auditWrapper.logAudit(Action.UPDATE_USER_CONSENT, ActionStatus.SUCCESS, AuditHelper.buildAuditDto(transaction.getAuthTransactionId(),transaction),null); } } diff --git a/oidc-service-impl/src/main/java/io/mosip/esignet/services/LinkedAuthorizationServiceImpl.java b/oidc-service-impl/src/main/java/io/mosip/esignet/services/LinkedAuthorizationServiceImpl.java index 35b89deb0..1124b3f6a 100644 --- a/oidc-service-impl/src/main/java/io/mosip/esignet/services/LinkedAuthorizationServiceImpl.java +++ b/oidc-service-impl/src/main/java/io/mosip/esignet/services/LinkedAuthorizationServiceImpl.java @@ -25,7 +25,6 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.annotation.Primary; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; import org.springframework.web.context.request.async.DeferredResult; @@ -270,7 +269,7 @@ public LinkedConsentResponse saveConsentV2(LinkedConsentRequestV2 linkedConsentR // cache consent only, auth-code will be generated on link-auth-code-status API call transaction.setAcceptedClaims(linkedConsentRequest.getAcceptedClaims()); transaction.setPermittedScopes(linkedConsentRequest.getPermittedAuthorizeScopes()); - consentHelperService.addUserConsent(transaction, true, linkedConsentRequest.getSignature()); + consentHelperService.updateUserConsent(transaction, true, linkedConsentRequest.getSignature()); cacheUtilService.setLinkedConsentedTransaction(linkedConsentRequest.getLinkedTransactionId(), transaction); //Publish message after successfully saving the consent kafkaHelperService.publish(linkedAuthCodeTopicName, linkedConsentRequest.getLinkedTransactionId()); diff --git a/oidc-service-impl/src/test/java/io/mosip/esignet/services/ConsentHelperServiceTest.java b/oidc-service-impl/src/test/java/io/mosip/esignet/services/ConsentHelperServiceTest.java index 615352753..392699d16 100644 --- a/oidc-service-impl/src/test/java/io/mosip/esignet/services/ConsentHelperServiceTest.java +++ b/oidc-service-impl/src/test/java/io/mosip/esignet/services/ConsentHelperServiceTest.java @@ -9,9 +9,11 @@ import com.fasterxml.jackson.databind.ObjectMapper; import io.mosip.esignet.api.dto.ClaimDetail; import io.mosip.esignet.api.dto.Claims; +import io.mosip.esignet.api.spi.AuditPlugin; import io.mosip.esignet.api.util.ConsentAction; import io.mosip.esignet.core.dto.ConsentDetail; import io.mosip.esignet.core.dto.OIDCTransaction; +import io.mosip.esignet.core.dto.UserConsent; import io.mosip.esignet.core.dto.UserConsentRequest; import io.mosip.esignet.core.spi.ConsentService; import io.mosip.esignet.core.util.KafkaHelperService; @@ -50,13 +52,16 @@ public class ConsentHelperServiceTest { @Autowired ObjectMapper objectMapper; + @Mock + AuditPlugin auditHelper; + @Test public void addUserConsent_withValidLinkedTransaction_thenPass() { OIDCTransaction oidcTransaction = new OIDCTransaction(); oidcTransaction.setAuthTransactionId("123"); - oidcTransaction.setAcceptedClaims(List.of("name","email")); + oidcTransaction.setAcceptedClaims(List.of("name")); oidcTransaction.setPermittedScopes(null); oidcTransaction.setConsentAction(ConsentAction.CAPTURE); @@ -66,13 +71,18 @@ public void addUserConsent_withValidLinkedTransaction_thenPass() ClaimDetail userinfoNameClaimDetail = new ClaimDetail("name", new String[]{"value1a", "value1b"}, true); ClaimDetail idTokenClaimDetail = new ClaimDetail("token", new String[]{"value2a", "value2b"}, false); userinfo.put("name", userinfoNameClaimDetail); - userinfo.put("email",null); id_token.put("idTokenKey", idTokenClaimDetail); claims.setUserinfo(userinfo); claims.setId_token(id_token); oidcTransaction.setRequestedClaims(claims); - consentHelperService.addUserConsent(oidcTransaction, true, null); + consentHelperService.updateUserConsent(oidcTransaction, true, null); + UserConsent userConsent = new UserConsent(); + userConsent.setHash("PxQIckCdFC5TPmL7_G7NH0Zs4UmHC74rGpOkyldqRpg"); + userConsent.setClaims(claims); + userConsent.setAuthorizationScopes(Map.of()); + userConsent.setAcceptedClaims(List.of("name")); + Mockito.verify(consentService).saveUserConsent(userConsent); } @@ -81,7 +91,7 @@ public void addUserConsent_withValidWebTransaction_thenPass() { OIDCTransaction oidcTransaction = new OIDCTransaction(); oidcTransaction.setAuthTransactionId("123"); - oidcTransaction.setAcceptedClaims(List.of("name","email")); + oidcTransaction.setAcceptedClaims(List.of("value1")); oidcTransaction.setPermittedScopes(null); oidcTransaction.setConsentAction(ConsentAction.CAPTURE); @@ -99,7 +109,34 @@ public void addUserConsent_withValidWebTransaction_thenPass() Mockito.when(consentService.saveUserConsent(Mockito.any())).thenReturn(new ConsentDetail()); - consentHelperService.addUserConsent(oidcTransaction, false, ""); + consentHelperService.updateUserConsent(oidcTransaction, false, ""); + UserConsent userConsent = new UserConsent(); + userConsent.setHash("Cgh8oWpNM84WPYQVvluGj616_kd4z60elVXtc7R_lXw"); + userConsent.setClaims(claims); + userConsent.setAuthorizationScopes(Map.of()); + userConsent.setAcceptedClaims(List.of("value1")); + userConsent.setSignature(""); + Mockito.verify(consentService).saveUserConsent(userConsent); + } + + @Test + public void addUserConsent_withValidWebTransactionNoClaimsAndScopes_thenPass() + { + String clientId = "clientId"; + String psuToken = "psuToken"; + OIDCTransaction oidcTransaction = new OIDCTransaction(); + oidcTransaction.setAuthTransactionId("123"); + oidcTransaction.setAcceptedClaims(List.of()); + oidcTransaction.setRequestedAuthorizeScopes(List.of()); + oidcTransaction.setConsentAction(ConsentAction.NOCAPTURE); + oidcTransaction.setVoluntaryClaims(List.of()); + oidcTransaction.setEssentialClaims(List.of()); + oidcTransaction.setAcceptedClaims(List.of()); + oidcTransaction.setPermittedScopes(List.of()); + oidcTransaction.setClientId(clientId); + oidcTransaction.setPartnerSpecificUserToken(psuToken); + consentHelperService.updateUserConsent(oidcTransaction, false, ""); + Mockito.verify(consentService).deleteUserConsent(clientId, psuToken); } @Test @@ -110,6 +147,8 @@ public void processConsent_withValidConsentAndConsentActionAsNoCapture_thenPass( oidcTransaction.setPartnerSpecificUserToken("123"); oidcTransaction.setRequestedAuthorizeScopes(List.of("openid","profile")); oidcTransaction.setPermittedScopes(List.of("openid","profile")); + oidcTransaction.setEssentialClaims(List.of("name")); + oidcTransaction.setVoluntaryClaims(List.of("email")); Claims claims = new Claims(); Map userinfo = new HashMap<>(); @@ -156,7 +195,8 @@ public void processConsent_withValidConsentAndConsentActionAsCapture_thenPass() oidcTransaction.setPartnerSpecificUserToken("123"); oidcTransaction.setRequestedAuthorizeScopes(List.of("openid","profile")); oidcTransaction.setPermittedScopes(List.of("openid","profile")); - + oidcTransaction.setEssentialClaims(List.of("name")); + oidcTransaction.setVoluntaryClaims(List.of("email")); Claims claims = new Claims(); Map userinfo = new HashMap<>(); Map id_token = new HashMap<>(); @@ -207,7 +247,9 @@ public void processConsent_withEmptyConsent_thenPass(){ OIDCTransaction oidcTransaction=new OIDCTransaction(); oidcTransaction.setClientId("abc"); oidcTransaction.setPartnerSpecificUserToken("123"); - + oidcTransaction.setVoluntaryClaims(List.of("email")); + oidcTransaction.setEssentialClaims(List.of()); + oidcTransaction.setRequestedAuthorizeScopes(List.of()); UserConsentRequest userConsentRequest = new UserConsentRequest(); userConsentRequest.setClientId(oidcTransaction.getClientId()); userConsentRequest.setPsuToken(oidcTransaction.getPartnerSpecificUserToken()); @@ -218,4 +260,19 @@ public void processConsent_withEmptyConsent_thenPass(){ Assert.assertEquals(oidcTransaction.getConsentAction(),ConsentAction.CAPTURE); } + + @Test + public void processConsent_withEmptyRequestedClaims_thenPass(){ + OIDCTransaction oidcTransaction=new OIDCTransaction(); + oidcTransaction.setClientId("abc"); + oidcTransaction.setPartnerSpecificUserToken("123"); + oidcTransaction.setVoluntaryClaims(List.of()); + oidcTransaction.setEssentialClaims(List.of()); + oidcTransaction.setRequestedAuthorizeScopes(List.of()); + UserConsentRequest userConsentRequest = new UserConsentRequest(); + userConsentRequest.setClientId(oidcTransaction.getClientId()); + userConsentRequest.setPsuToken(oidcTransaction.getPartnerSpecificUserToken()); + consentHelperService.processConsent(oidcTransaction,true); + Assert.assertEquals(oidcTransaction.getConsentAction(),ConsentAction.NOCAPTURE); + } } \ No newline at end of file From d77d188ec1284fb98ae9e353c4c9d9cfdcce596f Mon Sep 17 00:00:00 2001 From: PRAFUL RAKHADE <99539100+Prafulrakhade@users.noreply.github.com> Date: Mon, 24 Jul 2023 14:01:43 +0530 Subject: [PATCH 51/61] =?UTF-8?q?[DSD-2996]=20updated=20esignet=20captcha?= =?UTF-8?q?=20in=20install.sh=20file=20and=20added=20copy=5F=E2=80=A6=20(#?= =?UTF-8?q?273)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [DSD-2996] updated esignet captcha in install.sh file and added copy_secrets.sh file * [DSD-2996] updated esignet captcha in install.sh file and added copy_secrets.sh file * [DSD-2996] updated esignet captcha in install.sh file and added copy_secrets.sh file * [DSD-2996] updated esignet captcha in install.sh file and added copy_secrets.sh file --- helm/esignet/copy_secrets.sh | 16 ++++++++++++++++ helm/esignet/install.sh | 18 ++++++++++++++++++ 2 files changed, 34 insertions(+) create mode 100755 helm/esignet/copy_secrets.sh diff --git a/helm/esignet/copy_secrets.sh b/helm/esignet/copy_secrets.sh new file mode 100755 index 000000000..4f470a2e4 --- /dev/null +++ b/helm/esignet/copy_secrets.sh @@ -0,0 +1,16 @@ +#!/bin/bash +# Copy secrets from other namespaces +# DST_NS: Destination namespace +function copying_secrets() { + COPY_UTIL=../esignet/copy_cm_func.sh + #DST_NS=esignet + $COPY_UTIL secret esignet-captcha esignet config-server + return 0 +} +# set commands for error handling. +set -e +set -o errexit ## set -e : exit the script if any statement returns a non-true return value +set -o nounset ## set -u : exit the script if you try to use an uninitialised variable +set -o errtrace # trace ERR through 'time command' and other functions +set -o pipefail # trace ERR through pipes +copying_secrets # calling function \ No newline at end of file diff --git a/helm/esignet/install.sh b/helm/esignet/install.sh index 7c20cac41..a6c3ca71e 100755 --- a/helm/esignet/install.sh +++ b/helm/esignet/install.sh @@ -9,6 +9,8 @@ fi NS=esignet CHART_VERSION=1.0.1 +ESIGNET_HOST=$(kubectl get cm global -o jsonpath={.data.mosip-esignet-host}) + echo Create $NS namespace kubectl create ns $NS @@ -17,9 +19,25 @@ function installing_esignet() { ./keycloak-init.sh + echo Please enter the recaptcha admin site key for domain $ESIGNET_HOST + read ESITE_KEY + echo Please enter the recaptcha admin secret key for domain $ESIGNET_HOST + read ESECRET_KEY + + echo Setting up captcha secrets + kubectl -n $NS create secret generic esignet-captcha --from-literal=esignet-captcha-site-key=$ESITE_KEY --from-literal=esignet-captcha-secret-key=$ESECRET_KEY --dry-run=client -o yaml | kubectl apply -f - + echo Copy configmaps ./copy_cm.sh + echo copy secrets + ./copy_secrets.sh + + kubectl -n config-server set env --keys=esignet-captcha-site-key --from secret/esignet-captcha deployment/config-server --prefix=SPRING_CLOUD_CONFIG_SERVER_OVERRIDES_ + kubectl -n config-server set env --keys=esignet-captcha-secret-key --from secret/esignet-captcha deployment/config-server --prefix=SPRING_CLOUD_CONFIG_SERVER_OVERRIDES_ + + kubectl -n config-server get deploy -o name | xargs -n1 -t kubectl -n config-server rollout status + echo "Do you have public domain & valid SSL? (Y/n) " echo "Y: if you have public domain & valid ssl certificate" echo "n: If you don't have a public domain and a valid SSL certificate. Note: It is recommended to use this option only in development environments." From dc160c3c57aff0413377fd5b157f08d83ad73c84 Mon Sep 17 00:00:00 2001 From: ase-101 <> Date: Mon, 24 Jul 2023 14:41:27 +0530 Subject: [PATCH 52/61] Fixed test case failures --- .../java/io/mosip/esignet/services/KeyBindingServiceImpl.java | 3 ++- .../src/test/java/io/mosip/esignet/KeyBindingServiceTest.java | 2 -- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/binding-service-impl/src/main/java/io/mosip/esignet/services/KeyBindingServiceImpl.java b/binding-service-impl/src/main/java/io/mosip/esignet/services/KeyBindingServiceImpl.java index 35e86b877..6f8fd1ec1 100644 --- a/binding-service-impl/src/main/java/io/mosip/esignet/services/KeyBindingServiceImpl.java +++ b/binding-service-impl/src/main/java/io/mosip/esignet/services/KeyBindingServiceImpl.java @@ -93,10 +93,11 @@ private void validateChallengeListAuthFormat(List challengeList){ public WalletBindingResponse bindWallet(WalletBindingRequest walletBindingRequest, Map requestHeaders) throws EsignetException { log.debug("bindWallet :: Request headers >> {}", requestHeaders); validateChallengeListAuthFormat(walletBindingRequest.getChallengeList()); + //Do not store format, only check if the format is supported by the wrapper. if(!keyBindingWrapper.getSupportedChallengeFormats(walletBindingRequest.getAuthFactorType()). contains(walletBindingRequest.getFormat())) - throw new EsignetException(INVALID_CHALLENGE_FORMAT); + throw new EsignetException(INVALID_AUTH_FACTOR_TYPE_OR_CHALLENGE_FORMAT); String publicKey = IdentityProviderUtil.getJWKString(walletBindingRequest.getPublicKey()); KeyBindingResult keyBindingResult; diff --git a/binding-service-impl/src/test/java/io/mosip/esignet/KeyBindingServiceTest.java b/binding-service-impl/src/test/java/io/mosip/esignet/KeyBindingServiceTest.java index 193a7c549..21490d519 100644 --- a/binding-service-impl/src/test/java/io/mosip/esignet/KeyBindingServiceTest.java +++ b/binding-service-impl/src/test/java/io/mosip/esignet/KeyBindingServiceTest.java @@ -231,8 +231,6 @@ public void bindWallet_withInvalidKeyBindingResult_thenFail() throws IOException walletBindingRequest.setPublicKey( (Map) objectMapper.readValue(clientJWK.toJSONString(), HashMap.class)); - when(mockKeyBindingWrapperService.doKeyBinding(Mockito.anyString(), Mockito.any(), Mockito.any(), Mockito.anyString(), Mockito.any())) - .thenReturn(null); try { Assert.assertNotNull(keyBindingService.bindWallet(walletBindingRequest, new HashMap<>())); Assert.fail(); From 7d777c5307a8df64cecfc173561f23b4caf5dd39 Mon Sep 17 00:00:00 2001 From: ase-101 <> Date: Mon, 24 Jul 2023 15:27:24 +0530 Subject: [PATCH 53/61] Added transactionId in OIDC transaction DTO, so that transactionId is always available for auditing --- .../mosip/esignet/core/dto/OIDCTransaction.java | 2 ++ .../java/io/mosip/esignet/api/util/Action.java | 3 ++- .../services/AuthorizationServiceImpl.java | 1 + .../esignet/services/ConsentHelperService.java | 6 ++++-- .../services/LinkedAuthorizationServiceImpl.java | 16 ++++++++-------- .../mosip/esignet/services/OAuthServiceImpl.java | 6 +++--- .../services/OpenIdConnectServiceImpl.java | 4 ++-- 7 files changed, 22 insertions(+), 16 deletions(-) diff --git a/esignet-core/src/main/java/io/mosip/esignet/core/dto/OIDCTransaction.java b/esignet-core/src/main/java/io/mosip/esignet/core/dto/OIDCTransaction.java index 4ede0e067..07e71a30d 100644 --- a/esignet-core/src/main/java/io/mosip/esignet/core/dto/OIDCTransaction.java +++ b/esignet-core/src/main/java/io/mosip/esignet/core/dto/OIDCTransaction.java @@ -17,6 +17,8 @@ @Data public class OIDCTransaction implements Serializable { + String transactionId; + String clientId; String relyingPartyId; String redirectUri; diff --git a/esignet-integration-api/src/main/java/io/mosip/esignet/api/util/Action.java b/esignet-integration-api/src/main/java/io/mosip/esignet/api/util/Action.java index 6979351c7..1ca13f461 100644 --- a/esignet-integration-api/src/main/java/io/mosip/esignet/api/util/Action.java +++ b/esignet-integration-api/src/main/java/io/mosip/esignet/api/util/Action.java @@ -23,5 +23,6 @@ public enum Action { LINK_AUTH_CODE, GET_USER_CONSENT, SAVE_USER_CONSENT, - UPDATE_USER_CONSENT + UPDATE_USER_CONSENT, + DELETE_USER_CONSENT } diff --git a/oidc-service-impl/src/main/java/io/mosip/esignet/services/AuthorizationServiceImpl.java b/oidc-service-impl/src/main/java/io/mosip/esignet/services/AuthorizationServiceImpl.java index 5f436f22a..3cee6f367 100644 --- a/oidc-service-impl/src/main/java/io/mosip/esignet/services/AuthorizationServiceImpl.java +++ b/oidc-service-impl/src/main/java/io/mosip/esignet/services/AuthorizationServiceImpl.java @@ -113,6 +113,7 @@ public OAuthDetailResponse getOauthDetails(OAuthDetailRequest oauthDetailReqDto) //Cache the transaction OIDCTransaction oidcTransaction = new OIDCTransaction(); + oidcTransaction.setTransactionId(transactionId); oidcTransaction.setEssentialClaims(oauthDetailResponse.getEssentialClaims()); oidcTransaction.setVoluntaryClaims(oauthDetailResponse.getVoluntaryClaims()); oidcTransaction.setRedirectUri(oauthDetailReqDto.getRedirectUri()); diff --git a/oidc-service-impl/src/main/java/io/mosip/esignet/services/ConsentHelperService.java b/oidc-service-impl/src/main/java/io/mosip/esignet/services/ConsentHelperService.java index 1e41ec774..3244af552 100644 --- a/oidc-service-impl/src/main/java/io/mosip/esignet/services/ConsentHelperService.java +++ b/oidc-service-impl/src/main/java/io/mosip/esignet/services/ConsentHelperService.java @@ -74,7 +74,7 @@ public void updateUserConsent(OIDCTransaction transaction, boolean linked, Strin ){ //delete old consent if it exists since this scenario doesn't require capture of consent. consentService.deleteUserConsent(transaction.getClientId(),transaction.getPartnerSpecificUserToken()); - auditWrapper.logAudit(Action.UPDATE_USER_CONSENT, ActionStatus.SUCCESS, AuditHelper.buildAuditDto(transaction.getAuthTransactionId(),transaction),null); + auditWrapper.logAudit(Action.DELETE_USER_CONSENT, ActionStatus.SUCCESS, AuditHelper.buildAuditDto(transaction.getTransactionId(),transaction),null); } if(ConsentAction.CAPTURE.equals(transaction.getConsentAction())){ UserConsent userConsent = new UserConsent(); @@ -98,10 +98,11 @@ public void updateUserConsent(OIDCTransaction transaction, boolean linked, Strin try { userConsent.setHash(hashUserConsent(normalizedClaims, authorizeScopes)); } catch (JsonProcessingException e) { + log.error("Failed to hash the user consent", e); throw new EsignetException(ErrorConstants.INVALID_CLAIM); } consentService.saveUserConsent(userConsent); - auditWrapper.logAudit(Action.UPDATE_USER_CONSENT, ActionStatus.SUCCESS, AuditHelper.buildAuditDto(transaction.getAuthTransactionId(),transaction),null); + auditWrapper.logAudit(Action.UPDATE_USER_CONSENT, ActionStatus.SUCCESS, AuditHelper.buildAuditDto(transaction.getTransactionId(),transaction),null); } } @@ -184,6 +185,7 @@ private ConsentAction evaluateConsentAction(OIDCTransaction transaction, Consent normalizedClaims.setId_token(normalizeClaims(transaction.getRequestedClaims().getId_token())); hash = hashUserConsent(normalizedClaims, authorizeScopes); } catch (JsonProcessingException e) { + log.error("Failed to hash the user consent", e); throw new EsignetException(ErrorConstants.INVALID_CLAIM); } return consentDetail.getHash().equals(hash) ? ConsentAction.NOCAPTURE : ConsentAction.CAPTURE; diff --git a/oidc-service-impl/src/main/java/io/mosip/esignet/services/LinkedAuthorizationServiceImpl.java b/oidc-service-impl/src/main/java/io/mosip/esignet/services/LinkedAuthorizationServiceImpl.java index 1124b3f6a..fba03ed7a 100644 --- a/oidc-service-impl/src/main/java/io/mosip/esignet/services/LinkedAuthorizationServiceImpl.java +++ b/oidc-service-impl/src/main/java/io/mosip/esignet/services/LinkedAuthorizationServiceImpl.java @@ -121,7 +121,7 @@ public LinkCodeResponse generateLinkCode(LinkCodeRequest linkCodeRequest) throws linkCodeResponse.setTransactionId(linkCodeRequest.getTransactionId()); linkCodeResponse.setExpireDateTime(expireDateTime == null ? null : expireDateTime.format(DateTimeFormatter.ofPattern(UTC_DATETIME_PATTERN))); - auditWrapper.logAudit(Action.LINK_CODE, ActionStatus.SUCCESS, AuditHelper.buildAuditDto(linkCodeRequest.getTransactionId(), transaction), null); + auditWrapper.logAudit(Action.LINK_CODE, ActionStatus.SUCCESS, AuditHelper.buildAuditDto(transaction.getTransactionId(), transaction), null); return linkCodeResponse; } @@ -161,7 +161,7 @@ public LinkTransactionResponse linkTransaction(LinkTransactionRequest linkTransa //Publish message after successfully linking the transaction kafkaHelperService.publish(linkedSessionTopicName, linkCodeHash); - auditWrapper.logAudit(Action.LINK_TRANSACTION, ActionStatus.SUCCESS, AuditHelper.buildAuditDto(linkTransactionMetadata.getTransactionId(), transaction), null); + auditWrapper.logAudit(Action.LINK_TRANSACTION, ActionStatus.SUCCESS, AuditHelper.buildAuditDto(transaction.getTransactionId(), transaction), null); return linkTransactionResponse; } @@ -176,7 +176,7 @@ public OtpResponse sendOtp(OtpRequest otpRequest) throws EsignetException { otpResponse.setTransactionId(otpRequest.getTransactionId()); otpResponse.setMaskedEmail(sendOtpResult.getMaskedEmail()); otpResponse.setMaskedMobile(sendOtpResult.getMaskedMobile()); - auditWrapper.logAudit(Action.LINK_SEND_OTP, ActionStatus.SUCCESS, AuditHelper.buildAuditDto(otpRequest.getTransactionId(), transaction), null); + auditWrapper.logAudit(Action.LINK_SEND_OTP, ActionStatus.SUCCESS, AuditHelper.buildAuditDto(transaction.getTransactionId(), transaction), null); return otpResponse; } @@ -200,7 +200,7 @@ public LinkedKycAuthResponse authenticateUser(LinkedKycAuthRequest linkedKycAuth cacheUtilService.setLinkedAuthenticatedTransaction(linkedKycAuthRequest.getLinkedTransactionId(), transaction); LinkedKycAuthResponse authRespDto = new LinkedKycAuthResponse(); authRespDto.setLinkedTransactionId(linkedKycAuthRequest.getLinkedTransactionId()); - auditWrapper.logAudit(Action.LINK_AUTHENTICATE, ActionStatus.SUCCESS, AuditHelper.buildAuditDto(null, transaction), null); + auditWrapper.logAudit(Action.LINK_AUTHENTICATE, ActionStatus.SUCCESS, AuditHelper.buildAuditDto(transaction.getTransactionId(), transaction), null); return authRespDto; } @@ -232,7 +232,7 @@ public LinkedKycAuthResponseV2 authenticateUserV2(LinkedKycAuthRequest linkedKyc LinkedKycAuthResponseV2 authRespDto = new LinkedKycAuthResponseV2(); authRespDto.setLinkedTransactionId(linkedKycAuthRequest.getLinkedTransactionId()); authRespDto.setConsentAction(transaction.getConsentAction()); - auditWrapper.logAudit(Action.LINK_AUTHENTICATE, ActionStatus.SUCCESS, AuditHelper.buildAuditDto(null, transaction), null); + auditWrapper.logAudit(Action.LINK_AUTHENTICATE, ActionStatus.SUCCESS, AuditHelper.buildAuditDto(transaction.getTransactionId(), transaction), null); return authRespDto; } @@ -253,7 +253,7 @@ public LinkedConsentResponse saveConsent(LinkedConsentRequest linkedConsentReque LinkedConsentResponse authRespDto = new LinkedConsentResponse(); authRespDto.setLinkedTransactionId(linkedConsentRequest.getLinkedTransactionId()); - auditWrapper.logAudit(Action.SAVE_CONSENT, ActionStatus.SUCCESS, AuditHelper.buildAuditDto(linkedConsentRequest.getLinkedTransactionId(), transaction), null); + auditWrapper.logAudit(Action.SAVE_CONSENT, ActionStatus.SUCCESS, AuditHelper.buildAuditDto(transaction.getTransactionId(), transaction), null); return authRespDto; } @@ -276,7 +276,7 @@ public LinkedConsentResponse saveConsentV2(LinkedConsentRequestV2 linkedConsentR LinkedConsentResponse authRespDto = new LinkedConsentResponse(); authRespDto.setLinkedTransactionId(linkedConsentRequest.getLinkedTransactionId()); - auditWrapper.logAudit(Action.SAVE_CONSENT, ActionStatus.SUCCESS, AuditHelper.buildAuditDto(linkedConsentRequest.getLinkedTransactionId(), transaction), null); + auditWrapper.logAudit(Action.SAVE_CONSENT, ActionStatus.SUCCESS, AuditHelper.buildAuditDto(transaction.getTransactionId(), transaction), null); return authRespDto; } @@ -311,7 +311,7 @@ public void getLinkAuthCode(DeferredResult deferredResult, LinkAuthCodeRequest l OIDCTransaction oidcTransaction = cacheUtilService.getConsentedTransaction(linkTransactionMetadata.getLinkedTransactionId()); if(oidcTransaction != null) { - auditWrapper.logAudit(Action.LINK_AUTH_CODE, ActionStatus.SUCCESS, AuditHelper.buildAuditDto(linkAuthCodeRequest.getTransactionId(), oidcTransaction), null); + auditWrapper.logAudit(Action.LINK_AUTH_CODE, ActionStatus.SUCCESS, AuditHelper.buildAuditDto(oidcTransaction.getTransactionId(), oidcTransaction), null); deferredResult.setResult(authorizationHelperService.getLinkAuthStatusResponse(linkTransactionMetadata.getTransactionId(), oidcTransaction)); } else { authorizationHelperService.addEntryInLinkAuthCodeStatusDeferredResultMap(linkTransactionMetadata.getLinkedTransactionId(), deferredResult); diff --git a/oidc-service-impl/src/main/java/io/mosip/esignet/services/OAuthServiceImpl.java b/oidc-service-impl/src/main/java/io/mosip/esignet/services/OAuthServiceImpl.java index d3672cae0..882fd8f8b 100644 --- a/oidc-service-impl/src/main/java/io/mosip/esignet/services/OAuthServiceImpl.java +++ b/oidc-service-impl/src/main/java/io/mosip/esignet/services/OAuthServiceImpl.java @@ -98,14 +98,14 @@ public TokenResponse getTokens(TokenRequest tokenRequest) throws EsignetExceptio transaction.getClientId(), kycExchangeDto); } catch (KycExchangeException e) { log.error("KYC exchange failed", e); - auditWrapper.logAudit(Action.DO_KYC_EXCHANGE, ActionStatus.ERROR, AuditHelper.buildAuditDto(codeHash, transaction), e); + auditWrapper.logAudit(Action.DO_KYC_EXCHANGE, ActionStatus.ERROR, AuditHelper.buildAuditDto(transaction.getTransactionId(), transaction), e); throw new EsignetException(e.getErrorCode()); } if(kycExchangeResult == null || kycExchangeResult.getEncryptedKyc() == null) throw new EsignetException(DATA_EXCHANGE_FAILED); - auditWrapper.logAudit(Action.DO_KYC_EXCHANGE, ActionStatus.SUCCESS, AuditHelper.buildAuditDto(codeHash, transaction), null); + auditWrapper.logAudit(Action.DO_KYC_EXCHANGE, ActionStatus.SUCCESS, AuditHelper.buildAuditDto(transaction.getTransactionId(), transaction), null); TokenResponse tokenResponse = new TokenResponse(); tokenResponse.setAccess_token(tokenService.getAccessToken(transaction)); @@ -119,7 +119,7 @@ public TokenResponse getTokens(TokenRequest tokenRequest) throws EsignetExceptio transaction.setEncryptedKyc(kycExchangeResult.getEncryptedKyc()); cacheUtilService.setUserInfoTransaction(accessTokenHash, transaction); - auditWrapper.logAudit(Action.GENERATE_TOKEN, ActionStatus.SUCCESS, AuditHelper.buildAuditDto(codeHash, + auditWrapper.logAudit(Action.GENERATE_TOKEN, ActionStatus.SUCCESS, AuditHelper.buildAuditDto(transaction.getTransactionId(), transaction), null); return tokenResponse; } diff --git a/oidc-service-impl/src/main/java/io/mosip/esignet/services/OpenIdConnectServiceImpl.java b/oidc-service-impl/src/main/java/io/mosip/esignet/services/OpenIdConnectServiceImpl.java index fd3278e62..035720487 100644 --- a/oidc-service-impl/src/main/java/io/mosip/esignet/services/OpenIdConnectServiceImpl.java +++ b/oidc-service-impl/src/main/java/io/mosip/esignet/services/OpenIdConnectServiceImpl.java @@ -61,13 +61,13 @@ public String getUserInfo(String accessToken) throws EsignetException { throw new NotAuthenticatedException(); tokenService.verifyAccessToken(transaction.getClientId(), transaction.getPartnerSpecificUserToken(), tokenParts[1]); - auditWrapper.logAudit(Action.GET_USERINFO, ActionStatus.SUCCESS, AuditHelper.buildAuditDto(accessTokenHash, + auditWrapper.logAudit(Action.GET_USERINFO, ActionStatus.SUCCESS, AuditHelper.buildAuditDto(transaction.getTransactionId(), transaction), null); return transaction.getEncryptedKyc(); } catch (EsignetException ex) { auditWrapper.logAudit(Action.GET_USERINFO, ActionStatus.ERROR, AuditHelper.buildAuditDto(accessTokenHash, - transaction), null); + transaction), ex); throw ex; } } From b27b485ee71b4015c059480ec77a3c96d729f97f Mon Sep 17 00:00:00 2001 From: Hitesh Jain Date: Wed, 2 Aug 2023 06:44:35 +0530 Subject: [PATCH 54/61] [BUGFIX] [ES-218] Fixed inconsistency with consent action capture shared for authorize scopes in the workflow --- .github/workflows/push_trigger.yml | 2 +- .../mosip/esignet/services/ConsentHelperService.java | 11 +++++------ .../esignet/services/ConsentHelperServiceTest.java | 2 +- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/.github/workflows/push_trigger.yml b/.github/workflows/push_trigger.yml index dc6d7ae94..a8ad836ed 100644 --- a/.github/workflows/push_trigger.yml +++ b/.github/workflows/push_trigger.yml @@ -10,7 +10,7 @@ on: - 1.* - develop - main - - bugfix-ES-177 + - bugfix-ES-218 jobs: call-workflow-codeql-analysis: diff --git a/oidc-service-impl/src/main/java/io/mosip/esignet/services/ConsentHelperService.java b/oidc-service-impl/src/main/java/io/mosip/esignet/services/ConsentHelperService.java index 3244af552..d6b212c8f 100644 --- a/oidc-service-impl/src/main/java/io/mosip/esignet/services/ConsentHelperService.java +++ b/oidc-service-impl/src/main/java/io/mosip/esignet/services/ConsentHelperService.java @@ -89,9 +89,9 @@ public void updateUserConsent(OIDCTransaction transaction, boolean linked, Strin userConsent.setClaims(normalizedClaims); userConsent.setSignature(signature); List permittedScopes = transaction.getPermittedScopes(); - List authorizeScope = transaction.getRequestedAuthorizeScopes(); - Map authorizeScopes = permittedScopes != null ? permittedScopes.stream() - .collect(Collectors.toMap(Function.identity(), authorizeScope::contains)) : Collections.emptyMap(); + List requestedAuthorizeScopes = transaction.getRequestedAuthorizeScopes(); + Map authorizeScopes = requestedAuthorizeScopes != null ? requestedAuthorizeScopes.stream() + .collect(Collectors.toMap(Function.identity(), s->false)) : Collections.emptyMap(); userConsent.setAuthorizationScopes(authorizeScopes); userConsent.setAcceptedClaims(acceptedClaims); userConsent.setPermittedScopes(permittedScopes); @@ -176,10 +176,9 @@ private static ClaimDetail sortClaimDetail(ClaimDetail claimDetail){ private ConsentAction evaluateConsentAction(OIDCTransaction transaction, ConsentDetail consentDetail, boolean linked) { String hash; try { - List permittedScopes = transaction.getPermittedScopes(); List authorizeScope = transaction.getRequestedAuthorizeScopes(); - Map authorizeScopes = permittedScopes != null ? permittedScopes.stream() - .collect(Collectors.toMap(Function.identity(), authorizeScope::contains)) : Collections.emptyMap(); + Map authorizeScopes = authorizeScope != null ? authorizeScope.stream() + .collect(Collectors.toMap(Function.identity(), s->false)) : Collections.emptyMap(); Claims normalizedClaims = new Claims(); normalizedClaims.setUserinfo(normalizeClaims(transaction.getRequestedClaims().getUserinfo())); normalizedClaims.setId_token(normalizeClaims(transaction.getRequestedClaims().getId_token())); diff --git a/oidc-service-impl/src/test/java/io/mosip/esignet/services/ConsentHelperServiceTest.java b/oidc-service-impl/src/test/java/io/mosip/esignet/services/ConsentHelperServiceTest.java index 392699d16..5d10cfc57 100644 --- a/oidc-service-impl/src/test/java/io/mosip/esignet/services/ConsentHelperServiceTest.java +++ b/oidc-service-impl/src/test/java/io/mosip/esignet/services/ConsentHelperServiceTest.java @@ -170,7 +170,7 @@ public void processConsent_withValidConsentAndConsentActionAsNoCapture_thenPass( ConsentDetail consentDetail = new ConsentDetail(); consentDetail.setClientId("123"); consentDetail.setSignature("signature"); - consentDetail.setAuthorizationScopes(Map.of("openid",true,"profile",true)); + consentDetail.setAuthorizationScopes(Map.of("openid",false,"profile",false)); consentDetail.setClaims(claims); Claims normalizedClaims = new Claims(); normalizedClaims.setUserinfo(consentHelperService.normalizeClaims(claims.getUserinfo())); From 4e7c99cd3a1cbd779306f3c303f1390aeaf838e9 Mon Sep 17 00:00:00 2001 From: Hitesh Jain Date: Wed, 2 Aug 2023 12:31:01 +0530 Subject: [PATCH 55/61] Added documentation --- .../main/java/io/mosip/esignet/entity/ConsentDetail.java | 6 ++++++ db_scripts/mosip_esignet/ddl/esignet-consent.sql | 2 +- db_scripts/mosip_esignet/ddl/esignet-consent_history.sql | 2 +- .../io/mosip/esignet/services/ConsentHelperService.java | 2 ++ 4 files changed, 10 insertions(+), 2 deletions(-) diff --git a/consent-service-impl/src/main/java/io/mosip/esignet/entity/ConsentDetail.java b/consent-service-impl/src/main/java/io/mosip/esignet/entity/ConsentDetail.java index 272562c52..4f0073f51 100644 --- a/consent-service-impl/src/main/java/io/mosip/esignet/entity/ConsentDetail.java +++ b/consent-service-impl/src/main/java/io/mosip/esignet/entity/ConsentDetail.java @@ -38,6 +38,12 @@ public class ConsentDetail { @Column(name = "claims") private String claims; + /* + It stores the requested authorization scopes from the relying party in a json string + { + "scope" : "boolean" (essential or optional) + } + */ @NotNull @Column(name = "authorization_scopes") private String authorizationScopes; diff --git a/db_scripts/mosip_esignet/ddl/esignet-consent.sql b/db_scripts/mosip_esignet/ddl/esignet-consent.sql index ad7873f60..9bd1f8b50 100644 --- a/db_scripts/mosip_esignet/ddl/esignet-consent.sql +++ b/db_scripts/mosip_esignet/ddl/esignet-consent.sql @@ -37,7 +37,7 @@ COMMENT ON COLUMN consent_detail.id IS 'UUID : Unique id associated with each co COMMENT ON COLUMN consent_detail.client_id IS 'Client_id: associated with relying party'; COMMENT ON COLUMN consent_detail.psu_token IS 'PSU token associated with user consent'; COMMENT ON COLUMN consent_detail.claims IS 'Json of requested and user accepted claims'; -COMMENT ON COLUMN consent_detail.authorization_scopes IS 'Json string of user accepted authorization scope'; +COMMENT ON COLUMN consent_detail.authorization_scopes IS 'Json string of requested authorization scope'; COMMENT ON COLUMN consent_detail.cr_dtimes IS 'Consent creation date'; COMMENT ON COLUMN consent_detail.expire_dtimes IS 'Expiration date'; COMMENT ON COLUMN consent_detail.signature IS 'Signature of consent object '; diff --git a/db_scripts/mosip_esignet/ddl/esignet-consent_history.sql b/db_scripts/mosip_esignet/ddl/esignet-consent_history.sql index ef824227a..0d90fa34f 100644 --- a/db_scripts/mosip_esignet/ddl/esignet-consent_history.sql +++ b/db_scripts/mosip_esignet/ddl/esignet-consent_history.sql @@ -35,7 +35,7 @@ COMMENT ON COLUMN consent_history.id IS 'UUID : Unique id associated with each c COMMENT ON COLUMN consent_history.client_id IS 'Client_id: associated with relying party'; COMMENT ON COLUMN consent_history.psu_token IS 'PSU token associated with user consent'; COMMENT ON COLUMN consent_history.claims IS 'Json of requested and user accepted claims'; -COMMENT ON COLUMN consent_history.authorization_scopes IS 'Json string of user accepted authorization scope'; +COMMENT ON COLUMN consent_history.authorization_scopes IS 'Json string of requested authorization scope'; COMMENT ON COLUMN consent_history.cr_dtimes IS 'Consent creation date'; COMMENT ON COLUMN consent_history.expire_dtimes IS 'Expiration date'; COMMENT ON COLUMN consent_history.signature IS 'Signature of consent object '; diff --git a/oidc-service-impl/src/main/java/io/mosip/esignet/services/ConsentHelperService.java b/oidc-service-impl/src/main/java/io/mosip/esignet/services/ConsentHelperService.java index d6b212c8f..a4636a87f 100644 --- a/oidc-service-impl/src/main/java/io/mosip/esignet/services/ConsentHelperService.java +++ b/oidc-service-impl/src/main/java/io/mosip/esignet/services/ConsentHelperService.java @@ -90,6 +90,7 @@ public void updateUserConsent(OIDCTransaction transaction, boolean linked, Strin userConsent.setSignature(signature); List permittedScopes = transaction.getPermittedScopes(); List requestedAuthorizeScopes = transaction.getRequestedAuthorizeScopes(); + // defaulting the essential boolean flag as false Map authorizeScopes = requestedAuthorizeScopes != null ? requestedAuthorizeScopes.stream() .collect(Collectors.toMap(Function.identity(), s->false)) : Collections.emptyMap(); userConsent.setAuthorizationScopes(authorizeScopes); @@ -177,6 +178,7 @@ private ConsentAction evaluateConsentAction(OIDCTransaction transaction, Consent String hash; try { List authorizeScope = transaction.getRequestedAuthorizeScopes(); + // defaulting the essential boolean flag as false Map authorizeScopes = authorizeScope != null ? authorizeScope.stream() .collect(Collectors.toMap(Function.identity(), s->false)) : Collections.emptyMap(); Claims normalizedClaims = new Claims(); From 2ad6580833aa4c289edc915233af8667a14a6b70 Mon Sep 17 00:00:00 2001 From: Hitesh C Date: Wed, 2 Aug 2023 12:33:16 +0530 Subject: [PATCH 56/61] ES-218 (#296) * [BUGFIX] [ES-218] Fixed inconsistency with consent action capture shared for authorize scopes in the workflow * Added documentation --- .github/workflows/push_trigger.yml | 2 +- .../java/io/mosip/esignet/entity/ConsentDetail.java | 6 ++++++ db_scripts/mosip_esignet/ddl/esignet-consent.sql | 2 +- .../mosip_esignet/ddl/esignet-consent_history.sql | 2 +- .../esignet/services/ConsentHelperService.java | 13 +++++++------ .../esignet/services/ConsentHelperServiceTest.java | 2 +- 6 files changed, 17 insertions(+), 10 deletions(-) diff --git a/.github/workflows/push_trigger.yml b/.github/workflows/push_trigger.yml index dc6d7ae94..a8ad836ed 100644 --- a/.github/workflows/push_trigger.yml +++ b/.github/workflows/push_trigger.yml @@ -10,7 +10,7 @@ on: - 1.* - develop - main - - bugfix-ES-177 + - bugfix-ES-218 jobs: call-workflow-codeql-analysis: diff --git a/consent-service-impl/src/main/java/io/mosip/esignet/entity/ConsentDetail.java b/consent-service-impl/src/main/java/io/mosip/esignet/entity/ConsentDetail.java index 272562c52..4f0073f51 100644 --- a/consent-service-impl/src/main/java/io/mosip/esignet/entity/ConsentDetail.java +++ b/consent-service-impl/src/main/java/io/mosip/esignet/entity/ConsentDetail.java @@ -38,6 +38,12 @@ public class ConsentDetail { @Column(name = "claims") private String claims; + /* + It stores the requested authorization scopes from the relying party in a json string + { + "scope" : "boolean" (essential or optional) + } + */ @NotNull @Column(name = "authorization_scopes") private String authorizationScopes; diff --git a/db_scripts/mosip_esignet/ddl/esignet-consent.sql b/db_scripts/mosip_esignet/ddl/esignet-consent.sql index ad7873f60..9bd1f8b50 100644 --- a/db_scripts/mosip_esignet/ddl/esignet-consent.sql +++ b/db_scripts/mosip_esignet/ddl/esignet-consent.sql @@ -37,7 +37,7 @@ COMMENT ON COLUMN consent_detail.id IS 'UUID : Unique id associated with each co COMMENT ON COLUMN consent_detail.client_id IS 'Client_id: associated with relying party'; COMMENT ON COLUMN consent_detail.psu_token IS 'PSU token associated with user consent'; COMMENT ON COLUMN consent_detail.claims IS 'Json of requested and user accepted claims'; -COMMENT ON COLUMN consent_detail.authorization_scopes IS 'Json string of user accepted authorization scope'; +COMMENT ON COLUMN consent_detail.authorization_scopes IS 'Json string of requested authorization scope'; COMMENT ON COLUMN consent_detail.cr_dtimes IS 'Consent creation date'; COMMENT ON COLUMN consent_detail.expire_dtimes IS 'Expiration date'; COMMENT ON COLUMN consent_detail.signature IS 'Signature of consent object '; diff --git a/db_scripts/mosip_esignet/ddl/esignet-consent_history.sql b/db_scripts/mosip_esignet/ddl/esignet-consent_history.sql index ef824227a..0d90fa34f 100644 --- a/db_scripts/mosip_esignet/ddl/esignet-consent_history.sql +++ b/db_scripts/mosip_esignet/ddl/esignet-consent_history.sql @@ -35,7 +35,7 @@ COMMENT ON COLUMN consent_history.id IS 'UUID : Unique id associated with each c COMMENT ON COLUMN consent_history.client_id IS 'Client_id: associated with relying party'; COMMENT ON COLUMN consent_history.psu_token IS 'PSU token associated with user consent'; COMMENT ON COLUMN consent_history.claims IS 'Json of requested and user accepted claims'; -COMMENT ON COLUMN consent_history.authorization_scopes IS 'Json string of user accepted authorization scope'; +COMMENT ON COLUMN consent_history.authorization_scopes IS 'Json string of requested authorization scope'; COMMENT ON COLUMN consent_history.cr_dtimes IS 'Consent creation date'; COMMENT ON COLUMN consent_history.expire_dtimes IS 'Expiration date'; COMMENT ON COLUMN consent_history.signature IS 'Signature of consent object '; diff --git a/oidc-service-impl/src/main/java/io/mosip/esignet/services/ConsentHelperService.java b/oidc-service-impl/src/main/java/io/mosip/esignet/services/ConsentHelperService.java index 3244af552..a4636a87f 100644 --- a/oidc-service-impl/src/main/java/io/mosip/esignet/services/ConsentHelperService.java +++ b/oidc-service-impl/src/main/java/io/mosip/esignet/services/ConsentHelperService.java @@ -89,9 +89,10 @@ public void updateUserConsent(OIDCTransaction transaction, boolean linked, Strin userConsent.setClaims(normalizedClaims); userConsent.setSignature(signature); List permittedScopes = transaction.getPermittedScopes(); - List authorizeScope = transaction.getRequestedAuthorizeScopes(); - Map authorizeScopes = permittedScopes != null ? permittedScopes.stream() - .collect(Collectors.toMap(Function.identity(), authorizeScope::contains)) : Collections.emptyMap(); + List requestedAuthorizeScopes = transaction.getRequestedAuthorizeScopes(); + // defaulting the essential boolean flag as false + Map authorizeScopes = requestedAuthorizeScopes != null ? requestedAuthorizeScopes.stream() + .collect(Collectors.toMap(Function.identity(), s->false)) : Collections.emptyMap(); userConsent.setAuthorizationScopes(authorizeScopes); userConsent.setAcceptedClaims(acceptedClaims); userConsent.setPermittedScopes(permittedScopes); @@ -176,10 +177,10 @@ private static ClaimDetail sortClaimDetail(ClaimDetail claimDetail){ private ConsentAction evaluateConsentAction(OIDCTransaction transaction, ConsentDetail consentDetail, boolean linked) { String hash; try { - List permittedScopes = transaction.getPermittedScopes(); List authorizeScope = transaction.getRequestedAuthorizeScopes(); - Map authorizeScopes = permittedScopes != null ? permittedScopes.stream() - .collect(Collectors.toMap(Function.identity(), authorizeScope::contains)) : Collections.emptyMap(); + // defaulting the essential boolean flag as false + Map authorizeScopes = authorizeScope != null ? authorizeScope.stream() + .collect(Collectors.toMap(Function.identity(), s->false)) : Collections.emptyMap(); Claims normalizedClaims = new Claims(); normalizedClaims.setUserinfo(normalizeClaims(transaction.getRequestedClaims().getUserinfo())); normalizedClaims.setId_token(normalizeClaims(transaction.getRequestedClaims().getId_token())); diff --git a/oidc-service-impl/src/test/java/io/mosip/esignet/services/ConsentHelperServiceTest.java b/oidc-service-impl/src/test/java/io/mosip/esignet/services/ConsentHelperServiceTest.java index 392699d16..5d10cfc57 100644 --- a/oidc-service-impl/src/test/java/io/mosip/esignet/services/ConsentHelperServiceTest.java +++ b/oidc-service-impl/src/test/java/io/mosip/esignet/services/ConsentHelperServiceTest.java @@ -170,7 +170,7 @@ public void processConsent_withValidConsentAndConsentActionAsNoCapture_thenPass( ConsentDetail consentDetail = new ConsentDetail(); consentDetail.setClientId("123"); consentDetail.setSignature("signature"); - consentDetail.setAuthorizationScopes(Map.of("openid",true,"profile",true)); + consentDetail.setAuthorizationScopes(Map.of("openid",false,"profile",false)); consentDetail.setClaims(claims); Claims normalizedClaims = new Claims(); normalizedClaims.setUserinfo(consentHelperService.normalizeClaims(claims.getUserinfo())); From e900a0a11beee8d7690ee86dc3ee45efabfd3855 Mon Sep 17 00:00:00 2001 From: Hitesh Jain Date: Thu, 3 Aug 2023 13:17:01 +0530 Subject: [PATCH 57/61] [BUGFIX] remove consent in linked consent when openid is only the scope --- .../mosip/esignet/services/LinkedAuthorizationServiceImpl.java | 1 + 1 file changed, 1 insertion(+) diff --git a/oidc-service-impl/src/main/java/io/mosip/esignet/services/LinkedAuthorizationServiceImpl.java b/oidc-service-impl/src/main/java/io/mosip/esignet/services/LinkedAuthorizationServiceImpl.java index fba03ed7a..e445a1326 100644 --- a/oidc-service-impl/src/main/java/io/mosip/esignet/services/LinkedAuthorizationServiceImpl.java +++ b/oidc-service-impl/src/main/java/io/mosip/esignet/services/LinkedAuthorizationServiceImpl.java @@ -225,6 +225,7 @@ public LinkedKycAuthResponseV2 authenticateUserV2(LinkedKycAuthRequest linkedKyc if(ConsentAction.NOCAPTURE.equals(transaction.getConsentAction())){ validateConsent(transaction, transaction.getAcceptedClaims(), transaction.getPermittedScopes()); cacheUtilService.setLinkedConsentedTransaction(transaction.getLinkedTransactionId(), transaction); + consentHelperService.updateUserConsent(transaction,true, ""); kafkaHelperService.publish(linkedAuthCodeTopicName, transaction.getLinkedTransactionId()); } else { cacheUtilService.setLinkedAuthenticatedTransaction(linkedKycAuthRequest.getLinkedTransactionId(), transaction); From 9818287e8b3f6f1e8ab9b098f2785d3a3ad5e517 Mon Sep 17 00:00:00 2001 From: Hitesh Jain Date: Thu, 17 Aug 2023 10:50:01 +0530 Subject: [PATCH 58/61] [ADDED] Swagger openapi v1.1.0 yml --- docs/esignet-openapi-1.1.0.yaml | 2777 +++++++++++++++++++++++++++++++ 1 file changed, 2777 insertions(+) create mode 100644 docs/esignet-openapi-1.1.0.yaml diff --git a/docs/esignet-openapi-1.1.0.yaml b/docs/esignet-openapi-1.1.0.yaml new file mode 100644 index 000000000..8b4f6039d --- /dev/null +++ b/docs/esignet-openapi-1.1.0.yaml @@ -0,0 +1,2777 @@ +openapi: 3.1.0 +x-stoplight: + id: 6f1syzijynu40 +info: + title: e-Signet + version: '1.0' + contact: + name: MOSIP Team + email: info@mosip.io + url: 'https://www.mosip.io/' + description: |- + This API document details on the below categories of endpoints +
    +
  • Management - Endpoints for creation and updation of OIDC client details
  • +
  • OIDC - All OIDC compliant endpoints for performing the Open ID Connect flows
  • +
  • UI - All endpoints used by the UI application
  • +
  • Wallet - All endpoints used by the Wallet application
  • +
  • binding-service - All endpoints used by the UI application
  • +
+ + Abbreviations:

+ OIDC - Open ID Connect
+ IdP - Identity provider
+ PMP - Partner Management portal
+ KYC - Know Your Customer
+ IDA - Authentication server
+ UIN - Unique Identification Number
+ VID - Virtual Identifier
+ PSUT - Partner(Relying Party) Specific User Token
+ + + + + license: + name: MPL-2.0 + url: 'https://www.mozilla.org/en-US/MPL/2.0/' + summary: Open ID Connect based identity provider for large scale authentication +servers: + - url: 'https://api.esignet.io/v1/esignet' +paths: + /client-mgmt/oidc-client: + post: + summary: Create OIDC Client Endpoint + operationId: post-client + requestBody: + content: + application/json: + schema: + type: object + description: OIDC client details + properties: + requestTime: + type: string + format: date-time + pattern: '' + description: Current date and time when the request is sent + request: + type: object + required: + - clientId + - clientName + - relyingPartyId + - logoUri + - authContextRefs + - publicKey + - userClaims + - grantTypes + - clientAuthMethods + properties: + clientId: + type: string + description: 'Unique OIDC client id (Case-Sensitive). If duplicates found, request will be rejected.' + example: 785b806d0e594657b05aabdb30fff8a4 + maxLength: 50 + minLength: 1 + clientName: + type: string + minLength: 1 + maxLength: 256 + description: Name of OIDC client. + example: ABC Health Care + relyingPartyId: + type: string + description: |- + Relying Party ID of the client. This will be passed on to authentications servers when KYC is fetched. + + Note: Use the client Id as relyingPartyId if there is no separate concept of relying party in the ID authentication system. + example: bharathi-inc + minLength: 1 + maxLength: 50 + logoUri: + type: string + description: Relying party logo URI which will used to display logo in OIDC login and consent pages. + format: uri + minLength: 1 + maxLength: 1024 + redirectUris: + type: array + description: |- + Valid list of callback Uris of the relying party. + When OIDC authorize API is called, any one Uri from this list should be sent as redirect_uri. authorization_code will be redirected to this Uri on successful authentication. + items: + type: string + authContextRefs: + type: array + description: The Authentication Context Class Reference is case-sensitive string specifying a list of Authentication Context Class values that identifies the Authentication Context Class. Values that the authentication performed satisfied implying a Level Of Assurance. + minItems: 1 + items: + type: string + enum: + - 'mosip:idp:acr:static-code' + - 'mosip:idp:acr:generated-code' + - 'mosip:idp:acr:linked-wallet' + - 'mosip:idp:acr:biometrics' + publicKey: + type: object + description: |- + OIDC client's public key used to verify the client's private_key_jwt when OIDC token endpoint is invoked. + This field will not be allowed to udpate later, if the private key is compromised, then new OIDC client to be created. + Format : Json Web Key (JWK). + userClaims: + type: array + description: 'Allowed user info claims, that can be requested by OIDC client in the authorize API' + minItems: 1 + items: + type: string + enum: + - name + - given_name + - middle_name + - preferred_username + - nickname + - gender + - birthdate + - email + - phone_number + - picture + - address + grantTypes: + type: array + description: Form of Authorization Grant presented to token endpoint + minItems: 1 + uniqueItems: true + items: + type: string + enum: + - authorization_code + clientAuthMethods: + type: array + description: Auth method supported for token endpoint. At present only "private_key_jwt" is supported. + minItems: 1 + items: + type: string + enum: + - private_key_jwt + required: + - requestTime + - request + examples: + example-1: + value: + requestTime: '2011-10-05T14:48:00.000Z' + request: + clientId: e-health-service + clientName: Health Service + relyingPartyId: bharath-gov + logoUri: 'http://example.com' + publicKey: {} + authContextRefs: + - 'mosip:idp:acr:static-code' + userClaims: + - name + grantTypes: + - authorization_code + clientAuthMethods: + - private_key_jwt + description: '' + description: |- + API to add new open ID connect (OIDC) clients, it can be invoked by other modules which manages the relying parties / partners. + + Each relying party can associate to one or multiple OIDC client ids. + + On create, OIDC client status will be by default set to "**active**". + x-internal: false + responses: + '200': + description: OK + content: + application/json: + schema: + type: object + properties: + responseTime: + type: string + description: ate and time when the response is generated + response: + type: object + properties: + clientId: + type: string + description: Client id as provided in the request. + errors: + type: array + items: + type: object + additionalProperties: false + properties: + errorCode: + type: string + enum: + - duplicate_client_id + - invalid_public_key + - invalid_input + - invalid_client_id + - invalid_client_name + - invalid_rp_id + - invalid_claim + - invalid_acr + - invalid_uri + - invalid_redirect_uri + - invalid_grant_type + - invalid_client_auth + errorMessage: + type: string + '401': + description: Unauthorized + tags: + - Management + parameters: [] + security: + - Authorization-add_oidc_client: [] + parameters: [] + '/client-mgmt/oidc-client/{client_id}': + parameters: + - schema: + type: string + example: 785b806d0e594657b05aabdb30fff8a4 + name: client_id + in: path + required: true + description: Client Identifier + put: + summary: Update OIDC Client Endpoint + operationId: put-oidc-client-client_id + responses: + '200': + description: OK + content: + application/json: + schema: + type: object + properties: + responseTime: + type: string + description: Date and time when the response is generated + response: + type: object + properties: + clientId: + type: string + description: OIDC client identifier. + required: + - clientId + errors: + type: array + description: 'List of Errors in case of request validation / processing failure in Idp server. When request processing is fully successful, this array will be empty.' + items: + type: object + properties: + errorCode: + type: string + enum: + - invalid_client_id + - invalid_client_name + - invalid_claim + - invalid_acr + - invalid_uri + - invalid_redirect_uri + - invalid_grant_type + - invalid_client_auth + errorMessage: + type: string + description: |- + API to update existing Open ID Connect (OIDC) client, it can be invoked by other modules which manages the relying parties / partners when there any updates on the fields accepted in this API. + + **Authentication and authorization** is based on a valid JWT issued by a trusted IAM system including "**update_oidc_client**" scope. + requestBody: + content: + application/json: + schema: + type: object + properties: + requestTime: + type: string + pattern: '' + description: Current date and time when the request is sent + request: + type: object + required: + - clientName + - status + - logoUri + - redirectUris + - userClaims + - authContextRefs + - grantTypes + - clientAuthMethods + properties: + clientName: + type: string + description: Name of the OIDC client. + minLength: 1 + maxLength: 256 + example: ABC Health Care + status: + type: string + enum: + - active + - inactive + description: Status of OIDC client. + logoUri: + type: string + description: Relying party logo URI which will used to display logo in OIDC login and consent pages. + format: uri + minLength: 1 + maxLength: 1024 + redirectUris: + type: array + description: 'Valid list of callback Uris of the relying party. When OIDC authorize API is called, any one Uri from this list should be sent as redirect_uri. authorization_code will be redirected to this Uri on successful authentication.' + minItems: 1 + uniqueItems: true + items: + type: string + format: uri + userClaims: + type: array + description: 'Allowed user info claims, that can be requested by OIDC client in the authorize API' + minItems: 1 + items: + type: string + enum: + - name + - given_name + - middle_name + - preferred_username + - nickname + - gender + - birthdate + - email + - phone_number + - picture + - address + authContextRefs: + type: array + description: The Authentication Context Class Reference is case-sensitive string specifying a list of Authentication Context Class values that identifies the Authentication Context Class. Values that the authentication performed satisfied implying a Level Of Assurance. + minItems: 1 + uniqueItems: true + items: + type: string + enum: + - 'mosip:idp:acr:static-code' + - 'mosip:idp:acr:generated-code' + - 'mosip:idp:acr:linked-wallet' + - 'mosip:idp:acr:biometrics' + grantTypes: + type: array + description: Form of Authorization Grant presented to token endpoint. + minItems: 1 + items: + type: string + enum: + - authorization_code + clientAuthMethods: + type: array + description: Auth method supported for token endpoint. At present only "private_key_jwt" is supported. + minItems: 1 + items: + type: string + enum: + - private_key_jwt + required: + - requestTime + - request + examples: + example-1: + value: + requestTime: '2022-09-22T08:03:45.000Z' + request: + clientName: Health Service + status: active + logoUri: 'http://example.com' + redirectUris: + - 'http://example.com' + userClaims: + - name + authContextRefs: + - 'mosip:idp:acr:static-code' + grantTypes: + - authorization_code + clientAuthMethods: + - private_key_jwt + description: '' + tags: + - Management + security: + - Authorization-update_oidc_client: [] + /authorize: + get: + summary: Authorization Endpoint + operationId: get-authorize + description: |- + This is the authorize endpoint of Open ID Connect (OIDC). The relying party applications will do a browser redirect to this endpoint with all required details passed as query parameters. + + This endpoint will respond with a basic HTML page to load a JS application in the browser. UI JS application will then echo all the query parameters received in this endpoint to the "/authorization/oauth-details" endpoint as the request body. + + All the validations on the query parameter values will be performed in the "/authorization/oauth-details" endpoint. + + **Authentication & Authroization**: None + parameters: + - schema: + type: string + default: openid profile + enum: + - openid profile + - openid + - profile + - email + - address + - phone + - offline_access + in: query + name: scope + description: Specifies what access privileges are being requested for Access Tokens. The scopes associated with Access Tokens determine what resources will be available when they are used to access OAuth 2.0 protected endpoints. OpenID Connect requests MUST contain the OpenID scope value. + required: true + - schema: + type: string + enum: + - code + in: query + name: response_type + description: 'The value set here determines the authorization processing flow. To use the Authorization Code Flow, the value should be configured to "code".' + required: true + - schema: + type: string + maxLength: 256 + in: query + name: client_id + required: true + description: Valid OAuth 2.0 Client Identifier in the Authorization Server. + - schema: + type: string + format: uri + in: query + name: redirect_uri + description: Redirection URI to which the response would be sent. This URI must match one of the redirection URI values during the client ID creation. + required: true + - schema: + type: string + maxLength: 256 + in: query + description: 'Opaque value used to maintain state between the request and the callback. Typically, Cross-Site Request Forgery (CSRF, XSRF) mitigation is done by cryptographically binding the value of this parameter with a browser cookie.' + name: state + - schema: + type: string + in: query + description: 'String value used to associate a Client session with an ID Token, and to mitigate replay attacks. The value is passed through unmodified from the Authentication Request to the ID Token.' + name: nonce + - schema: + type: string + enum: + - page + - popup + - touch + - wap + in: query + name: display + description: ASCII string value that specifies how the Authorization Server displays the authentication and consent user interface pages to the end user. + - schema: + type: string + enum: + - none + - login + - consent + - select_account + example: consent + in: query + name: prompt + description: Space delimited case-sensitive list of ASCII string values that specifies whether the Authorization Server prompts the End-User for re-authentication and consent. + - schema: + type: number + in: query + name: max_age + description: 'Maximum Authentication Age. This specifies the allowable elapsed time in seconds since the last time the end user was actively authenticated by the OP. If the elapsed time is greater than this value, then the OP MUST attempt to actively re-authenticate the end user. The max_age request parameter corresponds to the OpenID 2.0 PAPE [OpenID.PAPE] max_auth_age request parameter. When max_age is used, the ID Token returned MUST include an auth_time claim value.' + - schema: + type: string + in: query + name: ui_locales + description: 'End user''s preferred languages and scripts for the user interface, represented as a space-separated list of BCP47 [RFC5646] language tag values, ordered by preference. For instance, the value "fr-CA fr en" represents a preference for French as spoken in Canada, then French (without a region designation), followed by English (without a region designation). An error SHOULD NOT result if some or all of the requested locales are not supported by the OpenID Provider.' + - schema: + type: string + in: query + name: acr_values + description: 'Requested Authentication Context Class Reference values. Space-separated string that specifies the acr values that the Authorization Server is being requested to use for processing this Authentication Request, with the values appearing in order of preference. The Authentication Context Class satisfied by the authentication performed is returned as the acr Claim Value, as specified in Section 2. The acr Claim is requested as a Voluntary Claim by this parameter.' + - schema: + type: string + in: query + name: claims_locales + description: 'End-User''s preferred languages and scripts for Claims being returned, represented as a space-separated list of BCP47 [RFC5646] language tag values, ordered by preference. An error SHOULD NOT result if some or all of the requested locales are not supported by the OpenID Provider.' + - schema: + type: string + in: query + name: claims + description: This parameter is used to request specific claims to be returned. The value is a JSON object listing the requested claims. The claims parameter value is represented in an OAuth 2.0 request as UTF-8 encoded JSON. + responses: + '200': + description: |- + OK + + Loads JS application, and validates the provided query parameters using oauth-details endpoint. + tags: + - OIDC + parameters: [] + /authorization/oauth-details: + post: + summary: OAuth Details Endpoint + operationId: post-oauth-details + responses: + '200': + description: OK + content: + application/json: + schema: + type: object + properties: + responseTime: + type: string + response: + type: object + properties: + transactionId: + type: string + description: This value is passed through unmodified from the /oauth-details request to the /auth-code request. + authFactors: + description: |- + Auth factors defines the authentication screens displayed in IDP frontend. + More than one authFactor may be resolved or combination of auth factors. + Precedence of authFactors is based on its order + type: array + items: + type: array + items: + $ref: '#/components/schemas/AuthFactor' + essentialClaims: + type: array + description: Array holds all the requested essential claims. + items: + type: string + voluntaryClaims: + type: array + description: Array holds all the requested optional claims. + items: + type: string + authorizeScopes: + type: array + description: Scopes to be permitted by the end user. + items: + type: string + configs: + type: object + description: UI configuration key-value pairs. + clientName: + type: string + description: OIDC client name as registered. + logoUrl: + type: string + description: Registered OIDC client logo URL. + required: + - transactionId + - authFactors + - essentialClaims + errors: + type: + - array + - 'null' + description: List of errors in case of request validation / processing failure in Idp server. + items: + type: object + properties: + errorCode: + type: string + enum: + - invalid_client_id + - invalid_redirect_uri + - invalid_scope + - no_acr_registered + - invalid_response_type + - invalid_display + - invalid_prompt + errorMessage: + type: string + examples: + example-1: + value: + responseTime: '2022-09-22T08:03:45.287Z' + response: + transactionId: vKb8cVbq9PX_yt46_hX0xlBJNExl9cnYtL8kGRxU5OM + clientName: Health service OIDC Client + logoUrl: 'https://health-services.com/logo.png' + authFactors: + - - type: PIN + count: 0 + subTypes: null + authorizeScopes: [] + essentialClaims: + - given_name + - email + voluntaryClaims: + - birthdate + - gender + - phone + configs: + sbi.env: Staging + sbi.threshold.face: 40 + sbi.threshold.finger: 40 + sbi.threshold.iris: 40 + errors: null + description: | + OAuth details request is raised from the UI JS application on page load. + + OAuth details endpoint validates the provided request parameters and resolves the required authentication factors. Combination of resolved authentication factors and the consent details are sent back as response with a unique transactionId. + + The transcationId in the response is used to identify/maintain the end user pre-auth session. This pre-auth session has timeout (configurable in Idp service). + + All the query params passed to /authorize API MUST be sent to /oauth-details endpoint. All these parameters will be validated in IdP before returning success response. + + 1. Validates the clientId. + 2. validates redirectUri is one of the redirectUri during client create/update. + 3. validates display,responseType,prompts values are part of supported values in Idp properties. + 4. scope / acrValues / claims / locales / claim_locales - unknown values are ignored. Only valid values are considered. + 5. scopes like profile, email and phone are allowed only if "openid" is also part of the requested scope. + 6. Claims request parameter is allowed, only if 'openid' is part of the scope request parameter + 7. claims considered only if part of registered claims. + 8. ACR in claims request parameter is given the first priority over acr_values query parameter. if none of them are part of the registered acrs, registered ACRs are only considered to derive the auth factors. + requestBody: + content: + application/json: + schema: + type: object + properties: + requestTime: + type: string + pattern: '' + request: + type: object + required: + - scope + - responseType + - clientId + - redirectUri + properties: + scope: + type: string + description: Specifies what access privileges are being requested for Access Tokens. The scopes associated with Access Tokens determine what resources will be available when they are used to access OAuth 2.0 protected endpoints. OpenID Connect requests MUST contain the OpenID scope value. + responseType: + type: string + description: 'Value that determines the authorization processing flow to be used. When using the Authorization Code Flow, this value is code.' + clientId: + type: string + description: OAuth 2.0 Client Identifier valid at the Authorization Server + redirectUri: + type: string + description: Redirection URI to which the response will be sent. This URI MUST exactly match one of the Redirection URI values for the Client pre-registered + state: + type: string + description: client state value echoed. + nonce: + type: string + description: Client's nonce value echoed. + display: + type: string + description: ASCII string value that specifies how the Authorization Server displays the authentication and consent user interface pages to the End-User. + prompt: + type: string + description: 'Space delimited, case sensitive list of ASCII string values that specifies whether the Authorization Server prompts the End-User for re-authentication and consent.' + acrValues: + type: string + description: |- + Space separated ACR values, Unknown ACR are ignored. Only registered ACR values will be considered. + if none of the provided acr value is among the registered values, Error response is returned with error code "invalid_acr". + claims: + $ref: '#/components/schemas/Claim' + maxAge: + type: number + description: 'Maximum Authentication Age. Specifies the allowable elapsed time in seconds since the last time the End-User was actively authenticated by the OP. If the elapsed time is greater than this value, the OP MUST attempt to actively re-authenticate the End-User. (The max_age request parameter corresponds to the OpenID 2.0 PAPE [OpenID.PAPE] max_auth_age request parameter.) When max_age is used, the ID Token returned MUST include an auth_time Claim Value.' + claimsLocales: + type: string + description: 'End-User''s preferred languages and scripts for Claims being returned, represented as a space-separated list of BCP47 [RFC5646] language tag values, ordered by preference. An error SHOULD NOT result if some or all of the requested locales are not supported by the OpenID Provider.' + uiLocales: + type: string + description: 'End-User''s preferred languages and scripts for the user interface, represented as a space-separated list of BCP47 [RFC5646] language tag values, ordered by preference. For instance, the value "fr-CA fr en" represents a preference for French as spoken in Canada, then French (without a region designation), followed by English (without a region designation). An error SHOULD NOT result if some or all of the requested locales are not supported by the OpenID Provider.' + required: + - requestTime + - request + examples: + example-1: + value: + requestTime: '2022-09-22T08:01:10.000Z' + request: + clientId: healthservicev1 + scope: openid resident-service profile + responseType: code + redirectUri: 'http://health-services.com/userprofile' + display: popup + prompt: login + acrValues: 'mosip:idp:acr:static-code mosip:idp:acr:generated-code' + claims: + userinfo: + given_name: + essential: true + phone: null + email: + essential: true + picture: + essential: false + gender: + essential: false + id_token: {} + nonce: 973eieljzng + state: eree2311 + claimsLocales: en + parameters: + - schema: + type: string + in: header + name: X-XSRF-TOKEN + description: CSRF token as set in cookie key 'XSRF-TOKEN' + required: true + tags: + - UI + parameters: [] + /authorization/send-otp: + post: + summary: Send OTP Endpoint + operationId: post-send-otp + responses: + '200': + description: OK + content: + application/json: + schema: + type: object + properties: + responseTime: + type: string + response: + type: object + description: 'Successful message, or null if failed to deliver OTP.' + properties: + transactionId: + type: string + description: oauth-details transactionId is used until the /token call. + maskedEmail: + type: string + description: Masked email id to which generated OTP was mailed. + maskedMobile: + type: string + description: Masked phone number to which generated OTP was messaged. + errors: + type: array + description: 'List of Errors in case of request validation / processing failure in Idp server. if failure from IDA, the same error is relayed in this response.' + items: + type: object + properties: + errorCode: + type: string + enum: + - invalid_transaction + - invalid_transaction_id + - invalid_identifier + - invalid_otp_channel + - invalid_captcha + - send_otp_failed + - unknown_error + errorMessage: + type: string + description: |- + When end user want to authenticate using OTP auth factor, he/she will enter their individual id (UIN/VID) and click on the "Generate OTP" button on the UI application. Then this endpoint will be invoked by the JS UI application. + + Since the OTP generation and delivery to end user is to be handled by the integrated authentication system, the request will be relayed to the same. + + 1. Validates the transactionId. + 2. Validates null / empty individualId. + 3. Validates captchaToken, if enabled. + 3. Delegates the call to integrated authentication system. + 4. Relays error from authentication system to UI on failure. + requestBody: + content: + application/json: + schema: + type: object + properties: + requestTime: + type: string + pattern: 'yyyy-MM-dd''T''HH:mm:ss.SSS''Z''' + request: + type: object + required: + - transactionId + - individualId + - otpChannels + properties: + transactionId: + type: string + description: oauth-details transactionId is used until the /token call. + individualId: + type: string + description: Actual UIN or VID value of the authenticating the end user. + otpChannels: + type: array + enum: + - email + - sms + description: Channel to be used to deliver request OTP. + minItems: 1 + uniqueItems: true + items: + type: string + enum: + - sms + - email + captchaToken: + type: string + description: 'Captcha token, if enabled.' + required: + - requestTime + - request + description: '' + parameters: + - schema: + type: string + in: header + name: oauth-details-hash + description: Base64 encoded SHA-256 hash of the oauth-details endpoint response. + required: true + - schema: + type: string + in: header + name: oauth-details-key + description: Transaction Id + required: true + - schema: + type: string + in: header + name: X-XSRF-TOKEN + description: CSRF token as set in cookie key 'XSRF-TOKEN' + required: true + tags: + - UI + parameters: [] + /linked-authorization/send-otp: + post: + summary: Link authorization Send OTP Endpoint + operationId: post-send-linked-otp + responses: + '200': + description: OK + content: + application/json: + schema: + type: object + properties: + responseTime: + type: string + response: + type: object + description: 'Successful message, or null if failed to deliver OTP.' + properties: + transactionId: + type: string + description: oauth-details transactionId is used until the /token call. + maskedEmail: + type: string + description: Masked email id to which generated OTP was mailed. + maskedMobile: + type: string + description: Masked phone number to which generated OTP was messaged. + errors: + type: array + description: 'List of Errors in case of request validation / processing failure in Idp server. if failure from IDA, the same error is relayed in this response.' + items: + type: object + properties: + errorCode: + type: string + enum: + - invalid_transaction + - invalid_transaction_id + - invalid_identifier + - invalid_otp_channel + - send_otp_failed + - unknown_error + errorMessage: + type: string + description: |- + When end user want to authenticate using OTP auth factor, he/she will enter their individual id (UIN/VID) and click on the "Generate OTP" button on the UI application. Then this endpoint will be invoked by wallet app with linked transactionId. + + Since the OTP generation and delivery to end user is to be handled by the integrated authentication system, the request will be relayed to the same. + + 1. Validates the linked transactionId. + 2. Validates null / empty individualId. + 3. Delegates the call to integrated authentication system. + 4. Relays error from authentication system to UI on failure. + requestBody: + content: + application/json: + schema: + type: object + properties: + requestTime: + type: string + pattern: 'yyyy-MM-dd''T''HH:mm:ss.SSS''Z''' + request: + type: object + required: + - transactionId + - individualId + - otpChannels + properties: + transactionId: + type: string + description: oauth-details transactionId is used until the /token call. + individualId: + type: string + description: Actual UIN or VID value of the authenticating the end user. + otpChannels: + type: array + enum: + - email + - sms + description: Channel to be used to deliver request OTP. + minItems: 1 + uniqueItems: true + items: + type: string + enum: + - sms + - email + required: + - requestTime + - request + description: '' + parameters: [] + tags: + - UI + parameters: [] + /authorization/authenticate: + post: + summary: Authentication Endpoint + operationId: post-authenticate + responses: + '200': + description: OK + content: + application/json: + schema: + type: object + properties: + responseTime: + type: string + response: + type: object + properties: + transactionId: + type: string + description: This is the same transactionId sent in the oauth-details response. + errors: + type: array + description: List of Errors in case of request validation / processing failure in Idp server. + items: + type: object + properties: + errorCode: + type: string + enum: + - invalid_transaction + - invalid_identifier + - invalid_no_of_challenges + - auth_failed + - unknown_error + errorMessage: + type: string + requestBody: + content: + application/json: + schema: + type: object + properties: + requestTime: + type: string + pattern: 'yyyy-MM-dd''T''HH:mm:ss.SSS''Z''' + request: + type: object + required: + - transactionId + - individualId + - challengeList + properties: + transactionId: + type: string + description: This is the same transactionId sent in the oauth-details response. + individualId: + type: string + description: ' User identifier (UIN/VID).' + challengeList: + type: array + description: Authentication Challenge. + items: + $ref: '#/components/schemas/AuthChallenge' + required: + - requestTime + - request + description: '' + description: |- + Once end user provides the user identifier (UIN/VID) and all the required auth challenge to the UI application, this endpoint will be invoked. + + Supported auth-challenge depends on the integrated authentication server. + + 1. Validates transactionId/linkTransactionId. + 2. Validates null / empty individualId. + 3. Invokes kyc-auth call to integrated authentication server (IDA). + 4. Relays error from integrated authentication server to UI on failure. + + On Authentication Success: Only transaction Id is returned in the below response without any errors. + + On Authentication Failure: Error list will be set with the errors returned from the integrated authentication server. + parameters: + - schema: + type: string + in: header + name: oauth-details-hash + description: Base64 encoded SHA-256 hash of the oauth-details endpoint response. + required: true + - schema: + type: string + in: header + name: oauth-details-key + description: Transaction ID + required: true + - schema: + type: string + in: header + name: X-XSRF-TOKEN + description: CSRF token as set in cookie key 'XSRF-TOKEN' + required: true + tags: + - UI + - WALLET + parameters: [] + /authorization/v2/authenticate: + post: + summary: Authentication Endpoint V2 + operationId: post-authenticate-v2 + responses: + '200': + description: OK + content: + application/json: + schema: + type: object + properties: + responseTime: + type: string + response: + type: object + properties: + transactionId: + type: string + description: This is the same transactionId sent in the oauth-details response. + consentAction: + type: string + x-stoplight: + id: gq30p6w6eprol + enum: + - CAPTURE + - NOCAPTURE + description: | + This field indicates the need to capture user consent or not + errors: + type: array + description: List of Errors in case of request validation / processing failure in Idp server. + items: + type: object + properties: + errorCode: + type: string + enum: + - invalid_transaction + - invalid_identifier + - invalid_no_of_challenges + - auth_failed + - unknown_error + errorMessage: + type: string + requestBody: + content: + application/json: + schema: + type: object + properties: + requestTime: + type: string + pattern: 'yyyy-MM-dd''T''HH:mm:ss.SSS''Z''' + request: + type: object + required: + - transactionId + - individualId + - challengeList + properties: + transactionId: + type: string + description: This is the same transactionId sent in the oauth-details response. + individualId: + type: string + description: ' User identifier (UIN/VID).' + challengeList: + type: array + description: Authentication Challenge. + items: + $ref: '#/components/schemas/AuthChallenge' + required: + - requestTime + - request + description: '' + description: |- + Once end user provides the user identifier (UIN/VID) and all the required auth challenge to the UI application, this endpoint will be invoked. + + Supported auth-challenge depends on the integrated authentication server. + + 1. Validates transactionId/linkTransactionId. + 2. Validates null / empty individualId. + 3. Invokes kyc-auth call to integrated authentication server (IDA). + 4. It validates stored userconsent against the requested claims and scopes + 5. Relays error from integrated authentication server to UI on failure. + + On Authentication Success: transaction Id and consentAction is returned in the below response without any errors. + + On Authentication Failure: Error list will be set with the errors returned from the integrated authentication server. + parameters: + - schema: + type: string + in: header + name: oauth-details-hash + description: Base64 encoded SHA-256 hash of the oauth-details endpoint response. + required: true + - schema: + type: string + in: header + name: oauth-details-key + description: Transaction ID + required: true + - schema: + type: string + in: header + name: X-XSRF-TOKEN + description: CSRF token as set in cookie key 'XSRF-TOKEN' + required: true + tags: + - UI + - WALLET + parameters: [] + /authorization/auth-code: + post: + summary: Authorization Code Endpoint + operationId: post-auth-code + description: |- + Once the authentication is successful and user consent is obtained, this endpoint will be invoked by the UI application to send the accepted consent and permitted scopes. + + Then UI application will receive the authorization code and few other details required for redirecting to the client / relying party application. + + 1. Validates transactionId. If valid, stores the accepted claims and permitted scopes in the cache and returns back the authorization code. + 2. Validate accepted claims and permitted scopes in the request. + requestBody: + content: + application/json: + schema: + type: object + properties: + requestTime: + type: string + pattern: 'yyyy-MM-dd''T''HH:mm:ss.SSS''Z''' + request: + type: object + required: + - transactionId + properties: + transactionId: + type: string + description: Transaction id echoed starting from /authorize call. + permittedAuthorizeScopes: + type: array + description: List of permitted scopes by end-user. + items: + type: string + acceptedClaims: + type: array + description: List of accepted essential and voluntary claims by end-user. + items: + type: string + required: + - requestTime + - request + parameters: + - schema: + type: string + in: header + name: oauth-details-hash + description: Base64 encoded SHA-256 hash of the oauth-details endpoint response. + required: true + - schema: + type: string + in: header + name: oauth-details-key + description: Transaction Id + required: true + - schema: + type: string + in: header + name: X-XSRF-TOKEN + description: CSRF token as set in cookie key 'XSRF-TOKEN' + required: true + responses: + '200': + description: OK + content: + application/json: + schema: + type: object + properties: + responseTime: + type: string + response: + type: object + properties: + code: + type: string + description: Authorization code. Required to obtain the ID token and / or access token from the /token endpoint. + redirectUri: + type: string + description: Client's validated redirect URI. + nonce: + type: string + description: 'The echoed nonce value, if one was passed with the request. Clients must validate the value before proceeding.' + state: + type: string + description: 'The echoed state value, used to maintain state between the request and the callback.' + errors: + type: array + items: + type: object + properties: + errorCode: + type: string + enum: + - invalid_transaction_id + - invalid_transaction + - invalid_accepted_claim + - invalid_permitted_scope + errorMessage: + type: string + tags: + - UI + - WALLET + parameters: [] + /linked-authorization/link-code: + post: + summary: Generate Link Code endpoint + tags: + - UI + responses: + '200': + description: OK + content: + application/json: + schema: + type: object + properties: + responseTime: + type: string + response: + type: object + properties: + transactionId: + type: string + description: TransactionId same the one passed in the request. + linkCode: + type: string + description: Unique random string mapped to this transactionId. + expireDateTime: + type: string + description: Expire date time (ISO format) for the generated linkCode. After this date time linkCode in this request is not valid. + errors: + type: array + items: + type: object + properties: + errorCode: + type: string + enum: + - invalid_transaction_id + - link_code_gen_failed + - invalid_transaction + errorMessage: + type: string + operationId: get-authorization-generate-link-code + description: |- + Generate link code request is raised from JS application. + + 1. JS application creates a deeplink with this link-code as parameter. + 2. This deeplink is embedded in a Machine-readable-code and the same is rendered in the UI. + 3. End user scans this machine-readable-code to open wallet app. + 4. On open of wallet-app, wallet-app invokes /link-transaction endpoint. + 5. In the JS application, once machine-readable-code is rendered, at the same time /link-status endpoint is invoked as a polling request. + + **Configuration to decide the expire date time of linkCode**: mosip.idp.link-code-expire-in-secs + requestBody: + content: + application/json: + schema: + type: object + properties: + requestTime: + type: string + request: + type: object + required: + - transactionId + properties: + transactionId: + type: string + description: TransactionId returned in the oauth-details response. + required: + - requestTime + - request + parameters: + - schema: + type: string + in: header + name: oauth-details-hash + description: Base64 encoded SHA-256 hash of the oauth-details endpoint response. + required: true + - schema: + type: string + in: header + name: oauth-details-key + description: Transaction Id + required: true + - schema: + type: string + in: header + name: X-XSRF-TOKEN + description: CSRF token as set in cookie key 'XSRF-TOKEN' + required: true + parameters: [] + /linked-authorization/link-transaction: + post: + summary: Link Transaction endpoint + operationId: post-authorization-link-transaction + responses: + '200': + description: OK + content: + application/json: + schema: + type: object + properties: + responseTime: + type: string + response: + type: object + properties: + linkTransactionId: + type: string + description: Unique link-transaction-id. + clientName: + type: string + description: Registered name of the OIDC client. + logoUrl: + type: string + description: Registered OIDC client Logo URL. + authorizeScopes: + type: array + description: List of requested scopes to be permitted by the end user. + items: + type: string + essentialClaims: + type: array + description: List of client request mandatory claim names. + items: + type: string + voluntaryClaims: + type: array + description: List of client request optional claim names. + items: + type: string + authFactors: + type: array + description: Auth factors defines the authentication screens displayed in IDP frontend. More than one authFactor may be resolved or combination of auth factors. Precedence of authFactors is based on its order + items: + type: array + items: + $ref: '#/components/schemas/AuthFactor' + configs: + type: object + errors: + type: array + items: + type: object + properties: + errorCode: + type: string + enum: + - invalid_link_code + - invalid_transaction + - invalid_client_id + - unknown_error + errorMessage: + type: string + requestBody: + content: + application/json: + schema: + type: object + properties: + requestTime: + type: string + request: + type: object + required: + - linkCode + properties: + linkCode: + type: string + description: Link code as received by the wallet-app from the QR code scanning. + required: + - requestTime + - request + description: |- + The link transaction endpoint is invoked from Wallet-app. + + 1. Validates the link-code and its expiry and generates the linkTransactionId. This linkTransactionId is linked to transactionId returned from /oauth-details endpoint. + + 2. Returns the auth-factors, clientName, logoUrl, User claims, authorize scopes along with linkTransactionId. + + **Note:** + Wallet-app will hereafter address the transaction with this linkTransactionId for the /authenticate and /consent endpoints. + tags: + - WALLET + parameters: [] + /linked-authorization/link-status: + post: + summary: Link status endpoint + tags: + - UI + responses: + '200': + description: OK + content: + application/json: + schema: + type: object + properties: + responseTIme: + type: string + response: + type: object + properties: + transactionId: + type: string + description: This is the same transactionId as sent in the request. + linkStatus: + type: string + description: Link status of the linkCode passed in the request. + enum: + - LINKED + linkedDateTime: + type: string + description: Epoch in milliseconds at which the wallet-app acknowledged the link-code. + errors: + type: array + items: + type: object + properties: + errorCode: + type: string + enum: + - invalid_transaction_id + - invalid_link_code + - response_timeout + - unknown_error + errorMessage: + type: string + operationId: post-authorization-link-status + requestBody: + content: + application/json: + schema: + type: object + properties: + requestTime: + type: string + request: + type: object + required: + - transactionId + - linkCode + properties: + transactionId: + type: string + description: This is the same transactionId sent in the oauth-details response. + linkCode: + type: string + description: This is same linkCode returned in the generate-link-code response. + required: + - requestTime + - request + description: |- + The link transaction endpoint is invoked from Wallet-app. + + 1. Validates the link-code and its expiry and generates the linkTransactionId. This linkTransactionId is linked to transactionId returned from /oauth-details endpoint. + + 2. Returns the auth-factors, clientName, logoUrl, User claims, authorize scopes along with linkTransactionId. + + **Note:** + Wallet-app will hereafter address the transaction with this linkTransactionId for the /authenticate and /consent endpoints. + parameters: + - schema: + type: string + in: header + description: Base64 encoded SHA-256 hash of the oauth-details endpoint response. + name: oauth-details-hash + required: true + - schema: + type: string + in: header + name: oauth-details-key + description: Transaction Id + required: true + - schema: + type: string + in: header + name: X-XSRF-TOKEN + description: CSRF token as set in cookie key 'XSRF-TOKEN' + required: true + parameters: [] + /linked-authorization/authenticate: + post: + summary: Linked Authentication Endpoint + operationId: post-linked-authenticate + responses: + '200': + description: OK + content: + application/json: + schema: + type: object + properties: + responseTime: + type: string + response: + type: object + properties: + linkedTransactionId: + type: string + description: This is the same transactionId sent in the oauth-details response. + errors: + type: array + description: List of Errors in case of request validation / processing failure in Idp server. + items: + type: object + properties: + errorCode: + type: string + enum: + - invalid_transaction_id + - invalid_transaction + - invalid_identifier + - invalid_no_of_challenges + - auth_failed + - unknown_error + errorMessage: + type: string + requestBody: + content: + application/json: + schema: + type: object + properties: + requestTime: + type: string + pattern: 'yyyy-MM-dd''T''HH:mm:ss.SSS''Z''' + request: + type: object + required: + - linkedTransactionId + - individualId + - challengeList + properties: + linkedTransactionId: + type: string + description: This is the same transactionId sent in the link-transaction response. + individualId: + type: string + description: User identifier (UIN/VID). + challengeList: + type: array + description: Authentication Challenge. + items: + $ref: '#/components/schemas/AuthChallenge' + required: + - requestTime + - request + description: '' + description: |- + Once end user provides the user identifier (UIN/VID) and all the required auth challenge to the Wallet-app, this endpoint will be invoked from wallet-app. + + Supported auth-challenge depends on the integrated authentication server. + + 1. Validates linkedTransactionId. + 2. Validates null / empty individualId. + 4. Invokes kyc-auth call to integrated authentication server (IDA). + 5. Relays error from integrated authentication server to UI on failure. + + On Authentication Success: Only linkTransactionId is returned in the below response without any errors. + + On Authentication Failure: Error list will be set with the errors returned from the integrated authentication server. + parameters: [] + tags: + - WALLET + parameters: [] + /linked-authorization/v2/authenticate: + post: + summary: Linked Authentication Endpoint V2 + operationId: post-linked-authenticate-v2 + responses: + '200': + description: OK + content: + application/json: + schema: + type: object + properties: + responseTime: + type: string + response: + type: object + properties: + linkedTransactionId: + type: string + description: This is the same transactionId sent in the oauth-details response. + consentAction: + type: string + x-stoplight: + id: n2zh4pnppn8kt + enum: + - CAPTURE + - NOCAPTURE + description: | + This field indicates the need to capture user consent or not + errors: + type: array + description: List of Errors in case of request validation / processing failure in Idp server. + items: + type: object + properties: + errorCode: + type: string + enum: + - invalid_transaction_id + - invalid_transaction + - invalid_identifier + - invalid_no_of_challenges + - auth_failed + - unknown_error + errorMessage: + type: string + requestBody: + content: + application/json: + schema: + type: object + properties: + requestTime: + type: string + pattern: 'yyyy-MM-dd''T''HH:mm:ss.SSS''Z''' + request: + type: object + required: + - linkedTransactionId + - individualId + - challengeList + properties: + linkedTransactionId: + type: string + description: This is the same transactionId sent in the link-transaction response. + individualId: + type: string + description: User identifier (UIN/VID). + challengeList: + type: array + description: Authentication Challenge. + items: + $ref: '#/components/schemas/AuthChallenge' + required: + - requestTime + - request + description: '' + description: |- + Once end user provides the user identifier (UIN/VID) and all the required auth challenge to the Wallet-app, this endpoint will be invoked from wallet-app. + + Supported auth-challenge depends on the integrated authentication server. + + 1. Validates linkedTransactionId. + 2. Validates null / empty individualId. + 4. Invokes kyc-auth call to integrated authentication server (IDA). + 5. Relays error from integrated authentication server to UI on failure. + 6. It validates stored userconsent against the requested claims and scopes + + On Authentication Success: linkTransactionId and consentAction is returned in the below response without any errors. + + On Authentication Failure: Error list will be set with the errors returned from the integrated authentication server. + parameters: [] + tags: + - WALLET + parameters: [] + /linked-authorization/consent: + post: + summary: Linked Consent Endpoint + operationId: post-linked-consent + description: | + Once the authentication is successful and user consent is obtained, this endpoint will be invoked by the wallet app to send the accepted consent and permitted scopes. + + 1. Validates linkedTransactionId. + 2. Validate accepted claims and permitted scopes in the request. + 3. If valid, stores the accepted claims and permitted scopes in the cache. + requestBody: + content: + application/json: + schema: + type: object + properties: + requestTime: + type: string + pattern: 'yyyy-MM-dd''T''HH:mm:ss.SSS''Z''' + request: + type: object + required: + - linkedTransactionId + properties: + linkedTransactionId: + type: string + description: Transaction id echoed starting from /authorize call. + permittedAuthorizeScopes: + type: array + description: List of permitted scopes by end-user. + items: + type: string + acceptedClaims: + type: array + description: List of accepted essential and voluntary claims by end-user. + items: + type: string + required: + - requestTime + - request + parameters: [] + responses: + '200': + description: OK + content: + application/json: + schema: + type: object + properties: + responseTime: + type: string + response: + type: object + properties: + linkedTransactionId: + type: string + description: This is the same transactionId sent in the link-transaction response. + errors: + type: array + items: + type: object + properties: + errorCode: + type: string + enum: + - invalid_transaction_id + - invalid_transaction + - invalid_accepted_claim + - invalid_permitted_scope + errorMessage: + type: string + tags: + - WALLET + parameters: [] + /linked-authorization/v2/consent: + post: + summary: Linked Consent Endpoint V2 + operationId: post-linked-consent-v2 + description: | + Once the authentication is successful and user consent is obtained, this endpoint will be invoked by the wallet app to send the accepted consent and permitted scopes. + + 1. Validates linkedTransactionId. + 2. Validate accepted claims and permitted scopes in the request and the signature. + 3. If valid, stores the accepted claims, permitted scopes and signature in the consent registry. + requestBody: + content: + application/json: + schema: + type: object + properties: + requestTime: + type: string + pattern: 'yyyy-MM-dd''T''HH:mm:ss.SSS''Z''' + request: + type: object + required: + - linkedTransactionId + properties: + linkedTransactionId: + type: string + description: Transaction id echoed starting from /authorize call. + permittedAuthorizeScopes: + type: array + description: List of permitted scopes by end-user. + items: + type: string + acceptedClaims: + type: array + description: List of accepted essential and voluntary claims by end-user. + items: + type: string + signature: + type: string + x-stoplight: + id: hw1q1wqlgf98v + description: Signature of permittedscopes and acceptedclaims from inji + required: + - requestTime + - request + parameters: [] + responses: + '200': + description: OK + content: + application/json: + schema: + type: object + properties: + responseTime: + type: string + response: + type: object + properties: + linkedTransactionId: + type: string + description: This is the same transactionId sent in the link-transaction response. + errors: + type: array + items: + type: object + properties: + errorCode: + type: string + enum: + - invalid_transaction_id + - invalid_transaction + - invalid_accepted_claim + - invalid_permitted_scope + errorMessage: + type: string + tags: + - WALLET + parameters: [] + /linked-authorization/link-auth-code: + post: + summary: Link authorization code endpoint + tags: + - UI + responses: + '200': + description: OK + content: + application/json: + schema: + type: object + properties: + responseTime: + type: string + response: + type: object + properties: + code: + type: string + description: Authorization code. Required to obtain the ID token and / or access token from the /token endpoint. + redirectUri: + type: string + description: Client's validated redirect URI. + state: + type: string + description: 'The echoed state value, used to maintain state between the request and the callback' + nonce: + type: string + description: 'The echoed nonce value, if one was passed with the request. Clients must validate the value before proceeding.' + errors: + type: + - array + items: + type: object + properties: + errorCode: + type: string + enum: + - invalid_transaction + - invalid_transaction_id + - invalid_link_code + - response_timeout + - unknown_error + errorMessage: + type: string + operationId: post-authorization-link-auth + requestBody: + content: + application/json: + schema: + type: object + properties: + requestTime: + type: string + request: + type: object + required: + - transactionId + - linkedCode + properties: + transactionId: + type: string + description: This is the same transactionId sent in the oauth-details response. + linkedCode: + type: string + description: LINKED linkCode. + required: + - requestTime + - request + description: |- + Link authorization code endpoint is invoked from JS application. + + 1. This is a Long polling request to IdP-service. + 2. validates the transactionId + 3. validates the linkCode if its LINKED. + 4. checks the cache to see if the auth-code is generated, if yes returns the response. + 5. If the auth-code is not yet generated, polling request waits for the configured time. + 6. On successful response, IdP-UI should redirect to the provided redirectUri and auth-code or errors. + + + **Configuration to decide the wait interval**: mosip.idp.link-auth-code-deferred-response-timeout-secs + parameters: + - schema: + type: string + in: header + name: oauth-details-hash + description: Base64 encoded SHA-256 hash of the oauth-details endpoint response. + required: true + - schema: + type: string + in: header + name: oauth-details-key + description: Transaction Id + required: true + - schema: + type: string + in: header + name: X-XSRF-TOKEN + description: CSRF token as set in cookie key 'XSRF-TOKEN' + required: true + parameters: [] + /oauth/token: + post: + summary: Token Endpoint + operationId: post-token + responses: + '200': + description: OK + content: + application/json: + schema: + type: object + properties: + id_token: + type: string + description: |- + Identity token in JWT format. Will have the below claims in the payload. +
    +
  • iss
  • +
  • sub - (PSUT)
  • +
  • aud
  • +
  • exp
  • +
  • iat
  • +
  • auth_time
  • +
  • nonce
  • +
  • acr
  • +
  • at_hash
  • +
+ access_token: + type: string + description: The access token in JWT format. This token that will be used to call the UserInfo endpoint. + token_type: + type: string + default: Bearer + enum: + - Bearer + description: 'The type of the access token, set to Bearer' + expires_in: + type: number + format: duration + description: 'The lifetime of the access token, in seconds.' + required: + - id_token + - access_token + - token_type + - expires_in + headers: + Cache-Control: + schema: + type: string + enum: + - no-store + Pragma: + schema: + type: string + enum: + - no-cache + '400': + description: Bad Request + content: + application/json: + schema: + type: object + properties: + error: + type: string + description: The error code. + enum: + - invalid_transaction + - invalid_assertion + - invalid_redirect_uri + - invalid_input + - unknown_error + - invalid_request + - invalid_assertion_type + error_description: + type: string + description: Optional text providing additional information about the error that occurred. + required: + - error + description: |- + Once the client / relying party application receives the authorization code through redirect, this OIDC complaint endpoint will be called from the relying party backend application to get the ID and access token. + + 1. The only supported client authentication methods : private_key_jwt + 2. clientAssertion is a signed JWT with Clients private key, corresponding public key should be shared with IdP during the OIDC client registration process. + 3. clientAssertion JWT payload must be as below: + + The JWT MUST contain the following REQUIRED Claim Values and MAY contain the additional OPTIONAL Claim Values: + + **iss*** (Issuer): This MUST contain the client_id of the OAuth Client. + + **sub*** (Subject): This MUST contain the client_id of the OAuth Client. + + **aud*** (Audience): Value that identifies the authorization server as an intended audience. The authorization server MUST verify that it is an intended audience for the token. The audience SHOULD be the URL of the authorization server's token endpoint. + + **exp*** (Expiration): Time on or after which the ID token MUST NOT be accepted for processing. + + **iat***: Time at which the JWT was issued.

+ + **Note**: The Client Assertion JWT can contain other Claims. Any Claims used that are not understood WILL be ignored.

+ requestBody: + content: + application/x-www-form-urlencoded: + schema: + type: object + properties: + grant_type: + type: string + description: Authorization code grant type. + enum: + - authorization_code + code: + type: string + description: 'Authorization code, sent as query param in the client''s redirect URI.' + client_id: + type: string + description: Client Id of the OIDC client. + client_assertion_type: + type: string + enum: + - 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer' + description: Type of the client assertion part of this request. + client_assertion: + type: string + description: 'Private key signed JWT, This JWT payload structure is defined above as part of request description.' + redirect_uri: + type: string + description: Valid client redirect_uri. Must be same as the one sent in the authorize call. + required: + - grant_type + - code + - client_assertion_type + - client_assertion + - redirect_uri + description: '' + tags: + - OIDC + parameters: [] + /oidc/userinfo: + get: + summary: UserInfo Endpoint + responses: + '200': + description: OK + content: + application/jwt: + schema: + type: string + format: jwt + description: 'The response is signed and then encrypted, with the result being a Nested JWT. Signed using the authentication system''s private key. Signed full JWT will then be encrypted using OIDC client''s public key.' + '401': + description: Unauthorized + headers: + WWW-AUTHENTICATE: + schema: + type: string + enum: + - invalid_token + - unknown_error + description: 'Bearer error=invalid_token, error_description=MOSIPIDP123: A user info request was made with an access token that was not recognized.' + operationId: get-userinfo + parameters: [] + description: |- + Once the access token is received via the token endpoint, relying party backend application can call this OIDC compliant endpoint to request for the user claims. + + Consented user claims will be returned as a JWT. This JWT will be a nested JWT which is a signed using JWS and then encrypted using JWE. + + + **Example**: Assuming the below are the requested claims by the relying party + + name : { "essential" : true } + + phone: { "essential" : true } + + **Response 1**: When consent is provided for both name and phone number: + + { "name" : "John Doe", "phone" : "033456743" } + + **Response 2**: When consent is provided for only name: + + { "name" : "John Doe" } + + **Response 3**: When Claims are requested with claims_locales : "en fr" + + { "name#en" : "John Doe", "name#fr" : "Jean Doe", "phone" : "033456743" } + + **Supported User Info Claims** +
    +
  • sub - Partner Specific User Token (PSUT)
  • +
  • name
  • +
  • address
  • +
  • gender
  • +
  • birthdate
  • +
  • profile photo
  • +
  • email
  • +
  • phone
  • +
  • locale
  • +
  • Custom - individual_id (You share this claim as a system-level config and it can be UIN, perceptual VID or temporary VID)
  • +
+ tags: + - OIDC + security: + - Authorization-access_token: [] + parameters: [] + /binding/binding-otp: + post: + summary: Send Binding OTP Endpoint + operationId: post-binding-otp + responses: + '200': + description: OK + content: + application/json: + schema: + type: object + properties: + responseTIme: + type: string + response: + type: object + properties: + maskedEmail: + type: string + description: Masked email id of the individualId user. + maskedMobile: + type: string + description: Masked mobile number of the individualId user. + errors: + type: array + items: + type: object + properties: + errorCode: + type: string + enum: + - invalid_otp_channel + - unknown_error + - invalid_individual_id + - send_otp_failed + errorMessage: + type: string + required: + - responseTIme + parameters: + - schema: + type: string + in: header + name: partner-api-key + description: 'API key of the binding partner, this will be passed to binder implementation to interact with authentication system.' + - schema: + type: string + in: header + name: partner-id + description: 'Binding partner Identifier, this will be passed to binder implementation to interact with authentication system.' + requestBody: + content: + application/json: + schema: + type: object + properties: + requestTime: + type: string + request: + type: object + required: + - individualId + - otpChannels + properties: + individualId: + type: string + description: User Id (UIN/VID) + otpChannels: + type: array + description: Channels to which OTP should be delivered. + items: + type: string + required: + - requestTime + - request + description: Send wallet binding OTP endpoint is invoked by Mimoto server. + security: + - Authorization-send_binding_otp: [] + tags: + - binding-service + parameters: [] + /binding/wallet-binding: + post: + summary: Wallet Binding Endpoint + operationId: post-wallet-binding + responses: + '200': + description: OK + content: + application/json: + schema: + type: object + properties: + responseTime: + type: string + response: + type: object + properties: + walletUserId: + type: string + description: Unique identifier given to public-key and partner specific userId mapping. + certificate: + type: string + description: Key binder signed certificate. + expireDateTime: + type: string + description: Expire date time of the signed certificate. + errors: + type: array + items: + type: object + properties: + errorCode: + type: string + enum: + - unsupported_challenge_format + - key_binding_failed + - invalid_public_key + - invalid_auth_challenge + - duplicate_public_key + errorMessage: + type: string + required: + - responseTime + requestBody: + content: + application/json: + schema: + type: object + properties: + requestTime: + type: string + request: + type: object + required: + - individualId + - authFactorType + - format + - challengeList + - publicKey + properties: + individualId: + type: string + description: User Id (UIN/VID). + authFactorType: + type: string + description: Auth factor type to be binded for the provided key. + format: + type: string + description: 'Format of the auth factor type supported in the wallet app.This is not stored, this value is only validated to check if its a supported format in the keybinder implementation.' + challengeList: + type: array + items: + $ref: '#/components/schemas/AuthChallenge' + publicKey: + type: object + description: key to be binded in JWK format. + required: + - requestTime + - request + description: |- + Wallet binding endpoint is invoked by Mimoto server. + + 1. This request is invoked from wallet-app with authChallenge. + 2. Integrated keybinder implementation validates the authChallenge. + 3. Public key registry is updated with the key binding details for the provided individualId. + 4. Binded walletUserId (WUID) is returned with keybinder signed certificate. + + **Note**: Binding entry uniqueness is combination of these 3 values -> (PSUT, public-key, auth-factor-type) + parameters: + - schema: + type: string + in: header + name: partner-api-key + description: 'API key of the Binding partner, this will be passed to binder implementation to interact with authentication system.' + - schema: + type: string + in: header + name: partner-id + description: 'Binding partner identifier, this will be passed to binder implementation to interact with authentication system.' + security: + - Authorization-wallet_binding: [] + tags: + - binding-service + parameters: [] + /.well-known/jwks.json: + get: + summary: JSON Web Key Set Endpoint + tags: + - OIDC + responses: + '200': + description: OK + content: + application/json: + schema: + type: object + properties: + keys: + type: array + items: + type: object + properties: + kid: + type: string + description: The certificate's Key ID + use: + type: string + description: 'How the Key is used. Valid value: sig' + enum: + - sig + kty: + type: string + description: 'Cryptographic algorithm family for the certificate''s Key pair. Valid value: RSA' + enum: + - RSA + e: + type: string + description: RSA Key value (exponent) for Key blinding + 'n': + type: string + description: RSA modulus value + x5t#S256: + type: string + x-stoplight: + id: 52n5251u1kfap + description: SHA-256 thumbprint of the certificate. + x5c: + type: array + description: Certificate to validate the Oauth server trust. + items: + x-stoplight: + id: l0l1kpf2b9jcn + type: string + exp: + type: string + x-stoplight: + id: q4o4nzqtvb09p + description: Expire datetime of the key. Given in ISO format. + format: date-time + example: '2026-02-05T13:43:07.979Z' + required: + - kid + - use + - kty + - e + - 'n' + - x5t#S256 + - x5c + - exp + operationId: get-certs + description: Endpoint to fetch all the public keys of the e-Signet server. Returns public key set in the JWKS format. + parameters: [] + /.well-known/openid-configuration: + get: + summary: Configuration Endpoint + tags: + - OIDC + responses: + '200': + description: OK + content: + application/json: + schema: + type: object + properties: + issuer: + type: string + description: URL using the https scheme with no query or fragment component that the RP asserts as its Issuer Identifier. This also MUST be identical to the iss Claim value in ID Tokens issued from this Issuer. + authorization_endpoint: + type: string + description: URL of the OAuth 2.0 Authorization Endpoint. + token_endpoint: + type: string + description: URL of the OAuth 2.0 Token Endpoint. + userinfo_endpoint: + type: string + description: URL of the OP's UserInfo Endpoint. + jwks_uri: + type: string + description: 'URL of the OP''s JSON Web Key Set [JWK] document.' + registration_endpoint: + type: string + description: URL of Client Registration Endpoint. + scopes_supported: + type: array + description: 'JSON array containing a list of the OAuth 2.0 [RFC6749] scope values that this server supports.' + enum: + - openid + items: {} + response_types_supported: + type: array + description: JSON array containing a list of the OAuth 2.0 response_type values that this OP supports. + enum: + - code + items: {} + acr_values_supported: + type: array + description: JSON array containing a list of the Authentication Context Class References that IDP supports. + items: {} + userinfo_signing_alg_values_supported: + type: array + description: 'JSON array containing a list of the JWS [JWS] signing algorithms.' + items: {} + userinfo_encryption_alg_values_supported: + type: array + description: 'JSON array containing a list of the JWE [JWE] encryption algorithms.' + items: {} + userinfo_encryption_enc_values_supported: + type: array + description: 'JSON array containing a list of the JWE encryption algorithms (enc values) [JWA] supported by the UserInfo Endpoint to encode the Claims in a JWT.' + items: {} + token_endpoint_auth_methods_supported: + type: array + description: JSON array containing a list of Client Authentication methods supported by this Token Endpoint. + enum: + - private_key_jwt + items: {} + display_values_supported: + type: array + description: JSON array containing a list of the display parameter values that the OpenID Provider supports. + items: {} + claim_types_supported: + type: array + description: JSON array containing a list of the Claim Types that the OpenID Provider supports. + enum: + - normal + - aggregated + - distributed + items: {} + claims_supported: + type: array + description: JSON array containing a list of the Claim Names of the Claims that the OpenID Provider MAY be able to supply values for. + items: + type: string + claims_locales_supported: + type: array + description: Languages and scripts supported for values in Claims being returned. + items: + type: string + ui_locales_supported: + type: array + description: Languages and scripts supported for the user interface. + items: + type: string + response_modes_supported: + type: array + description: Mechanism to be used for returning parameters from the Authorization Endpoint. + items: + type: string + enum: + - query + token_endpoint_auth_signing_alg_values_supported: + type: array + items: + type: string + enum: + - RS256 + id_token_signing_alg_values_supported: + type: array + items: + type: string + enum: + - RS256 + required: + - issuer + - authorization_endpoint + - token_endpoint + - userinfo_endpoint + - jwks_uri + - registration_endpoint + - scopes_supported + - response_types_supported + operationId: get-.well-known-openid-configuration + description: |- + Open ID Connect dynamic provider discovery is not supported currently, this endpoint is only for facilitating the OIDC provider details in a standard way. + + **Reference**: https://openid.net/specs/openid-connect-discovery-1_0.html + parameters: [] + /oauth/introspect: + get: + summary: Introspect Endpoint (Draft) + tags: + - OIDC + responses: + '200': + description: OK + content: + application/json: + schema: + type: object + properties: + active: + type: boolean + '401': + description: Unauthorized + content: + application/json: + schema: + type: object + properties: + error: + type: string + error_description: + type: string + required: + - error + - error_description + operationId: get-introspect + description: |- + This endpoint takes an access token or ID token and returns a boolean that indicates whether it is active. If the token is active, additional data about the token is also returned. If the token is invalid, expired, or revoked, it is considered inactive. + + **Reference**: https://www.rfc-editor.org/rfc/rfc7662.html + parameters: + - schema: + type: string + in: query + name: token + description: An access token or ID token + required: true + - schema: + type: string + enum: + - access_token + - id_token + in: query + name: token_type_hint + description: 'Indicates the type of token being passed. Valid values: access_token, id_token' + required: true + security: + - Authorization-Bearer: [] + parameters: [] +components: + schemas: + Claim: + title: Claim + x-stoplight: + id: z7c32949w8qet + type: object + description: | + The userinfo and id_token members of the claims request both are JSON object. if null, Indicates that this Claim is being requested as Voluntary Claim. + + Note: Unknown claim names either in userinfo or id_token are ignored. + properties: + userinfo: + type: object + properties: + name: + $ref: '#/components/schemas/ClaimDetail' + given_name: + $ref: '#/components/schemas/ClaimDetail' + email: + $ref: '#/components/schemas/ClaimDetail' + gender: + $ref: '#/components/schemas/ClaimDetail' + birthdate: + $ref: '#/components/schemas/ClaimDetail' + phone_number: + $ref: '#/components/schemas/ClaimDetail' + profile_photo: + $ref: '#/components/schemas/ClaimDetail' + address: + $ref: '#/components/schemas/ClaimDetail' + locale: + $ref: '#/components/schemas/ClaimDetail' + individual_id: + $ref: '#/components/schemas/ClaimDetail' + id_token: + type: object + properties: + name: + $ref: '#/components/schemas/ClaimDetail' + acrs: + $ref: '#/components/schemas/ClaimDetail' + locales: + type: array + items: + type: string + ClaimDetail: + title: ClaimDetail + x-stoplight: + id: kypheo15jidj9 + type: object + properties: + essential: + type: boolean + description: | + Indicates whether the Claim being requested is an Essential Claim. If the value is true, this indicates that the Claim is an Essential Claim. The default is false. + value: + type: string + description: |- + Requests that the Claim be returned with a particular value. For instance the Claim request. + + "sub": {"value": "248289761001"} can be used to specify that the request apply to the End-User with Subject Identifier 248289761001. + values: + type: array + description: 'Requests that the Claim be returned with one of a set of values, with the values appearing in order of preference.' + items: + type: string + AuthChallenge: + title: AuthChallenge + x-stoplight: + id: n3fy2qkg9r7h2 + type: object + description: Model to take any type of challenge from the end user as part of authenticate request. + properties: + authFactorType: + type: string + description: Defines the type of auth challenge. It should be same as authfactor.type (oauth-details response). + enum: + - OTP + - BIO + - PIN + - WLA + challenge: + type: string + description: Actual challenge as string. + format: + type: string + description: Format of the challenge provided. + enum: + - alpha-numeric + - jwt + - encoded-json + - number + required: + - authFactorType + - challenge + - format + AuthFactor: + title: AuthFactor + x-stoplight: + id: m6lnp87wondln + type: object + properties: + type: + type: string + description: Name of the authentication method + enum: + - PIN + - OTP + - L1-bio-device + - Wallet + count: + type: integer + description: 'Applicable for biometric based authentication, number of bio segments to be captured for authentication.' + bioSubTypes: + type: array + description: Applicable for biometric based authentication. Can be more specific about which bio segments should be captured. + items: + type: string + required: + - type + securitySchemes: + Authorization-Bearer: + type: http + scheme: bearer + Authorization-add_oidc_client: + type: http + scheme: bearer + description: Valid JWT issued by a trusted IAM system with "**add_oidc_client**" scope. + Authorization-update_oidc_client: + type: http + scheme: bearer + description: Valid JWT issued by a trusted IAM system including "**update_oidc_client**" scope. + Authorization-access_token: + type: http + scheme: bearer + description: Access token received from /token endpoint + Authorization-send_binding_otp: + type: http + scheme: bearer + description: Valid JWT issued by a trusted IAM system with "send_binding_otp" scope. + Authorization-wallet_binding: + type: http + scheme: bearer + description: Valid JWT issued by a trusted IAM system with "**wallet_binding**" scope. +tags: + - name: Management + description: Management level API's used for internal use. + - name: OIDC + description: API's that are supposed to be compliant to OIDC. + - name: UI + description: UI related API. From 3067b1b68d96cb90bb14671f59e9029eeeaf892c Mon Sep 17 00:00:00 2001 From: Hitesh Jain Date: Thu, 17 Aug 2023 12:04:17 +0530 Subject: [PATCH 59/61] [ADDED] DB upgrade scripts --- db_upgrade_script/README.md | 1 + .../mosip_esignet/1.0.0_to_1.1.0_rollback.sql | 19 +++++ .../mosip_esignet/1.0.0_to_1.1.0_upgrade.sql | 79 +++++++++++++++++++ db_upgrade_script/upgrade.properties | 12 +++ db_upgrade_script/upgrade.sh | 51 ++++++++++++ 5 files changed, 162 insertions(+) create mode 100644 db_upgrade_script/README.md create mode 100644 db_upgrade_script/mosip_esignet/1.0.0_to_1.1.0_rollback.sql create mode 100644 db_upgrade_script/mosip_esignet/1.0.0_to_1.1.0_upgrade.sql create mode 100644 db_upgrade_script/upgrade.properties create mode 100644 db_upgrade_script/upgrade.sh diff --git a/db_upgrade_script/README.md b/db_upgrade_script/README.md new file mode 100644 index 000000000..1b407890b --- /dev/null +++ b/db_upgrade_script/README.md @@ -0,0 +1 @@ +Directory contains sql scripts to be executed for DB migrations. upgrade and revoke scripts are named after the migrated version. \ No newline at end of file diff --git a/db_upgrade_script/mosip_esignet/1.0.0_to_1.1.0_rollback.sql b/db_upgrade_script/mosip_esignet/1.0.0_to_1.1.0_rollback.sql new file mode 100644 index 000000000..7a97b57ed --- /dev/null +++ b/db_upgrade_script/mosip_esignet/1.0.0_to_1.1.0_rollback.sql @@ -0,0 +1,19 @@ +-- 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: mosip_esignet +-- Table Name : consent_detail +-- Purpose : To store user consent details +-- +-- Create By : Hitesh C +-- Created Date : August-2023 +-- +-- Modified Date Modified By Comments / Remarks +-- ------------------------------------------------------------------------------------------ +-- ------------------------------------------------------------------------------------------ + +\c mosip_esignet + +drop table consent_detail; +drop table consent_history; \ No newline at end of file diff --git a/db_upgrade_script/mosip_esignet/1.0.0_to_1.1.0_upgrade.sql b/db_upgrade_script/mosip_esignet/1.0.0_to_1.1.0_upgrade.sql new file mode 100644 index 000000000..c40f958f1 --- /dev/null +++ b/db_upgrade_script/mosip_esignet/1.0.0_to_1.1.0_upgrade.sql @@ -0,0 +1,79 @@ +-- 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: mosip_esignet +-- Table Name : consent_detail +-- Purpose : To store user consent details +-- +-- Create By : Hitesh C +-- Created Date : August-2023 +-- +-- Modified Date Modified By Comments / Remarks +-- ------------------------------------------------------------------------------------------ +-- ------------------------------------------------------------------------------------------ +\c mosip_esignet + +create table 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 consent_detail(psu_token, client_id); + +COMMENT ON TABLE consent_detail IS 'Contains user consent details'; + +COMMENT ON COLUMN consent_detail.id IS 'UUID : Unique id associated with each consent'; +COMMENT ON COLUMN consent_detail.client_id IS 'Client_id: associated with relying party'; +COMMENT ON COLUMN consent_detail.psu_token IS 'PSU token associated with user consent'; +COMMENT ON COLUMN consent_detail.claims IS 'Json of requested and user accepted claims'; +COMMENT ON COLUMN consent_detail.authorization_scopes IS 'Json string of requested authorization scope'; +COMMENT ON COLUMN consent_detail.cr_dtimes IS 'Consent creation date'; +COMMENT ON COLUMN consent_detail.expire_dtimes IS 'Expiration date'; +COMMENT ON COLUMN consent_detail.signature IS 'Signature of consent object '; +COMMENT ON COLUMN consent_detail.hash IS 'hash of consent object'; +COMMENT ON COLUMN consent_detail.accepted_claims IS 'Accepted Claims by the user'; +COMMENT ON COLUMN consent_detail.permitted_scopes IS 'Accepted Scopes by the user'; + + +create table 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 consent_history(psu_token, client_id); + +COMMENT ON TABLE consent_history IS 'Contains user consent details'; + +COMMENT ON COLUMN consent_history.id IS 'UUID : Unique id associated with each consent'; +COMMENT ON COLUMN consent_history.client_id IS 'Client_id: associated with relying party'; +COMMENT ON COLUMN consent_history.psu_token IS 'PSU token associated with user consent'; +COMMENT ON COLUMN consent_history.claims IS 'Json of requested and user accepted claims'; +COMMENT ON COLUMN consent_history.authorization_scopes IS 'Json string of requested authorization scope'; +COMMENT ON COLUMN consent_history.cr_dtimes IS 'Consent creation date'; +COMMENT ON COLUMN consent_history.expire_dtimes IS 'Expiration date'; +COMMENT ON COLUMN consent_history.signature IS 'Signature of consent object '; +COMMENT ON COLUMN consent_history.hash IS 'hash of consent object'; +COMMENT ON COLUMN consent_history.accepted_claims IS 'Accepted Claims by the user'; +COMMENT ON COLUMN consent_history.permitted_scopes IS 'Accepted Scopes by the user'; + diff --git a/db_upgrade_script/upgrade.properties b/db_upgrade_script/upgrade.properties new file mode 100644 index 000000000..6d4bafcd3 --- /dev/null +++ b/db_upgrade_script/upgrade.properties @@ -0,0 +1,12 @@ +ACTION=upgrade +MOSIP_DB_NAME= +DB_SERVERIP= +DB_PORT= +SU_USER=postgres +SU_USER_PWD= +SYS_ADMIN_USER= +SYS_ADMIN_PWD= +DEFAULT_DB_NAME=postgres +DBUSER_PWD= +CURRENT_VERSION= +UPGRADE_VERSION= diff --git a/db_upgrade_script/upgrade.sh b/db_upgrade_script/upgrade.sh new file mode 100644 index 000000000..fab569c81 --- /dev/null +++ b/db_upgrade_script/upgrade.sh @@ -0,0 +1,51 @@ +#!/bin/bash + +set -e +properties_file="$1" +echo `date "+%m/%d/%Y %H:%M:%S"` ": $properties_file" +if [ -f "$properties_file" ] +then + echo `date "+%m/%d/%Y %H:%M:%S"` ": Property file \"$properties_file\" found." + while IFS='=' read -r key value + do + key=$(echo $key | tr '.' '_') + eval ${key}=\${value} + done < "$properties_file" +else + echo `date "+%m/%d/%Y %H:%M:%S"` ": Property file not found, Pass property file name as argument." +fi + +echo "Current version: $CURRENT_VERSION" +echo "UPGRADE version: $UPGRADE_VERSION" +echo "Action: $ACTION" + +# Terminate existing connections +echo " active connections" +CONN=$(PGPASSWORD=$SU_USER_PWD psql -v ON_ERROR_STOP=1 --username=$SU_USER --host=$DB_SERVERIP --port=$DB_PORT --dbname=$DEFAULT_DB_NAME -t -c "SELECT count(pg_terminate_backend(pg_stat_activity.pid)) FROM pg_stat_activity WHERE datname = '$MOSIP_DB_NAME' AND pid <> pg_backend_pid()";exit;) +echo "Terminated connections" + +# Execute upgrade or rollback +if [ "$ACTION" == "upgrade" ]; then + echo "Upgrading database from $CURRENT_VERSION to $UPGRADE_VERSION" + UPGRADE_SCRIPT_FILE="mosip_esignet/${CURRENT_VERSION}_to_${UPGRADE_VERSION}_upgrade.sql" + if [ -f "$UPGRADE_SCRIPT_FILE" ]; then + echo "Executing upgrade script $UPGRADE_SCRIPT_FILE" + PGPASSWORD=$SU_USER_PWD psql -v ON_ERROR_STOP=1 --username=$SU_USER --host=$DB_SERVERIP --port=$DB_PORT --dbname=$DEFAULT_DB_NAME -v primary_language_code=$PRIMARY_LANGUAGE_CODE -a -b -f $UPGRADE_SCRIPT_FILE + else + echo "Upgrade script not found, exiting." + exit 1 + fi +elif [ "$ACTION" == "rollback" ]; then + echo "Rolling back database for $CURRENT_VERSION to $UPGRADE_VERSION" + REVOKE_SCRIPT_FILE="mosip_esignet/${CURRENT_VERSION}_to_${UPGRADE_VERSION}_rollback.sql" + if [ -f "$REVOKE_SCRIPT_FILE" ]; then + echo "Executing rollback script $REVOKE_SCRIPT_FILE" + PGPASSWORD=$SU_USER_PWD psql -v ON_ERROR_STOP=1 --username=$SU_USER --host=$DB_SERVERIP --port=$DB_PORT --dbname=$DEFAULT_DB_NAME -v primary_language_code=$PRIMARY_LANGUAGE_CODE -a -b -f $REVOKE_SCRIPT_FILE + else + echo "rollback script not found, exiting." + exit 1 + fi +else + echo "Unknown action: $ACTION, must be 'upgrade' or 'rollback'." + exit 1 +fi \ No newline at end of file From 5bb1850f38c65a40223125628c3bfc7c53a7c2a3 Mon Sep 17 00:00:00 2001 From: Hitesh Jain Date: Thu, 17 Aug 2023 12:06:02 +0530 Subject: [PATCH 60/61] Modified Readme --- db_upgrade_script/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/db_upgrade_script/README.md b/db_upgrade_script/README.md index 1b407890b..b09ed8119 100644 --- a/db_upgrade_script/README.md +++ b/db_upgrade_script/README.md @@ -1 +1 @@ -Directory contains sql scripts to be executed for DB migrations. upgrade and revoke scripts are named after the migrated version. \ No newline at end of file +Directory contains sql scripts to be executed for DB migrations. \ No newline at end of file From 5c90cbe716a8bc017357c8960fa29c46749af67c Mon Sep 17 00:00:00 2001 From: Hitesh Jain Date: Thu, 17 Aug 2023 15:34:00 +0530 Subject: [PATCH 61/61] [REFORMATTED] upgrade scripts --- .../mosip_esignet/{ => sql}/1.0.0_to_1.1.0_rollback.sql | 0 .../mosip_esignet/{ => sql}/1.0.0_to_1.1.0_upgrade.sql | 0 db_upgrade_script/{ => mosip_esignet}/upgrade.properties | 0 db_upgrade_script/{ => mosip_esignet}/upgrade.sh | 4 ++-- 4 files changed, 2 insertions(+), 2 deletions(-) rename db_upgrade_script/mosip_esignet/{ => sql}/1.0.0_to_1.1.0_rollback.sql (100%) rename db_upgrade_script/mosip_esignet/{ => sql}/1.0.0_to_1.1.0_upgrade.sql (100%) rename db_upgrade_script/{ => mosip_esignet}/upgrade.properties (100%) rename db_upgrade_script/{ => mosip_esignet}/upgrade.sh (91%) diff --git a/db_upgrade_script/mosip_esignet/1.0.0_to_1.1.0_rollback.sql b/db_upgrade_script/mosip_esignet/sql/1.0.0_to_1.1.0_rollback.sql similarity index 100% rename from db_upgrade_script/mosip_esignet/1.0.0_to_1.1.0_rollback.sql rename to db_upgrade_script/mosip_esignet/sql/1.0.0_to_1.1.0_rollback.sql diff --git a/db_upgrade_script/mosip_esignet/1.0.0_to_1.1.0_upgrade.sql b/db_upgrade_script/mosip_esignet/sql/1.0.0_to_1.1.0_upgrade.sql similarity index 100% rename from db_upgrade_script/mosip_esignet/1.0.0_to_1.1.0_upgrade.sql rename to db_upgrade_script/mosip_esignet/sql/1.0.0_to_1.1.0_upgrade.sql diff --git a/db_upgrade_script/upgrade.properties b/db_upgrade_script/mosip_esignet/upgrade.properties similarity index 100% rename from db_upgrade_script/upgrade.properties rename to db_upgrade_script/mosip_esignet/upgrade.properties diff --git a/db_upgrade_script/upgrade.sh b/db_upgrade_script/mosip_esignet/upgrade.sh similarity index 91% rename from db_upgrade_script/upgrade.sh rename to db_upgrade_script/mosip_esignet/upgrade.sh index fab569c81..6e9ccdc8a 100644 --- a/db_upgrade_script/upgrade.sh +++ b/db_upgrade_script/mosip_esignet/upgrade.sh @@ -27,7 +27,7 @@ echo "Terminated connections" # Execute upgrade or rollback if [ "$ACTION" == "upgrade" ]; then echo "Upgrading database from $CURRENT_VERSION to $UPGRADE_VERSION" - UPGRADE_SCRIPT_FILE="mosip_esignet/${CURRENT_VERSION}_to_${UPGRADE_VERSION}_upgrade.sql" + UPGRADE_SCRIPT_FILE="sql/${CURRENT_VERSION}_to_${UPGRADE_VERSION}_upgrade.sql" if [ -f "$UPGRADE_SCRIPT_FILE" ]; then echo "Executing upgrade script $UPGRADE_SCRIPT_FILE" PGPASSWORD=$SU_USER_PWD psql -v ON_ERROR_STOP=1 --username=$SU_USER --host=$DB_SERVERIP --port=$DB_PORT --dbname=$DEFAULT_DB_NAME -v primary_language_code=$PRIMARY_LANGUAGE_CODE -a -b -f $UPGRADE_SCRIPT_FILE @@ -37,7 +37,7 @@ if [ "$ACTION" == "upgrade" ]; then fi elif [ "$ACTION" == "rollback" ]; then echo "Rolling back database for $CURRENT_VERSION to $UPGRADE_VERSION" - REVOKE_SCRIPT_FILE="mosip_esignet/${CURRENT_VERSION}_to_${UPGRADE_VERSION}_rollback.sql" + REVOKE_SCRIPT_FILE="sql/${CURRENT_VERSION}_to_${UPGRADE_VERSION}_rollback.sql" if [ -f "$REVOKE_SCRIPT_FILE" ]; then echo "Executing rollback script $REVOKE_SCRIPT_FILE" PGPASSWORD=$SU_USER_PWD psql -v ON_ERROR_STOP=1 --username=$SU_USER --host=$DB_SERVERIP --port=$DB_PORT --dbname=$DEFAULT_DB_NAME -v primary_language_code=$PRIMARY_LANGUAGE_CODE -a -b -f $REVOKE_SCRIPT_FILE