diff --git a/pom.xml b/pom.xml index 601f3e49..7e00bf28 100644 --- a/pom.xml +++ b/pom.xml @@ -1,6 +1,7 @@ + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 @@ -9,10 +10,10 @@ 3.2.3 - io.mosip + io.inji.verify verify-service-parent 0.1.0-SNAPSHOT - Parent project of MOSIP inji-verify-service + Parent project of MOSIP Inji verify backend service https://github.com/mosip/inji-verify pom @@ -87,7 +88,6 @@ ossrh https://oss.sonatype.org/service/local/staging/deploy/maven2/ - @@ -124,6 +124,7 @@ org.springframework.boot spring-boot-starter-web + org.springframework.boot spring-boot-starter-test @@ -153,6 +154,49 @@ org.springframework.boot spring-boot-starter-actuator + + jakarta.servlet + jakarta.servlet-api + + + jakarta.validation + jakarta.validation-api + + + org.json + json + 20240303 + + + org.bouncycastle + bcpkix-jdk18on + 1.76 + + + org.projectlombok + lombok + compile + + + org.springframework.boot + spring-boot-starter-data-jpa + + + com.h2database + h2 + runtime + + + io.hypersistence + hypersistence-utils-hibernate-63 + 3.8.3 + + + + com.auth0 + java-jwt + 3.18.1 + @@ -193,7 +237,8 @@ true - ${project.build.outputDirectory}/git.properties + ${project.build.outputDirectory}/git.properties + ^git.build.(time|version)$ ^git.commit.id.(abbrev|full)$ @@ -216,9 +261,6 @@ org.apache.maven.plugins maven-javadoc-plugin - - true - org.apache.maven.plugins @@ -237,22 +279,6 @@ - - org.apache.maven.plugins - maven-javadoc-plugin - ${maven.javadoc.version} - - - attach-javadocs - - jar - - - - - none - - org.apache.maven.plugins maven-jar-plugin diff --git a/verify-service/.mvn/wrapper/maven-wrapper.properties b/verify-service/.mvn/wrapper/maven-wrapper.properties deleted file mode 100644 index d58dfb70..00000000 --- a/verify-service/.mvn/wrapper/maven-wrapper.properties +++ /dev/null @@ -1,19 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -wrapperVersion=3.3.2 -distributionType=only-script -distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.9/apache-maven-3.9.9-bin.zip diff --git a/verify-service/mvnw b/verify-service/mvnw deleted file mode 100755 index 19529ddf..00000000 --- a/verify-service/mvnw +++ /dev/null @@ -1,259 +0,0 @@ -#!/bin/sh -# ---------------------------------------------------------------------------- -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# ---------------------------------------------------------------------------- - -# ---------------------------------------------------------------------------- -# Apache Maven Wrapper startup batch script, version 3.3.2 -# -# Optional ENV vars -# ----------------- -# JAVA_HOME - location of a JDK home dir, required when download maven via java source -# MVNW_REPOURL - repo url base for downloading maven distribution -# MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven -# MVNW_VERBOSE - true: enable verbose log; debug: trace the mvnw script; others: silence the output -# ---------------------------------------------------------------------------- - -set -euf -[ "${MVNW_VERBOSE-}" != debug ] || set -x - -# OS specific support. -native_path() { printf %s\\n "$1"; } -case "$(uname)" in -CYGWIN* | MINGW*) - [ -z "${JAVA_HOME-}" ] || JAVA_HOME="$(cygpath --unix "$JAVA_HOME")" - native_path() { cygpath --path --windows "$1"; } - ;; -esac - -# set JAVACMD and JAVACCMD -set_java_home() { - # For Cygwin and MinGW, ensure paths are in Unix format before anything is touched - if [ -n "${JAVA_HOME-}" ]; then - if [ -x "$JAVA_HOME/jre/sh/java" ]; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - JAVACCMD="$JAVA_HOME/jre/sh/javac" - else - JAVACMD="$JAVA_HOME/bin/java" - JAVACCMD="$JAVA_HOME/bin/javac" - - if [ ! -x "$JAVACMD" ] || [ ! -x "$JAVACCMD" ]; then - echo "The JAVA_HOME environment variable is not defined correctly, so mvnw cannot run." >&2 - echo "JAVA_HOME is set to \"$JAVA_HOME\", but \"\$JAVA_HOME/bin/java\" or \"\$JAVA_HOME/bin/javac\" does not exist." >&2 - return 1 - fi - fi - else - JAVACMD="$( - 'set' +e - 'unset' -f command 2>/dev/null - 'command' -v java - )" || : - JAVACCMD="$( - 'set' +e - 'unset' -f command 2>/dev/null - 'command' -v javac - )" || : - - if [ ! -x "${JAVACMD-}" ] || [ ! -x "${JAVACCMD-}" ]; then - echo "The java/javac command does not exist in PATH nor is JAVA_HOME set, so mvnw cannot run." >&2 - return 1 - fi - fi -} - -# hash string like Java String::hashCode -hash_string() { - str="${1:-}" h=0 - while [ -n "$str" ]; do - char="${str%"${str#?}"}" - h=$(((h * 31 + $(LC_CTYPE=C printf %d "'$char")) % 4294967296)) - str="${str#?}" - done - printf %x\\n $h -} - -verbose() { :; } -[ "${MVNW_VERBOSE-}" != true ] || verbose() { printf %s\\n "${1-}"; } - -die() { - printf %s\\n "$1" >&2 - exit 1 -} - -trim() { - # MWRAPPER-139: - # Trims trailing and leading whitespace, carriage returns, tabs, and linefeeds. - # Needed for removing poorly interpreted newline sequences when running in more - # exotic environments such as mingw bash on Windows. - printf "%s" "${1}" | tr -d '[:space:]' -} - -# parse distributionUrl and optional distributionSha256Sum, requires .mvn/wrapper/maven-wrapper.properties -while IFS="=" read -r key value; do - case "${key-}" in - distributionUrl) distributionUrl=$(trim "${value-}") ;; - distributionSha256Sum) distributionSha256Sum=$(trim "${value-}") ;; - esac -done <"${0%/*}/.mvn/wrapper/maven-wrapper.properties" -[ -n "${distributionUrl-}" ] || die "cannot read distributionUrl property in ${0%/*}/.mvn/wrapper/maven-wrapper.properties" - -case "${distributionUrl##*/}" in -maven-mvnd-*bin.*) - MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ - case "${PROCESSOR_ARCHITECTURE-}${PROCESSOR_ARCHITEW6432-}:$(uname -a)" in - *AMD64:CYGWIN* | *AMD64:MINGW*) distributionPlatform=windows-amd64 ;; - :Darwin*x86_64) distributionPlatform=darwin-amd64 ;; - :Darwin*arm64) distributionPlatform=darwin-aarch64 ;; - :Linux*x86_64*) distributionPlatform=linux-amd64 ;; - *) - echo "Cannot detect native platform for mvnd on $(uname)-$(uname -m), use pure java version" >&2 - distributionPlatform=linux-amd64 - ;; - esac - distributionUrl="${distributionUrl%-bin.*}-$distributionPlatform.zip" - ;; -maven-mvnd-*) MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ ;; -*) MVN_CMD="mvn${0##*/mvnw}" _MVNW_REPO_PATTERN=/org/apache/maven/ ;; -esac - -# apply MVNW_REPOURL and calculate MAVEN_HOME -# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/ -[ -z "${MVNW_REPOURL-}" ] || distributionUrl="$MVNW_REPOURL$_MVNW_REPO_PATTERN${distributionUrl#*"$_MVNW_REPO_PATTERN"}" -distributionUrlName="${distributionUrl##*/}" -distributionUrlNameMain="${distributionUrlName%.*}" -distributionUrlNameMain="${distributionUrlNameMain%-bin}" -MAVEN_USER_HOME="${MAVEN_USER_HOME:-${HOME}/.m2}" -MAVEN_HOME="${MAVEN_USER_HOME}/wrapper/dists/${distributionUrlNameMain-}/$(hash_string "$distributionUrl")" - -exec_maven() { - unset MVNW_VERBOSE MVNW_USERNAME MVNW_PASSWORD MVNW_REPOURL || : - exec "$MAVEN_HOME/bin/$MVN_CMD" "$@" || die "cannot exec $MAVEN_HOME/bin/$MVN_CMD" -} - -if [ -d "$MAVEN_HOME" ]; then - verbose "found existing MAVEN_HOME at $MAVEN_HOME" - exec_maven "$@" -fi - -case "${distributionUrl-}" in -*?-bin.zip | *?maven-mvnd-?*-?*.zip) ;; -*) die "distributionUrl is not valid, must match *-bin.zip or maven-mvnd-*.zip, but found '${distributionUrl-}'" ;; -esac - -# prepare tmp dir -if TMP_DOWNLOAD_DIR="$(mktemp -d)" && [ -d "$TMP_DOWNLOAD_DIR" ]; then - clean() { rm -rf -- "$TMP_DOWNLOAD_DIR"; } - trap clean HUP INT TERM EXIT -else - die "cannot create temp dir" -fi - -mkdir -p -- "${MAVEN_HOME%/*}" - -# Download and Install Apache Maven -verbose "Couldn't find MAVEN_HOME, downloading and installing it ..." -verbose "Downloading from: $distributionUrl" -verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName" - -# select .zip or .tar.gz -if ! command -v unzip >/dev/null; then - distributionUrl="${distributionUrl%.zip}.tar.gz" - distributionUrlName="${distributionUrl##*/}" -fi - -# verbose opt -__MVNW_QUIET_WGET=--quiet __MVNW_QUIET_CURL=--silent __MVNW_QUIET_UNZIP=-q __MVNW_QUIET_TAR='' -[ "${MVNW_VERBOSE-}" != true ] || __MVNW_QUIET_WGET='' __MVNW_QUIET_CURL='' __MVNW_QUIET_UNZIP='' __MVNW_QUIET_TAR=v - -# normalize http auth -case "${MVNW_PASSWORD:+has-password}" in -'') MVNW_USERNAME='' MVNW_PASSWORD='' ;; -has-password) [ -n "${MVNW_USERNAME-}" ] || MVNW_USERNAME='' MVNW_PASSWORD='' ;; -esac - -if [ -z "${MVNW_USERNAME-}" ] && command -v wget >/dev/null; then - verbose "Found wget ... using wget" - wget ${__MVNW_QUIET_WGET:+"$__MVNW_QUIET_WGET"} "$distributionUrl" -O "$TMP_DOWNLOAD_DIR/$distributionUrlName" || die "wget: Failed to fetch $distributionUrl" -elif [ -z "${MVNW_USERNAME-}" ] && command -v curl >/dev/null; then - verbose "Found curl ... using curl" - curl ${__MVNW_QUIET_CURL:+"$__MVNW_QUIET_CURL"} -f -L -o "$TMP_DOWNLOAD_DIR/$distributionUrlName" "$distributionUrl" || die "curl: Failed to fetch $distributionUrl" -elif set_java_home; then - verbose "Falling back to use Java to download" - javaSource="$TMP_DOWNLOAD_DIR/Downloader.java" - targetZip="$TMP_DOWNLOAD_DIR/$distributionUrlName" - cat >"$javaSource" <<-END - public class Downloader extends java.net.Authenticator - { - protected java.net.PasswordAuthentication getPasswordAuthentication() - { - return new java.net.PasswordAuthentication( System.getenv( "MVNW_USERNAME" ), System.getenv( "MVNW_PASSWORD" ).toCharArray() ); - } - public static void main( String[] args ) throws Exception - { - setDefault( new Downloader() ); - java.nio.file.Files.copy( java.net.URI.create( args[0] ).toURL().openStream(), java.nio.file.Paths.get( args[1] ).toAbsolutePath().normalize() ); - } - } - END - # For Cygwin/MinGW, switch paths to Windows format before running javac and java - verbose " - Compiling Downloader.java ..." - "$(native_path "$JAVACCMD")" "$(native_path "$javaSource")" || die "Failed to compile Downloader.java" - verbose " - Running Downloader.java ..." - "$(native_path "$JAVACMD")" -cp "$(native_path "$TMP_DOWNLOAD_DIR")" Downloader "$distributionUrl" "$(native_path "$targetZip")" -fi - -# If specified, validate the SHA-256 sum of the Maven distribution zip file -if [ -n "${distributionSha256Sum-}" ]; then - distributionSha256Result=false - if [ "$MVN_CMD" = mvnd.sh ]; then - echo "Checksum validation is not supported for maven-mvnd." >&2 - echo "Please disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2 - exit 1 - elif command -v sha256sum >/dev/null; then - if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | sha256sum -c >/dev/null 2>&1; then - distributionSha256Result=true - fi - elif command -v shasum >/dev/null; then - if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | shasum -a 256 -c >/dev/null 2>&1; then - distributionSha256Result=true - fi - else - echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." >&2 - echo "Please install either command, or disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2 - exit 1 - fi - if [ $distributionSha256Result = false ]; then - echo "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised." >&2 - echo "If you updated your Maven version, you need to update the specified distributionSha256Sum property." >&2 - exit 1 - fi -fi - -# unzip and move -if command -v unzip >/dev/null; then - unzip ${__MVNW_QUIET_UNZIP:+"$__MVNW_QUIET_UNZIP"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -d "$TMP_DOWNLOAD_DIR" || die "failed to unzip" -else - tar xzf${__MVNW_QUIET_TAR:+"$__MVNW_QUIET_TAR"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -C "$TMP_DOWNLOAD_DIR" || die "failed to untar" -fi -printf %s\\n "$distributionUrl" >"$TMP_DOWNLOAD_DIR/$distributionUrlNameMain/mvnw.url" -mv -- "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" "$MAVEN_HOME" || [ -d "$MAVEN_HOME" ] || die "fail to move MAVEN_HOME" - -clean || : -exec_maven "$@" diff --git a/verify-service/mvnw.cmd b/verify-service/mvnw.cmd deleted file mode 100644 index 249bdf38..00000000 --- a/verify-service/mvnw.cmd +++ /dev/null @@ -1,149 +0,0 @@ -<# : batch portion -@REM ---------------------------------------------------------------------------- -@REM Licensed to the Apache Software Foundation (ASF) under one -@REM or more contributor license agreements. See the NOTICE file -@REM distributed with this work for additional information -@REM regarding copyright ownership. The ASF licenses this file -@REM to you under the Apache License, Version 2.0 (the -@REM "License"); you may not use this file except in compliance -@REM with the License. You may obtain a copy of the License at -@REM -@REM http://www.apache.org/licenses/LICENSE-2.0 -@REM -@REM Unless required by applicable law or agreed to in writing, -@REM software distributed under the License is distributed on an -@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -@REM KIND, either express or implied. See the License for the -@REM specific language governing permissions and limitations -@REM under the License. -@REM ---------------------------------------------------------------------------- - -@REM ---------------------------------------------------------------------------- -@REM Apache Maven Wrapper startup batch script, version 3.3.2 -@REM -@REM Optional ENV vars -@REM MVNW_REPOURL - repo url base for downloading maven distribution -@REM MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven -@REM MVNW_VERBOSE - true: enable verbose log; others: silence the output -@REM ---------------------------------------------------------------------------- - -@IF "%__MVNW_ARG0_NAME__%"=="" (SET __MVNW_ARG0_NAME__=%~nx0) -@SET __MVNW_CMD__= -@SET __MVNW_ERROR__= -@SET __MVNW_PSMODULEP_SAVE=%PSModulePath% -@SET PSModulePath= -@FOR /F "usebackq tokens=1* delims==" %%A IN (`powershell -noprofile "& {$scriptDir='%~dp0'; $script='%__MVNW_ARG0_NAME__%'; icm -ScriptBlock ([Scriptblock]::Create((Get-Content -Raw '%~f0'))) -NoNewScope}"`) DO @( - IF "%%A"=="MVN_CMD" (set __MVNW_CMD__=%%B) ELSE IF "%%B"=="" (echo %%A) ELSE (echo %%A=%%B) -) -@SET PSModulePath=%__MVNW_PSMODULEP_SAVE% -@SET __MVNW_PSMODULEP_SAVE= -@SET __MVNW_ARG0_NAME__= -@SET MVNW_USERNAME= -@SET MVNW_PASSWORD= -@IF NOT "%__MVNW_CMD__%"=="" (%__MVNW_CMD__% %*) -@echo Cannot start maven from wrapper >&2 && exit /b 1 -@GOTO :EOF -: end batch / begin powershell #> - -$ErrorActionPreference = "Stop" -if ($env:MVNW_VERBOSE -eq "true") { - $VerbosePreference = "Continue" -} - -# calculate distributionUrl, requires .mvn/wrapper/maven-wrapper.properties -$distributionUrl = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionUrl -if (!$distributionUrl) { - Write-Error "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties" -} - -switch -wildcard -casesensitive ( $($distributionUrl -replace '^.*/','') ) { - "maven-mvnd-*" { - $USE_MVND = $true - $distributionUrl = $distributionUrl -replace '-bin\.[^.]*$',"-windows-amd64.zip" - $MVN_CMD = "mvnd.cmd" - break - } - default { - $USE_MVND = $false - $MVN_CMD = $script -replace '^mvnw','mvn' - break - } -} - -# apply MVNW_REPOURL and calculate MAVEN_HOME -# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/ -if ($env:MVNW_REPOURL) { - $MVNW_REPO_PATTERN = if ($USE_MVND) { "/org/apache/maven/" } else { "/maven/mvnd/" } - $distributionUrl = "$env:MVNW_REPOURL$MVNW_REPO_PATTERN$($distributionUrl -replace '^.*'+$MVNW_REPO_PATTERN,'')" -} -$distributionUrlName = $distributionUrl -replace '^.*/','' -$distributionUrlNameMain = $distributionUrlName -replace '\.[^.]*$','' -replace '-bin$','' -$MAVEN_HOME_PARENT = "$HOME/.m2/wrapper/dists/$distributionUrlNameMain" -if ($env:MAVEN_USER_HOME) { - $MAVEN_HOME_PARENT = "$env:MAVEN_USER_HOME/wrapper/dists/$distributionUrlNameMain" -} -$MAVEN_HOME_NAME = ([System.Security.Cryptography.MD5]::Create().ComputeHash([byte[]][char[]]$distributionUrl) | ForEach-Object {$_.ToString("x2")}) -join '' -$MAVEN_HOME = "$MAVEN_HOME_PARENT/$MAVEN_HOME_NAME" - -if (Test-Path -Path "$MAVEN_HOME" -PathType Container) { - Write-Verbose "found existing MAVEN_HOME at $MAVEN_HOME" - Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD" - exit $? -} - -if (! $distributionUrlNameMain -or ($distributionUrlName -eq $distributionUrlNameMain)) { - Write-Error "distributionUrl is not valid, must end with *-bin.zip, but found $distributionUrl" -} - -# prepare tmp dir -$TMP_DOWNLOAD_DIR_HOLDER = New-TemporaryFile -$TMP_DOWNLOAD_DIR = New-Item -Itemtype Directory -Path "$TMP_DOWNLOAD_DIR_HOLDER.dir" -$TMP_DOWNLOAD_DIR_HOLDER.Delete() | Out-Null -trap { - if ($TMP_DOWNLOAD_DIR.Exists) { - try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null } - catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" } - } -} - -New-Item -Itemtype Directory -Path "$MAVEN_HOME_PARENT" -Force | Out-Null - -# Download and Install Apache Maven -Write-Verbose "Couldn't find MAVEN_HOME, downloading and installing it ..." -Write-Verbose "Downloading from: $distributionUrl" -Write-Verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName" - -$webclient = New-Object System.Net.WebClient -if ($env:MVNW_USERNAME -and $env:MVNW_PASSWORD) { - $webclient.Credentials = New-Object System.Net.NetworkCredential($env:MVNW_USERNAME, $env:MVNW_PASSWORD) -} -[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 -$webclient.DownloadFile($distributionUrl, "$TMP_DOWNLOAD_DIR/$distributionUrlName") | Out-Null - -# If specified, validate the SHA-256 sum of the Maven distribution zip file -$distributionSha256Sum = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionSha256Sum -if ($distributionSha256Sum) { - if ($USE_MVND) { - Write-Error "Checksum validation is not supported for maven-mvnd. `nPlease disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." - } - Import-Module $PSHOME\Modules\Microsoft.PowerShell.Utility -Function Get-FileHash - if ((Get-FileHash "$TMP_DOWNLOAD_DIR/$distributionUrlName" -Algorithm SHA256).Hash.ToLower() -ne $distributionSha256Sum) { - Write-Error "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised. If you updated your Maven version, you need to update the specified distributionSha256Sum property." - } -} - -# unzip and move -Expand-Archive "$TMP_DOWNLOAD_DIR/$distributionUrlName" -DestinationPath "$TMP_DOWNLOAD_DIR" | Out-Null -Rename-Item -Path "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" -NewName $MAVEN_HOME_NAME | Out-Null -try { - Move-Item -Path "$TMP_DOWNLOAD_DIR/$MAVEN_HOME_NAME" -Destination $MAVEN_HOME_PARENT | Out-Null -} catch { - if (! (Test-Path -Path "$MAVEN_HOME" -PathType Container)) { - Write-Error "fail to move MAVEN_HOME" - } -} finally { - try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null } - catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" } -} - -Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD" diff --git a/verify-service/pom.xml b/verify-service/pom.xml index ca3a0e1b..e23f7d54 100644 --- a/verify-service/pom.xml +++ b/verify-service/pom.xml @@ -1,32 +1,20 @@ + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - io.mosip + io.inji.verify verify-service-parent 0.1.0-SNAPSHOT - io.mosip verify-service 0.1.0-SNAPSHOT verify-service - verify-service + Inji verify backend server implementing the OpenId4VP flow and online verification of VC jar - - - org.springframework.boot - spring-boot-starter-web - - - - org.springframework.boot - spring-boot-starter-test - test - - diff --git a/verify-service/src/main/java/io/mosip/verifyservice/VerifyServiceApplication.java b/verify-service/src/main/java/io/inji/verify/VerifyServiceApplication.java similarity index 72% rename from verify-service/src/main/java/io/mosip/verifyservice/VerifyServiceApplication.java rename to verify-service/src/main/java/io/inji/verify/VerifyServiceApplication.java index e5482ff1..3829c7d5 100644 --- a/verify-service/src/main/java/io/mosip/verifyservice/VerifyServiceApplication.java +++ b/verify-service/src/main/java/io/inji/verify/VerifyServiceApplication.java @@ -1,11 +1,12 @@ -package io.mosip.verifyservice; +package io.inji.verify; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.domain.EntityScan; @SpringBootApplication +@EntityScan("io.inji.verify") public class VerifyServiceApplication { - public static void main(String[] args) { SpringApplication.run(VerifyServiceApplication.class, args); } diff --git a/verify-service/src/main/java/io/inji/verify/config/AppConfig.java b/verify-service/src/main/java/io/inji/verify/config/AppConfig.java new file mode 100644 index 00000000..169adc54 --- /dev/null +++ b/verify-service/src/main/java/io/inji/verify/config/AppConfig.java @@ -0,0 +1,19 @@ +package io.inji.verify.config; + +import com.nimbusds.jose.shaded.gson.Gson; +import io.mosip.vercred.vcverifier.CredentialsVerifier; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class AppConfig { + @Bean + public CredentialsVerifier credentialsVerifier() { + return new CredentialsVerifier(); + } + + @Bean + public Gson gson() { + return new Gson(); + } +} diff --git a/verify-service/src/main/java/io/inji/verify/controller/VCVerificationController.java b/verify-service/src/main/java/io/inji/verify/controller/VCVerificationController.java new file mode 100644 index 00000000..d79732e8 --- /dev/null +++ b/verify-service/src/main/java/io/inji/verify/controller/VCVerificationController.java @@ -0,0 +1,20 @@ +package io.inji.verify.controller; + +import io.inji.verify.dto.verification.VCVerificationStatusDto; +import io.inji.verify.spi.VCVerificationService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RequestMapping(path = "/vc-verification") +@RestController +public class VCVerificationController { + @Autowired + VCVerificationService VCVerificationService; + @PostMapping() + public VCVerificationStatusDto verify(@RequestBody String vc) { + return VCVerificationService.verify(vc); + } +} \ No newline at end of file diff --git a/verify-service/src/main/java/io/inji/verify/controller/VPDefinitionController.java b/verify-service/src/main/java/io/inji/verify/controller/VPDefinitionController.java new file mode 100644 index 00000000..3873c00f --- /dev/null +++ b/verify-service/src/main/java/io/inji/verify/controller/VPDefinitionController.java @@ -0,0 +1,31 @@ +package io.inji.verify.controller; + +import io.inji.verify.dto.presentation.VPDefinitionResponseDto; +import io.inji.verify.spi.VPDefinitionService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RequestMapping("/vp-definition") +@RestController +public class VPDefinitionController { + @Autowired + VPDefinitionService VPDefinitionService; + + @GetMapping(path = "/{id}") + public ResponseEntity getPresentationDefinitionFor(@PathVariable String id) { + + VPDefinitionResponseDto VPDefinitionResponseDto = VPDefinitionService.getPresentationDefinition(id); + if (VPDefinitionResponseDto != null) + { + return new ResponseEntity<>(VPDefinitionResponseDto, HttpStatus.OK); + } + + return new ResponseEntity<>(null, HttpStatus.NOT_FOUND); + + } +} diff --git a/verify-service/src/main/java/io/inji/verify/controller/VPRequestController.java b/verify-service/src/main/java/io/inji/verify/controller/VPRequestController.java new file mode 100644 index 00000000..a8a18715 --- /dev/null +++ b/verify-service/src/main/java/io/inji/verify/controller/VPRequestController.java @@ -0,0 +1,39 @@ +package io.inji.verify.controller; + +import io.inji.verify.dto.authorizationrequest.VPRequestCreateDto; +import io.inji.verify.dto.authorizationrequest.VPRequestResponseDto; +import io.inji.verify.dto.authorizationrequest.VPRequestStatusDto; +import io.inji.verify.spi.VerifiablePresentationRequestService; +import jakarta.validation.Valid; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +@RequestMapping("/vp-request") +@RestController +public class VPRequestController { + + @Autowired + VerifiablePresentationRequestService verifiablePresentationRequestService; + + @PostMapping(consumes = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity createVPRequest(@Valid @RequestBody VPRequestCreateDto vpRequestCreate) { + if (vpRequestCreate.getPresentationDefinition() == null) { + return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(null); + } + VPRequestResponseDto authorizationRequestResponse = verifiablePresentationRequestService.createAuthorizationRequest(vpRequestCreate); + return new ResponseEntity<>(authorizationRequestResponse, HttpStatus.CREATED); + } + + @GetMapping(path = "/{requestId}/status") + public ResponseEntity getStatus(@PathVariable String requestId) { + + VPRequestStatusDto vpRequestStatusDto = verifiablePresentationRequestService.getCurrentRequestStatus(requestId); + if (vpRequestStatusDto == null) + return new ResponseEntity<>(null, HttpStatus.NOT_FOUND); + + return new ResponseEntity<>(vpRequestStatusDto, HttpStatus.OK); + } +} diff --git a/verify-service/src/main/java/io/inji/verify/controller/VPResultController.java b/verify-service/src/main/java/io/inji/verify/controller/VPResultController.java new file mode 100644 index 00000000..49795636 --- /dev/null +++ b/verify-service/src/main/java/io/inji/verify/controller/VPResultController.java @@ -0,0 +1,38 @@ +package io.inji.verify.controller; + +import io.inji.verify.dto.submission.VPTokenResultDto; +import io.inji.verify.enums.ErrorCode; +import io.inji.verify.shared.Constants; +import io.inji.verify.spi.VerifiablePresentationRequestService; +import io.inji.verify.spi.VerifiablePresentationSubmissionService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; +@RestController +public class VPResultController { + @Autowired + VerifiablePresentationRequestService verifiablePresentationRequestService; + + @Autowired + VerifiablePresentationSubmissionService verifiablePresentationSubmissionService; + + @GetMapping(path = "/vp-result/{transactionId}") + public ResponseEntity getVPResult(@PathVariable String transactionId) { + List requestIds = verifiablePresentationRequestService.getLatestRequestIdFor(transactionId); + + if (requestIds.isEmpty()) { + return new ResponseEntity<>(new VPTokenResultDto(null,null,null, ErrorCode.ERR_100, Constants.ERR_100), HttpStatus.OK); + } + + VPTokenResultDto result = verifiablePresentationSubmissionService.getVPResult(requestIds,transactionId); + if (result != null) { + return new ResponseEntity<>(result, HttpStatus.OK); + } + return new ResponseEntity<>(new VPTokenResultDto(null,null,null, ErrorCode.ERR_101, Constants.ERR_101),HttpStatus.OK); + } +} diff --git a/verify-service/src/main/java/io/inji/verify/controller/VPSubmissionController.java b/verify-service/src/main/java/io/inji/verify/controller/VPSubmissionController.java new file mode 100644 index 00000000..cbcafbcb --- /dev/null +++ b/verify-service/src/main/java/io/inji/verify/controller/VPSubmissionController.java @@ -0,0 +1,48 @@ +package io.inji.verify.controller; + +import com.nimbusds.jose.shaded.gson.Gson; +import io.inji.verify.dto.authorizationrequest.VPRequestStatusDto; +import io.inji.verify.dto.submission.PresentationSubmissionDto; +import io.inji.verify.dto.submission.VPSubmissionDto; +import io.inji.verify.dto.submission.VPSubmissionResponseDto; +import io.inji.verify.dto.submission.VPTokenResultDto; +import io.inji.verify.enums.ErrorCode; +import io.inji.verify.shared.Constants; +import io.inji.verify.spi.VerifiablePresentationRequestService; +import io.inji.verify.spi.VerifiablePresentationSubmissionService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@RequestMapping(path = "/vp-submission") +public class VPSubmissionController { + + @Autowired + VerifiablePresentationRequestService verifiablePresentationRequestService; + + @Autowired + VerifiablePresentationSubmissionService verifiablePresentationSubmissionService; + + @Autowired + Gson gson; + + @PostMapping(path = Constants.RESPONSE_SUBMISSION_URI, consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE) + public ResponseEntity submitVP(@RequestParam(value = "vp_token") String vpToken, @RequestParam(value = "presentation_submission") String presentationSubmission, @RequestParam(value = "state") String state) { + PresentationSubmissionDto presentationSubmissionDto = gson.fromJson(presentationSubmission, PresentationSubmissionDto.class); + VPSubmissionDto vpSubmissionDto = new VPSubmissionDto(vpToken, presentationSubmissionDto, state); + verifiablePresentationSubmissionService.submit(vpSubmissionDto); + + VPRequestStatusDto currentVPRequestStatusDto = verifiablePresentationRequestService.getCurrentRequestStatus(vpSubmissionDto.getState()); + if (currentVPRequestStatusDto == null) { + return new ResponseEntity<>(HttpStatus.NOT_FOUND); + } + + VPSubmissionResponseDto submissionResponseDto = verifiablePresentationSubmissionService.submit(vpSubmissionDto); + return new ResponseEntity<>(submissionResponseDto, HttpStatus.OK); + } +} diff --git a/verify-service/src/main/java/io/inji/verify/dto/authorizationrequest/AuthorizationRequestResponseDto.java b/verify-service/src/main/java/io/inji/verify/dto/authorizationrequest/AuthorizationRequestResponseDto.java new file mode 100644 index 00000000..bd492f48 --- /dev/null +++ b/verify-service/src/main/java/io/inji/verify/dto/authorizationrequest/AuthorizationRequestResponseDto.java @@ -0,0 +1,35 @@ +package io.inji.verify.dto.authorizationrequest; + +import com.fasterxml.jackson.annotation.JsonInclude; +import io.inji.verify.models.PresentationDefinition; +import io.inji.verify.shared.Constants; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.io.Serializable; +import java.time.Instant; + +@Getter +@AllArgsConstructor +@Builder +@NoArgsConstructor(force = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public class AuthorizationRequestResponseDto implements Serializable { + + private final String responseType = Constants.RESPONSE_TYPE; + private final String clientId; + private final String presentationDefinitionUri; + private String responseUri; + private String nonce; + private final long issuedAt; + + public AuthorizationRequestResponseDto(String clientId, PresentationDefinition presentationDefinition, String nonce) { + this.clientId = clientId; + this.responseUri = Constants.RESPONSE_SUBMISSION_URI; + this.presentationDefinitionUri = presentationDefinition.getURL(); + this.issuedAt = Instant.now().toEpochMilli(); + this.nonce = nonce; + } +} diff --git a/verify-service/src/main/java/io/inji/verify/dto/authorizationrequest/VPRequestCreateDto.java b/verify-service/src/main/java/io/inji/verify/dto/authorizationrequest/VPRequestCreateDto.java new file mode 100644 index 00000000..f1244573 --- /dev/null +++ b/verify-service/src/main/java/io/inji/verify/dto/authorizationrequest/VPRequestCreateDto.java @@ -0,0 +1,17 @@ +package io.inji.verify.dto.authorizationrequest; + +import io.inji.verify.dto.presentation.VPDefinitionResponseDto; +import lombok.*; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Getter +public class VPRequestCreateDto { + String clientId; + String transactionId; + String presentationDefinitionId; + String nonce; + VPDefinitionResponseDto presentationDefinition; +} \ No newline at end of file diff --git a/verify-service/src/main/java/io/inji/verify/dto/authorizationrequest/VPRequestResponseDto.java b/verify-service/src/main/java/io/inji/verify/dto/authorizationrequest/VPRequestResponseDto.java new file mode 100644 index 00000000..b562d19b --- /dev/null +++ b/verify-service/src/main/java/io/inji/verify/dto/authorizationrequest/VPRequestResponseDto.java @@ -0,0 +1,15 @@ +package io.inji.verify.dto.authorizationrequest; + +import lombok.*; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Getter +public class VPRequestResponseDto { + String transactionId; + String requestId; + AuthorizationRequestResponseDto authorizationDetails; + long expiresAt; +} diff --git a/verify-service/src/main/java/io/inji/verify/dto/authorizationrequest/VPRequestStatusDto.java b/verify-service/src/main/java/io/inji/verify/dto/authorizationrequest/VPRequestStatusDto.java new file mode 100644 index 00000000..09d69b79 --- /dev/null +++ b/verify-service/src/main/java/io/inji/verify/dto/authorizationrequest/VPRequestStatusDto.java @@ -0,0 +1,11 @@ +package io.inji.verify.dto.authorizationrequest; + +import io.inji.verify.enums.VPRequestStatus; +import lombok.AllArgsConstructor; +import lombok.Getter; + +@AllArgsConstructor +@Getter +public class VPRequestStatusDto { + VPRequestStatus status; +} diff --git a/verify-service/src/main/java/io/inji/verify/dto/authorizationrequest/VPResultDto.java b/verify-service/src/main/java/io/inji/verify/dto/authorizationrequest/VPResultDto.java new file mode 100644 index 00000000..436e4835 --- /dev/null +++ b/verify-service/src/main/java/io/inji/verify/dto/authorizationrequest/VPResultDto.java @@ -0,0 +1,19 @@ +package io.inji.verify.dto.authorizationrequest; + +import com.fasterxml.jackson.annotation.JsonInclude; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.json.JSONObject; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@JsonInclude(JsonInclude.Include.NON_NULL) +public class VPResultDto { + String transactionId; + boolean verified; + JSONObject claims; +} diff --git a/verify-service/src/main/java/io/inji/verify/dto/presentation/ConstraintsDTO.java b/verify-service/src/main/java/io/inji/verify/dto/presentation/ConstraintsDTO.java new file mode 100644 index 00000000..db079e9b --- /dev/null +++ b/verify-service/src/main/java/io/inji/verify/dto/presentation/ConstraintsDTO.java @@ -0,0 +1,16 @@ +package io.inji.verify.dto.presentation; + +import com.fasterxml.jackson.annotation.JsonInclude; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@JsonInclude(JsonInclude.Include.NON_NULL) +public class ConstraintsDTO { + FieldDTO[] fields; +} \ No newline at end of file diff --git a/verify-service/src/main/java/io/inji/verify/dto/presentation/FieldDTO.java b/verify-service/src/main/java/io/inji/verify/dto/presentation/FieldDTO.java new file mode 100644 index 00000000..116212d1 --- /dev/null +++ b/verify-service/src/main/java/io/inji/verify/dto/presentation/FieldDTO.java @@ -0,0 +1,15 @@ +package io.inji.verify.dto.presentation; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class FieldDTO { + String[] path; + FilterDTO filter; +} diff --git a/verify-service/src/main/java/io/inji/verify/dto/presentation/FilterDTO.java b/verify-service/src/main/java/io/inji/verify/dto/presentation/FilterDTO.java new file mode 100644 index 00000000..38f44f9f --- /dev/null +++ b/verify-service/src/main/java/io/inji/verify/dto/presentation/FilterDTO.java @@ -0,0 +1,15 @@ +package io.inji.verify.dto.presentation; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class FilterDTO { + String type; + String pattern; +} \ No newline at end of file diff --git a/verify-service/src/main/java/io/inji/verify/dto/presentation/InputDescriptorDto.java b/verify-service/src/main/java/io/inji/verify/dto/presentation/InputDescriptorDto.java new file mode 100644 index 00000000..c2182cb3 --- /dev/null +++ b/verify-service/src/main/java/io/inji/verify/dto/presentation/InputDescriptorDto.java @@ -0,0 +1,24 @@ +package io.inji.verify.dto.presentation; + +import com.fasterxml.jackson.annotation.JsonInclude; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; +import java.util.Map; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@JsonInclude(JsonInclude.Include.NON_NULL) +public class InputDescriptorDto { + String id; + String name; + String purpose; + List group; + Map>> format; + ConstraintsDTO constraints; +} diff --git a/verify-service/src/main/java/io/inji/verify/dto/presentation/SubmissionRequirementDto.java b/verify-service/src/main/java/io/inji/verify/dto/presentation/SubmissionRequirementDto.java new file mode 100644 index 00000000..4b388077 --- /dev/null +++ b/verify-service/src/main/java/io/inji/verify/dto/presentation/SubmissionRequirementDto.java @@ -0,0 +1,20 @@ +package io.inji.verify.dto.presentation; + +import com.fasterxml.jackson.annotation.JsonInclude; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@JsonInclude(JsonInclude.Include.NON_NULL) +public class SubmissionRequirementDto { + String name; + String rule; + String count; + String from; +} + diff --git a/verify-service/src/main/java/io/inji/verify/dto/presentation/VPDefinitionResponseDto.java b/verify-service/src/main/java/io/inji/verify/dto/presentation/VPDefinitionResponseDto.java new file mode 100644 index 00000000..e109501d --- /dev/null +++ b/verify-service/src/main/java/io/inji/verify/dto/presentation/VPDefinitionResponseDto.java @@ -0,0 +1,26 @@ +package io.inji.verify.dto.presentation; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.nimbusds.jose.shaded.gson.annotations.SerializedName; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import java.util.List; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@JsonInclude(JsonInclude.Include.NON_NULL) +public class VPDefinitionResponseDto { + String id; + @JsonProperty("input_descriptors") + @SerializedName("input_descriptors") + List inputDescriptors; + + @JsonProperty("submission_requirements") + @SerializedName("submission_requirements") + List submissionRequirements; +} diff --git a/verify-service/src/main/java/io/inji/verify/dto/submission/DescriptorMapDto.java b/verify-service/src/main/java/io/inji/verify/dto/submission/DescriptorMapDto.java new file mode 100644 index 00000000..51659a6a --- /dev/null +++ b/verify-service/src/main/java/io/inji/verify/dto/submission/DescriptorMapDto.java @@ -0,0 +1,22 @@ +package io.inji.verify.dto.submission; + + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.nimbusds.jose.shaded.gson.annotations.SerializedName; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class DescriptorMapDto { + String id; + String format; + String path; + @JsonProperty("path_nested") + @SerializedName("path_nested") + PathNestedDto pathNested; +} diff --git a/verify-service/src/main/java/io/inji/verify/dto/submission/PathNestedDto.java b/verify-service/src/main/java/io/inji/verify/dto/submission/PathNestedDto.java new file mode 100644 index 00000000..0e126abd --- /dev/null +++ b/verify-service/src/main/java/io/inji/verify/dto/submission/PathNestedDto.java @@ -0,0 +1,15 @@ +package io.inji.verify.dto.submission; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class PathNestedDto { + String format; + String path; +} diff --git a/verify-service/src/main/java/io/inji/verify/dto/submission/PresentationResponseDto.java b/verify-service/src/main/java/io/inji/verify/dto/submission/PresentationResponseDto.java new file mode 100644 index 00000000..19be511b --- /dev/null +++ b/verify-service/src/main/java/io/inji/verify/dto/submission/PresentationResponseDto.java @@ -0,0 +1,17 @@ +package io.inji.verify.dto.submission; + +import io.inji.verify.enums.VerificationStatus; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class PresentationResponseDto { + String transactionId; + String vpToken; + VerificationStatus verificationStatus; +} diff --git a/verify-service/src/main/java/io/inji/verify/dto/submission/PresentationSubmissionDto.java b/verify-service/src/main/java/io/inji/verify/dto/submission/PresentationSubmissionDto.java new file mode 100644 index 00000000..b65f7bd8 --- /dev/null +++ b/verify-service/src/main/java/io/inji/verify/dto/submission/PresentationSubmissionDto.java @@ -0,0 +1,24 @@ +package io.inji.verify.dto.submission; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.nimbusds.jose.shaded.gson.annotations.SerializedName; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class PresentationSubmissionDto { + String id; + @JsonProperty("definition_id") + @SerializedName("definition_id") + String definitionId; + @JsonProperty("descriptor_map") + @SerializedName("descriptor_map") + List descriptorMap; +} diff --git a/verify-service/src/main/java/io/inji/verify/dto/submission/VPSubmissionDto.java b/verify-service/src/main/java/io/inji/verify/dto/submission/VPSubmissionDto.java new file mode 100644 index 00000000..92d8be81 --- /dev/null +++ b/verify-service/src/main/java/io/inji/verify/dto/submission/VPSubmissionDto.java @@ -0,0 +1,20 @@ +package io.inji.verify.dto.submission; + +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class VPSubmissionDto { + @NotNull + String vpToken; + @NotNull + PresentationSubmissionDto presentationSubmission; + @NotNull + String state; +} diff --git a/verify-service/src/main/java/io/inji/verify/dto/submission/VPSubmissionResponseDto.java b/verify-service/src/main/java/io/inji/verify/dto/submission/VPSubmissionResponseDto.java new file mode 100644 index 00000000..e0231c46 --- /dev/null +++ b/verify-service/src/main/java/io/inji/verify/dto/submission/VPSubmissionResponseDto.java @@ -0,0 +1,17 @@ +package io.inji.verify.dto.submission; + + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class VPSubmissionResponseDto { + String redirectUri; + String error; + String errorDescription; +} diff --git a/verify-service/src/main/java/io/inji/verify/dto/submission/VPTokenResultDto.java b/verify-service/src/main/java/io/inji/verify/dto/submission/VPTokenResultDto.java new file mode 100644 index 00000000..63ba5dc9 --- /dev/null +++ b/verify-service/src/main/java/io/inji/verify/dto/submission/VPTokenResultDto.java @@ -0,0 +1,25 @@ +package io.inji.verify.dto.submission; + +import com.fasterxml.jackson.annotation.JsonInclude; +import io.inji.verify.enums.ErrorCode; +import io.inji.verify.enums.VPResultStatus; +import io.inji.verify.models.VCResult; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@JsonInclude(JsonInclude.Include.NON_NULL) +public class VPTokenResultDto { + String transactionId; + VPResultStatus VPResultStatus; + List VCResults; + ErrorCode errorCode; + String errorMessage; +} diff --git a/verify-service/src/main/java/io/inji/verify/dto/verification/VCVerificationStatusDto.java b/verify-service/src/main/java/io/inji/verify/dto/verification/VCVerificationStatusDto.java new file mode 100644 index 00000000..9f5b1391 --- /dev/null +++ b/verify-service/src/main/java/io/inji/verify/dto/verification/VCVerificationStatusDto.java @@ -0,0 +1,15 @@ +package io.inji.verify.dto.verification; + +import io.inji.verify.enums.VerificationStatus; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class VCVerificationStatusDto { + VerificationStatus verificationStatus; +} diff --git a/verify-service/src/main/java/io/inji/verify/enums/ErrorCode.java b/verify-service/src/main/java/io/inji/verify/enums/ErrorCode.java new file mode 100644 index 00000000..12c9ada7 --- /dev/null +++ b/verify-service/src/main/java/io/inji/verify/enums/ErrorCode.java @@ -0,0 +1,6 @@ +package io.inji.verify.enums; + +public enum ErrorCode { + ERR_100, + ERR_101 +} diff --git a/verify-service/src/main/java/io/inji/verify/enums/VPRequestStatus.java b/verify-service/src/main/java/io/inji/verify/enums/VPRequestStatus.java new file mode 100644 index 00000000..7de7fd09 --- /dev/null +++ b/verify-service/src/main/java/io/inji/verify/enums/VPRequestStatus.java @@ -0,0 +1,8 @@ +package io.inji.verify.enums; + +public enum VPRequestStatus { + ACTIVE, + VP_SUBMITTED, + EXPIRED +} + diff --git a/verify-service/src/main/java/io/inji/verify/enums/VPResultStatus.java b/verify-service/src/main/java/io/inji/verify/enums/VPResultStatus.java new file mode 100644 index 00000000..c87bd96d --- /dev/null +++ b/verify-service/src/main/java/io/inji/verify/enums/VPResultStatus.java @@ -0,0 +1,6 @@ +package io.inji.verify.enums; + +public enum VPResultStatus { + SUCCESS, + FAILED +} diff --git a/verify-service/src/main/java/io/inji/verify/enums/VerificationStatus.java b/verify-service/src/main/java/io/inji/verify/enums/VerificationStatus.java new file mode 100644 index 00000000..01d123d2 --- /dev/null +++ b/verify-service/src/main/java/io/inji/verify/enums/VerificationStatus.java @@ -0,0 +1,7 @@ +package io.inji.verify.enums; + +public enum VerificationStatus { + SUCCESS, + EXPIRED, + INVALID +} diff --git a/verify-service/src/main/java/io/inji/verify/exception/VerificationFailedException.java b/verify-service/src/main/java/io/inji/verify/exception/VerificationFailedException.java new file mode 100644 index 00000000..e4dc1c6e --- /dev/null +++ b/verify-service/src/main/java/io/inji/verify/exception/VerificationFailedException.java @@ -0,0 +1,8 @@ +package io.inji.verify.exception; + +public class VerificationFailedException extends Exception{ + private static final String message = "Verification Failed"; + public VerificationFailedException() { + super(message); + } +} diff --git a/verify-service/src/main/java/io/inji/verify/models/AuthorizationRequestCreateResponse.java b/verify-service/src/main/java/io/inji/verify/models/AuthorizationRequestCreateResponse.java new file mode 100644 index 00000000..0d4f8d4d --- /dev/null +++ b/verify-service/src/main/java/io/inji/verify/models/AuthorizationRequestCreateResponse.java @@ -0,0 +1,40 @@ +package io.inji.verify.models; + +import io.inji.verify.dto.authorizationrequest.AuthorizationRequestResponseDto; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import jakarta.persistence.Table; +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import org.hibernate.annotations.JdbcTypeCode; +import org.hibernate.type.SqlTypes; + +import java.io.Serializable; + +@Getter +@Setter +@Entity +@Table(name = "AuthorizationRequestCreateResponse") +@AllArgsConstructor +@NoArgsConstructor(force = true) +public class AuthorizationRequestCreateResponse implements Serializable { + @Id + private final String requestId; + + @NotNull + @Column + private final String transactionId; + + @NotNull + @Column(columnDefinition = "json") + @JdbcTypeCode(SqlTypes.JSON) + AuthorizationRequestResponseDto authorizationDetails; + + @NotNull + @Column + long expiresAt; +} \ No newline at end of file diff --git a/verify-service/src/main/java/io/inji/verify/models/PresentationDefinition.java b/verify-service/src/main/java/io/inji/verify/models/PresentationDefinition.java new file mode 100644 index 00000000..e9750f76 --- /dev/null +++ b/verify-service/src/main/java/io/inji/verify/models/PresentationDefinition.java @@ -0,0 +1,40 @@ +package io.inji.verify.models; + +import io.inji.verify.dto.presentation.InputDescriptorDto; +import io.inji.verify.dto.presentation.SubmissionRequirementDto; +import io.inji.verify.shared.Constants; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import jakarta.persistence.Table; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import org.hibernate.annotations.JdbcTypeCode; +import org.hibernate.type.SqlTypes; +import java.util.List; + +@Table(name = "PresentationDefinition") +@Getter +@Setter +@Entity +@AllArgsConstructor +@NoArgsConstructor(force = true) +public class PresentationDefinition { + @Id + private final String id; + + @Column(columnDefinition = "json") + @JdbcTypeCode(SqlTypes.JSON) + private final List inputDescriptors; + + @Column(columnDefinition = "json") + @JdbcTypeCode(SqlTypes.JSON) + private final List submissionRequirements; + + + public String getURL(){ + return Constants.VP_DEFINITION_URI +this.id; + } +} diff --git a/verify-service/src/main/java/io/inji/verify/models/VCResult.java b/verify-service/src/main/java/io/inji/verify/models/VCResult.java new file mode 100644 index 00000000..4cc56d15 --- /dev/null +++ b/verify-service/src/main/java/io/inji/verify/models/VCResult.java @@ -0,0 +1,17 @@ +package io.inji.verify.models; + + +import io.inji.verify.enums.VerificationStatus; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class VCResult { + String vc; + VerificationStatus verificationStatus; +} diff --git a/verify-service/src/main/java/io/inji/verify/models/VPSubmission.java b/verify-service/src/main/java/io/inji/verify/models/VPSubmission.java new file mode 100644 index 00000000..9c633ce5 --- /dev/null +++ b/verify-service/src/main/java/io/inji/verify/models/VPSubmission.java @@ -0,0 +1,35 @@ +package io.inji.verify.models; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.nimbusds.jose.shaded.gson.annotations.SerializedName; +import io.inji.verify.dto.submission.PresentationSubmissionDto; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import jakarta.persistence.Table; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import org.hibernate.annotations.JdbcTypeCode; +import org.hibernate.type.SqlTypes; + +@Table(name = "VPSubmission") +@Getter +@Setter +@Entity +@AllArgsConstructor +@NoArgsConstructor +public class VPSubmission { + @Id + @JsonProperty("state") + @SerializedName("state") + String requestId; + + @JdbcTypeCode(SqlTypes.CLOB) + String vpToken; + + @Column(columnDefinition = "json") + @JdbcTypeCode(SqlTypes.JSON) + PresentationSubmissionDto presentationSubmission; +} diff --git a/verify-service/src/main/java/io/inji/verify/repository/AuthorizationRequestCreateResponseRepository.java b/verify-service/src/main/java/io/inji/verify/repository/AuthorizationRequestCreateResponseRepository.java new file mode 100644 index 00000000..55612d9a --- /dev/null +++ b/verify-service/src/main/java/io/inji/verify/repository/AuthorizationRequestCreateResponseRepository.java @@ -0,0 +1,13 @@ +package io.inji.verify.repository; + +import io.inji.verify.models.AuthorizationRequestCreateResponse; +import jakarta.validation.constraints.NotNull; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.List; +import java.util.Optional; + +public interface AuthorizationRequestCreateResponseRepository extends JpaRepository { + List findAllByTransactionIdOrderByExpiresAtDesc(@NotNull String transactionId); +} + diff --git a/verify-service/src/main/java/io/inji/verify/repository/PresentationDefinitionRepository.java b/verify-service/src/main/java/io/inji/verify/repository/PresentationDefinitionRepository.java new file mode 100644 index 00000000..537aae29 --- /dev/null +++ b/verify-service/src/main/java/io/inji/verify/repository/PresentationDefinitionRepository.java @@ -0,0 +1,8 @@ +package io.inji.verify.repository; + +import io.inji.verify.models.PresentationDefinition; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface PresentationDefinitionRepository extends JpaRepository { } diff --git a/verify-service/src/main/java/io/inji/verify/repository/VPSubmissionRepository.java b/verify-service/src/main/java/io/inji/verify/repository/VPSubmissionRepository.java new file mode 100644 index 00000000..3319ebec --- /dev/null +++ b/verify-service/src/main/java/io/inji/verify/repository/VPSubmissionRepository.java @@ -0,0 +1,7 @@ +package io.inji.verify.repository; + +import io.inji.verify.models.VPSubmission; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface VPSubmissionRepository extends JpaRepository { +} diff --git a/verify-service/src/main/java/io/inji/verify/services/VCVerificationServiceImpl.java b/verify-service/src/main/java/io/inji/verify/services/VCVerificationServiceImpl.java new file mode 100644 index 00000000..4cc39c1d --- /dev/null +++ b/verify-service/src/main/java/io/inji/verify/services/VCVerificationServiceImpl.java @@ -0,0 +1,28 @@ +package io.inji.verify.services; + +import io.inji.verify.dto.verification.VCVerificationStatusDto; +import io.inji.verify.enums.VerificationStatus; +import io.inji.verify.spi.VCVerificationService; +import io.mosip.vercred.vcverifier.CredentialsVerifier; +import io.mosip.vercred.vcverifier.constants.CredentialFormat; +import io.mosip.vercred.vcverifier.constants.CredentialValidatorConstants; +import io.mosip.vercred.vcverifier.data.VerificationResult; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class VCVerificationServiceImpl implements VCVerificationService { + @Autowired + CredentialsVerifier credentialsVerifier; + + @Override + public VCVerificationStatusDto verify(String vc) { + VerificationResult verificationResult = credentialsVerifier.verify(vc, CredentialFormat.LDP_VC); + if (verificationResult.getVerificationStatus()) { + if (verificationResult.getVerificationErrorCode().equals(CredentialValidatorConstants.ERROR_CODE_VC_EXPIRED)) + return new VCVerificationStatusDto(VerificationStatus.EXPIRED); + return new VCVerificationStatusDto(VerificationStatus.SUCCESS); + } + return new VCVerificationStatusDto(VerificationStatus.INVALID); + } +} diff --git a/verify-service/src/main/java/io/inji/verify/services/VPDefinitionServiceImpl.java b/verify-service/src/main/java/io/inji/verify/services/VPDefinitionServiceImpl.java new file mode 100644 index 00000000..72e947a9 --- /dev/null +++ b/verify-service/src/main/java/io/inji/verify/services/VPDefinitionServiceImpl.java @@ -0,0 +1,25 @@ +package io.inji.verify.services; + +import io.inji.verify.dto.presentation.VPDefinitionResponseDto; +import io.inji.verify.models.PresentationDefinition; +import io.inji.verify.spi.VPDefinitionService; +import io.inji.verify.repository.PresentationDefinitionRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class VPDefinitionServiceImpl implements VPDefinitionService { + + @Autowired + PresentationDefinitionRepository presentationDefinitionRepository; + @Override + public VPDefinitionResponseDto getPresentationDefinition(String id) { + try { + PresentationDefinition presentationDefinition = presentationDefinitionRepository.findById(id).orElse(null); + assert presentationDefinition != null; + return new VPDefinitionResponseDto(presentationDefinition.getId(),presentationDefinition.getInputDescriptors(),presentationDefinition.getSubmissionRequirements()); + } catch (AssertionError e) { + return null; + } + } +} diff --git a/verify-service/src/main/java/io/inji/verify/services/VerifiablePresentationRequestServiceImpl.java b/verify-service/src/main/java/io/inji/verify/services/VerifiablePresentationRequestServiceImpl.java new file mode 100644 index 00000000..0cf0ecd0 --- /dev/null +++ b/verify-service/src/main/java/io/inji/verify/services/VerifiablePresentationRequestServiceImpl.java @@ -0,0 +1,76 @@ +package io.inji.verify.services; + +import io.inji.verify.dto.authorizationrequest.AuthorizationRequestResponseDto; +import io.inji.verify.dto.authorizationrequest.VPRequestCreateDto; +import io.inji.verify.dto.authorizationrequest.VPRequestResponseDto; +import io.inji.verify.dto.authorizationrequest.VPRequestStatusDto; +import io.inji.verify.dto.presentation.VPDefinitionResponseDto; +import io.inji.verify.enums.VPRequestStatus; +import io.inji.verify.models.AuthorizationRequestCreateResponse; +import io.inji.verify.models.PresentationDefinition; +import io.inji.verify.models.VPSubmission; +import io.inji.verify.repository.AuthorizationRequestCreateResponseRepository; +import io.inji.verify.repository.PresentationDefinitionRepository; +import io.inji.verify.repository.VPSubmissionRepository; +import io.inji.verify.shared.Constants; +import io.inji.verify.spi.VerifiablePresentationRequestService; +import io.inji.verify.utils.SecurityUtils; +import io.inji.verify.utils.Utils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.time.Instant; +import java.util.List; + +@Service +public class VerifiablePresentationRequestServiceImpl implements VerifiablePresentationRequestService { + + @Autowired + PresentationDefinitionRepository presentationDefinitionRepository; + @Autowired + AuthorizationRequestCreateResponseRepository authorizationRequestCreateResponseRepository; + @Autowired + VPSubmissionRepository vpSubmissionRepository; + public VerifiablePresentationRequestServiceImpl() {} + + @Override + public VPRequestResponseDto createAuthorizationRequest(VPRequestCreateDto vpRequestCreate) { + + String transactionId = vpRequestCreate.getTransactionId()!=null ? vpRequestCreate.getTransactionId() : Utils.generateID(Constants.TRANSACTION_ID_PREFIX); + String requestId = Utils.generateID(Constants.REQUEST_ID_PREFIX); + long expiresAt = Instant.now().plusSeconds(Constants.DEFAULT_EXPIRY).toEpochMilli(); + String nonce = vpRequestCreate.getNonce()!=null ? vpRequestCreate.getNonce() : SecurityUtils.generateNonce(); + + VPDefinitionResponseDto VPDefinitionResponseDto = vpRequestCreate.getPresentationDefinition(); + PresentationDefinition presentationDefinition = new PresentationDefinition(VPDefinitionResponseDto.getId(), VPDefinitionResponseDto.getInputDescriptors(), VPDefinitionResponseDto.getSubmissionRequirements()); + + AuthorizationRequestResponseDto authorizationRequestResponseDto = new AuthorizationRequestResponseDto(vpRequestCreate.getClientId(), presentationDefinition,nonce); + AuthorizationRequestCreateResponse authorizationRequestCreateResponse = new AuthorizationRequestCreateResponse(requestId, transactionId, authorizationRequestResponseDto, expiresAt); + + authorizationRequestCreateResponseRepository.save(authorizationRequestCreateResponse); + + return new VPRequestResponseDto(authorizationRequestCreateResponse.getTransactionId(),authorizationRequestCreateResponse.getRequestId(),authorizationRequestCreateResponse.getAuthorizationDetails(),authorizationRequestCreateResponse.getExpiresAt()); + } + + @Override + public VPRequestStatusDto getCurrentRequestStatus(String requestId) { + VPSubmission vpSubmission = vpSubmissionRepository.findById(requestId).orElse(null); + + if (vpSubmission != null) { + return new VPRequestStatusDto(VPRequestStatus.VP_SUBMITTED); + } + Long expiresAt = authorizationRequestCreateResponseRepository.findById(requestId).map(AuthorizationRequestCreateResponse::getExpiresAt).orElse(null); + if (expiresAt == null){ + return null; + } + if(Instant.now().toEpochMilli() > expiresAt){ + return new VPRequestStatusDto(VPRequestStatus.EXPIRED); + } + return new VPRequestStatusDto(VPRequestStatus.ACTIVE); + } + + @Override + public List getLatestRequestIdFor(String transactionId) { + return authorizationRequestCreateResponseRepository.findAllByTransactionIdOrderByExpiresAtDesc(transactionId).stream().map(AuthorizationRequestCreateResponse::getRequestId).toList(); + } +} diff --git a/verify-service/src/main/java/io/inji/verify/services/VerifiablePresentationSubmissionServiceImpl.java b/verify-service/src/main/java/io/inji/verify/services/VerifiablePresentationSubmissionServiceImpl.java new file mode 100644 index 00000000..75e5654e --- /dev/null +++ b/verify-service/src/main/java/io/inji/verify/services/VerifiablePresentationSubmissionServiceImpl.java @@ -0,0 +1,100 @@ +package io.inji.verify.services; + + +import com.auth0.jwt.JWT; +import com.auth0.jwt.JWTVerifier; +import com.auth0.jwt.algorithms.Algorithm; +import io.inji.verify.dto.submission.VPSubmissionResponseDto; +import io.inji.verify.dto.submission.VPSubmissionDto; +import io.inji.verify.dto.submission.VPTokenResultDto; +import io.inji.verify.enums.VPResultStatus; +import io.inji.verify.enums.VerificationStatus; +import io.inji.verify.exception.VerificationFailedException; +import io.inji.verify.models.VCResult; +import io.inji.verify.models.VPSubmission; +import io.inji.verify.repository.AuthorizationRequestCreateResponseRepository; +import io.inji.verify.repository.VPSubmissionRepository; +import io.inji.verify.shared.Constants; +import io.inji.verify.spi.VerifiablePresentationSubmissionService; +import io.inji.verify.utils.SecurityUtils; +import io.inji.verify.utils.Utils; +import io.mosip.vercred.vcverifier.CredentialsVerifier; +import io.mosip.vercred.vcverifier.constants.CredentialFormat; +import io.mosip.vercred.vcverifier.data.VerificationResult; +import lombok.extern.slf4j.Slf4j; +import org.json.JSONArray; +import org.json.JSONObject; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.List; + +@Service +@Slf4j +public class VerifiablePresentationSubmissionServiceImpl implements VerifiablePresentationSubmissionService { + + @Autowired + AuthorizationRequestCreateResponseRepository authorizationRequestCreateResponseRepository; + @Autowired + VPSubmissionRepository vpSubmissionRepository; + + @Autowired + CredentialsVerifier credentialsVerifier; + + @Override + public VPSubmissionResponseDto submit(VPSubmissionDto vpSubmissionDto) { + vpSubmissionRepository.save(new VPSubmission(vpSubmissionDto.getState(), vpSubmissionDto.getVpToken(), vpSubmissionDto.getPresentationSubmission())); + return new VPSubmissionResponseDto("", "", ""); + + } + + private VPTokenResultDto processSubmission(VPSubmission vpSubmission, String transactionId) { + JSONObject vpProof = new JSONObject(vpSubmission.getVpToken()).getJSONObject(Constants.KEY_PROOF); + String jws = vpProof.getString(Constants.KEY_JWS); + String publicKeyPem = vpProof.getString(Constants.KEY_VERIFICATION_METHOD); + List verificationResults = null; + //TODO: Dynamic algo type + try { + Algorithm algorithm = Algorithm.RSA256(SecurityUtils.readX509PublicKey(publicKeyPem), null); + JWTVerifier verifier = JWT.require(algorithm).build(); + verifier.verify(jws); + + JSONArray verifiableCredentials = new JSONObject(vpSubmission.getVpToken()).getJSONArray(Constants.KEY_VERIFIABLE_CREDENTIAL); + verificationResults = getVCVerificationResults(verifiableCredentials); + boolean combinedVerificationStatus = true; + for (VCResult verificationResult : verificationResults) { + combinedVerificationStatus = combinedVerificationStatus && (verificationResult.getVerificationStatus() == VerificationStatus.SUCCESS); + } + if (!combinedVerificationStatus) { + throw new VerificationFailedException(); + } + return new VPTokenResultDto(transactionId, VPResultStatus.SUCCESS, verificationResults,null,null); + } catch (Exception e) { + log.error("Failed to verify",e); + return new VPTokenResultDto(transactionId, VPResultStatus.FAILED, verificationResults,null,null); + } + } + + @Override + public VPTokenResultDto getVPResult(List requestIds, String transactionId) { + VPSubmission vpSubmission = vpSubmissionRepository.findAllById(requestIds).getFirst(); + + if (vpSubmission == null){ + return null; + } + return processSubmission(vpSubmission,transactionId); + } + + private List getVCVerificationResults(JSONArray verifiableCredentials) { + List verificationResults = new ArrayList<>(); + for (Object verifiableCredential : verifiableCredentials) { + JSONObject credential = new JSONObject((String) verifiableCredential).getJSONObject(Constants.KEY_VERIFIABLE_CREDENTIAL).getJSONObject(Constants.KEY_CREDENTIAL); + VerificationResult verificationResult = credentialsVerifier.verify(credential.toString(), CredentialFormat.LDP_VC); + VerificationStatus singleVCVerification = Utils.getVerificationStatus(verificationResult); + verificationResults.add(new VCResult(credential.toString(),singleVCVerification)); + } + return verificationResults; + } +} + diff --git a/verify-service/src/main/java/io/inji/verify/shared/Constants.java b/verify-service/src/main/java/io/inji/verify/shared/Constants.java new file mode 100644 index 00000000..de37e993 --- /dev/null +++ b/verify-service/src/main/java/io/inji/verify/shared/Constants.java @@ -0,0 +1,27 @@ +package io.inji.verify.shared; + +public class Constants { + + public static int DEFAULT_EXPIRY = 300 * 1000; + public static final String RESPONSE_SUBMISSION_URI = "/direct-post"; + public static final String VP_DEFINITION_URI = "/vp-definition/"; + public static final String RESPONSE_TYPE = "vp_token"; + + public static final String TRANSACTION_ID_PREFIX = "txn"; + public static final String REQUEST_ID_PREFIX = "req"; + + //JSON KEYS + public static final String KEY_PROOF = "proof"; + public static final String KEY_JWS = "jws"; + public static final String KEY_VERIFICATION_METHOD = "verificationMethod"; + public static final String KEY_VERIFIABLE_CREDENTIAL = "verifiableCredential"; + public static final String KEY_CREDENTIAL = "credential"; + + //ERROR MESSAGES + public static final String ERR_100 = "Invalid transaction ID, No requests found for given transaction ID."; + public static final String ERR_101 = "No VP submission found for given transaction ID."; + + + + +} diff --git a/verify-service/src/main/java/io/inji/verify/spi/VCVerificationService.java b/verify-service/src/main/java/io/inji/verify/spi/VCVerificationService.java new file mode 100644 index 00000000..375954ca --- /dev/null +++ b/verify-service/src/main/java/io/inji/verify/spi/VCVerificationService.java @@ -0,0 +1,8 @@ +package io.inji.verify.spi; + +import io.inji.verify.dto.verification.VCVerificationStatusDto; + +public interface VCVerificationService { + + VCVerificationStatusDto verify(String vc); +} diff --git a/verify-service/src/main/java/io/inji/verify/spi/VPDefinitionService.java b/verify-service/src/main/java/io/inji/verify/spi/VPDefinitionService.java new file mode 100644 index 00000000..7ca4b246 --- /dev/null +++ b/verify-service/src/main/java/io/inji/verify/spi/VPDefinitionService.java @@ -0,0 +1,8 @@ +package io.inji.verify.spi; + +import io.inji.verify.dto.presentation.VPDefinitionResponseDto; + +public interface VPDefinitionService { + + VPDefinitionResponseDto getPresentationDefinition(String id); +} diff --git a/verify-service/src/main/java/io/inji/verify/spi/VerifiablePresentationRequestService.java b/verify-service/src/main/java/io/inji/verify/spi/VerifiablePresentationRequestService.java new file mode 100644 index 00000000..1e657f78 --- /dev/null +++ b/verify-service/src/main/java/io/inji/verify/spi/VerifiablePresentationRequestService.java @@ -0,0 +1,15 @@ +package io.inji.verify.spi; + +import io.inji.verify.dto.authorizationrequest.VPRequestCreateDto; +import io.inji.verify.dto.authorizationrequest.VPRequestResponseDto; +import io.inji.verify.dto.authorizationrequest.VPRequestStatusDto; + +import java.util.List; + +public interface VerifiablePresentationRequestService { + VPRequestResponseDto createAuthorizationRequest(VPRequestCreateDto vpRequestCreate); + + VPRequestStatusDto getCurrentRequestStatus(String requestId); + + List getLatestRequestIdFor(String transactionId); +} diff --git a/verify-service/src/main/java/io/inji/verify/spi/VerifiablePresentationSubmissionService.java b/verify-service/src/main/java/io/inji/verify/spi/VerifiablePresentationSubmissionService.java new file mode 100644 index 00000000..7ac74475 --- /dev/null +++ b/verify-service/src/main/java/io/inji/verify/spi/VerifiablePresentationSubmissionService.java @@ -0,0 +1,13 @@ +package io.inji.verify.spi; + +import io.inji.verify.dto.submission.VPSubmissionResponseDto; +import io.inji.verify.dto.submission.VPSubmissionDto; +import io.inji.verify.dto.submission.VPTokenResultDto; + +import java.util.List; + +public interface VerifiablePresentationSubmissionService { + VPSubmissionResponseDto submit(VPSubmissionDto vpSubmissionDto); + + VPTokenResultDto getVPResult(List requestId, String transactionId); +} diff --git a/verify-service/src/main/java/io/inji/verify/utils/SecurityUtils.java b/verify-service/src/main/java/io/inji/verify/utils/SecurityUtils.java new file mode 100644 index 00000000..b3dfafff --- /dev/null +++ b/verify-service/src/main/java/io/inji/verify/utils/SecurityUtils.java @@ -0,0 +1,41 @@ +package io.inji.verify.utils; + +import org.bouncycastle.util.io.pem.PemObject; +import org.bouncycastle.util.io.pem.PemReader; + +import java.io.StringReader; +import java.security.KeyFactory; +import java.security.SecureRandom; +import java.security.interfaces.RSAPublicKey; +import java.security.spec.X509EncodedKeySpec; +import java.util.Base64; + +public class SecurityUtils { + + public static String generateNonce() + { + SecureRandom random = new SecureRandom(); + byte[] randomBytes = new byte[16]; + random.nextBytes(randomBytes); + StringBuilder hexString = new StringBuilder(); + for (byte b : randomBytes) { + String hex = Integer.toHexString(0xff & b); + if (hex.length() == 1) { + hexString.append('0'); + } + hexString.append(hex); + } + return hexString.toString(); + } + + public static RSAPublicKey readX509PublicKey(String pem) throws Exception { + String decodedPem = new String(Base64.getDecoder().decode(pem)); + KeyFactory factory = KeyFactory.getInstance("RSA"); + PemReader pemReader = new PemReader(new StringReader(decodedPem)); + PemObject pemObject = pemReader.readPemObject(); + byte[] content = pemObject.getContent(); + X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(content); + return (RSAPublicKey) factory.generatePublic(pubKeySpec); + + } +} \ No newline at end of file diff --git a/verify-service/src/main/java/io/inji/verify/utils/Utils.java b/verify-service/src/main/java/io/inji/verify/utils/Utils.java new file mode 100644 index 00000000..afaf83e1 --- /dev/null +++ b/verify-service/src/main/java/io/inji/verify/utils/Utils.java @@ -0,0 +1,23 @@ +package io.inji.verify.utils; + +import io.inji.verify.enums.VerificationStatus; +import io.mosip.vercred.vcverifier.data.VerificationResult; +import io.mosip.vercred.vcverifier.constants.CredentialValidatorConstants; + +import java.util.UUID; + +public class Utils { + public static String generateID(String prefix){ + return prefix+"_"+UUID.randomUUID(); + } + + public static VerificationStatus getVerificationStatus(VerificationResult verificationResult){ + if (verificationResult.getVerificationStatus()){ + if (verificationResult.getVerificationErrorCode().equals(CredentialValidatorConstants.ERROR_CODE_VC_EXPIRED)){ + return VerificationStatus.EXPIRED; + } + return VerificationStatus.SUCCESS; + } + return VerificationStatus.INVALID; + } +} diff --git a/verify-service/src/main/java/io/mosip/verifyservice/controller/CredentialVerificationController.java b/verify-service/src/main/java/io/mosip/verifyservice/controller/CredentialVerificationController.java deleted file mode 100644 index 18fdf934..00000000 --- a/verify-service/src/main/java/io/mosip/verifyservice/controller/CredentialVerificationController.java +++ /dev/null @@ -1,15 +0,0 @@ -package io.mosip.verifyservice.controller; - -import io.mosip.vercred.vcverifier.constants.CredentialFormat; -import io.mosip.vercred.vcverifier.data.VerificationResult; -import org.springframework.web.bind.annotation.*; -import io.mosip.vercred.vcverifier.CredentialsVerifier; - -@RequestMapping(path = "/credential") -@RestController -public class CredentialVerificationController { - @PostMapping() - public VerificationResult verify(@RequestBody String vc) { - return new CredentialsVerifier().verify(vc, CredentialFormat.LDP_VC); - } -} \ No newline at end of file diff --git a/verify-service/src/main/resources/application.properties b/verify-service/src/main/resources/application.properties index f9c405de..b0b62eae 100644 --- a/verify-service/src/main/resources/application.properties +++ b/verify-service/src/main/resources/application.properties @@ -1,2 +1,8 @@ spring.application.name=verify-service -server.servlet.context-path=/v1/verify \ No newline at end of file +spring.datasource.driverClassName=org.h2.Driver +spring.jpa.database-platform=org.hibernate.dialect.H2Dialect +spring.jpa.hibernate.ddl-auto=create +server.servlet.context-path=/v1/verify +spring.datasource.url=jdbc:h2:mem:verifydb +spring.datasource.username=${DB_USERNAME} +spring.datasource.password=${DB_PW} \ No newline at end of file diff --git a/verify-service/src/main/resources/bootstrap.properties b/verify-service/src/main/resources/bootstrap.properties new file mode 100644 index 00000000..f9c405de --- /dev/null +++ b/verify-service/src/main/resources/bootstrap.properties @@ -0,0 +1,2 @@ +spring.application.name=verify-service +server.servlet.context-path=/v1/verify \ No newline at end of file diff --git a/verify-service/src/test/java/io/mosip/verifyservice/VerifyServiceApplicationTests.java b/verify-service/src/test/java/io/inji/verify/VerifyServiceApplicationTests.java similarity index 86% rename from verify-service/src/test/java/io/mosip/verifyservice/VerifyServiceApplicationTests.java rename to verify-service/src/test/java/io/inji/verify/VerifyServiceApplicationTests.java index db06e8b8..2783dd67 100644 --- a/verify-service/src/test/java/io/mosip/verifyservice/VerifyServiceApplicationTests.java +++ b/verify-service/src/test/java/io/inji/verify/VerifyServiceApplicationTests.java @@ -1,4 +1,4 @@ -package io.mosip.verifyservice; +package io.inji.verify; import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; diff --git a/verify-service/src/test/java/io/inji/verify/services/VCVerificationServiceImplTest.java b/verify-service/src/test/java/io/inji/verify/services/VCVerificationServiceImplTest.java new file mode 100644 index 00000000..8b8b6a64 --- /dev/null +++ b/verify-service/src/test/java/io/inji/verify/services/VCVerificationServiceImplTest.java @@ -0,0 +1,63 @@ +package io.inji.verify.services; + +import io.inji.verify.dto.verification.VCVerificationStatusDto; +import io.inji.verify.enums.VerificationStatus; +import io.mosip.vercred.vcverifier.CredentialsVerifier; +import io.mosip.vercred.vcverifier.constants.CredentialFormat; +import io.mosip.vercred.vcverifier.constants.CredentialValidatorConstants; +import io.mosip.vercred.vcverifier.data.VerificationResult; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.*; + + +public class VCVerificationServiceImplTest { + static VCVerificationServiceImpl service; + static CredentialsVerifier mockCredentialsVerifier; + + @BeforeAll + public static void beforeAll(){ + mockCredentialsVerifier = mock(CredentialsVerifier.class); + service = new VCVerificationServiceImpl(); + } + + @Test + public void shouldReturnSuccessForVerifiedVc() { + + VerificationResult mockResult = new VerificationResult(true, "",""); + when(mockCredentialsVerifier.verify(anyString(), any(CredentialFormat.class))).thenReturn(mockResult); + + VCVerificationServiceImpl service = new VCVerificationServiceImpl(); + service.credentialsVerifier = mockCredentialsVerifier; + + VCVerificationStatusDto statusDto = service.verify("some_vc"); + + assertEquals(VerificationStatus.SUCCESS, statusDto.getVerificationStatus()); + } + + @Test + public void shouldReturnExpiredForVerifiedVcWhichIsExpired() { + VerificationResult mockResult = new VerificationResult(true,"" , CredentialValidatorConstants.ERROR_CODE_VC_EXPIRED); + when(mockCredentialsVerifier.verify(anyString(), any(CredentialFormat.class))).thenReturn(mockResult); + + service.credentialsVerifier = mockCredentialsVerifier; + + VCVerificationStatusDto statusDto = service.verify("some_vc"); + assertEquals(VerificationStatus.EXPIRED, statusDto.getVerificationStatus()); + } + + @Test + public void shouldReturnInvalidForVcWhichIsInvalid() { + // ... similar to the previous tests, but with an invalid result + VerificationResult mockResult = new VerificationResult(false, "",""); + when(mockCredentialsVerifier.verify(anyString(), any(CredentialFormat.class))).thenReturn(mockResult); + + service.credentialsVerifier = mockCredentialsVerifier; + + VCVerificationStatusDto statusDto = service.verify("some_vc"); + // ... + assertEquals(VerificationStatus.INVALID, statusDto.getVerificationStatus()); + } +} \ No newline at end of file diff --git a/verify-service/src/test/java/io/inji/verify/services/VPDefinitionServiceImplTest.java b/verify-service/src/test/java/io/inji/verify/services/VPDefinitionServiceImplTest.java new file mode 100644 index 00000000..712903e5 --- /dev/null +++ b/verify-service/src/test/java/io/inji/verify/services/VPDefinitionServiceImplTest.java @@ -0,0 +1,51 @@ +package io.inji.verify.services; + +import io.inji.verify.dto.presentation.InputDescriptorDto; +import io.inji.verify.dto.presentation.VPDefinitionResponseDto; +import io.inji.verify.dto.presentation.SubmissionRequirementDto; +import io.inji.verify.repository.PresentationDefinitionRepository; +import io.inji.verify.models.PresentationDefinition; +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + + +class VPDefinitionServiceImplTest { + + + @Test + public void shouldReturnValidPresentationDefinitionForGivenId() { + PresentationDefinitionRepository mockRepository = mock(PresentationDefinitionRepository.class); + List mockInputDescriptorDtos = mock(); + List mockSubmissionRequirementDtos = mock(); + PresentationDefinition mockPresentationDefinition = new PresentationDefinition("test_id", mockInputDescriptorDtos, mockSubmissionRequirementDtos); + when(mockRepository.findById("test_id")).thenReturn(java.util.Optional.of(mockPresentationDefinition)); + + VPDefinitionServiceImpl service = new VPDefinitionServiceImpl(); + service.presentationDefinitionRepository = mockRepository; + + VPDefinitionResponseDto result = service.getPresentationDefinition("test_id"); + + assertNotNull(result); + assertEquals("test_id", result.getId()); + assertEquals(mockInputDescriptorDtos, result.getInputDescriptors()); + assertEquals(mockSubmissionRequirementDtos, result.getSubmissionRequirements()); + } + + @Test + public void shouldReturnNullIfPresentationDefinitionIsNotFoundForGivenId() { + PresentationDefinitionRepository mockRepository = mock(PresentationDefinitionRepository.class); + when(mockRepository.findById("non_existent_id")).thenReturn(java.util.Optional.empty()); + + VPDefinitionServiceImpl service = new VPDefinitionServiceImpl(); + service.presentationDefinitionRepository = mockRepository; + + VPDefinitionResponseDto result = service.getPresentationDefinition("non_existent_id"); + + assertNull(result); + } +} \ No newline at end of file diff --git a/verify-service/src/test/java/io/inji/verify/services/VerifiablePresentationRequestServiceImplTest.java b/verify-service/src/test/java/io/inji/verify/services/VerifiablePresentationRequestServiceImplTest.java new file mode 100644 index 00000000..277e7d14 --- /dev/null +++ b/verify-service/src/test/java/io/inji/verify/services/VerifiablePresentationRequestServiceImplTest.java @@ -0,0 +1,101 @@ +package io.inji.verify.services; + +import io.inji.verify.dto.authorizationrequest.VPRequestCreateDto; +import io.inji.verify.dto.authorizationrequest.VPRequestResponseDto; +import io.inji.verify.dto.authorizationrequest.VPRequestStatusDto; +import io.inji.verify.dto.presentation.InputDescriptorDto; +import io.inji.verify.dto.presentation.VPDefinitionResponseDto; +import io.inji.verify.dto.presentation.SubmissionRequirementDto; +import io.inji.verify.repository.AuthorizationRequestCreateResponseRepository; +import io.inji.verify.repository.PresentationDefinitionRepository; +import io.inji.verify.enums.VPRequestStatus; +import io.inji.verify.models.AuthorizationRequestCreateResponse; +import io.inji.verify.models.PresentationDefinition; +import io.inji.verify.repository.VPSubmissionRepository; +import io.inji.verify.shared.Constants; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import java.time.Instant; +import java.util.List; +import java.util.Optional; + +import static org.mockito.Mockito.*; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +class VerifiablePresentationRequestServiceImplTest { + static VerifiablePresentationRequestServiceImpl service; + static AuthorizationRequestCreateResponseRepository mockAuthorizationRequestCreateResponseRepository; + static PresentationDefinitionRepository mockPresentationDefinitionRepository; + static VPSubmissionRepository mockVPSubmissionRepository; + @BeforeAll + public static void beforeAll(){ + mockPresentationDefinitionRepository = mock(PresentationDefinitionRepository.class); + mockAuthorizationRequestCreateResponseRepository = mock(AuthorizationRequestCreateResponseRepository.class); + mockVPSubmissionRepository = mock(VPSubmissionRepository.class); + service = new VerifiablePresentationRequestServiceImpl(); + service.presentationDefinitionRepository = mockPresentationDefinitionRepository; + service.authorizationRequestCreateResponseRepository = mockAuthorizationRequestCreateResponseRepository; + service.vpSubmissionRepository = mockVPSubmissionRepository; + + } + @Test + public void shouldCreateNewAuthorizationRequest() { + when(mockPresentationDefinitionRepository.save(any(PresentationDefinition.class))).thenReturn(null); + when(mockAuthorizationRequestCreateResponseRepository.save(any(AuthorizationRequestCreateResponse.class))).thenReturn(null); + + VPRequestCreateDto vpRequestCreateDto = new VPRequestCreateDto(); + vpRequestCreateDto.setTransactionId("test_transaction_id"); + vpRequestCreateDto.setClientId("test_client_id"); + List mockInputDescriptorDtos = mock(); + List mockSubmissionRequirementDtos = mock(); + vpRequestCreateDto.setPresentationDefinition(new VPDefinitionResponseDto("test_id", mockInputDescriptorDtos, mockSubmissionRequirementDtos)); + + + VPRequestResponseDto responseDto = service.createAuthorizationRequest(vpRequestCreateDto); + + assertNotNull(responseDto); + assertEquals("test_transaction_id", responseDto.getTransactionId()); + assertNotNull(responseDto.getRequestId()); + assertNotNull(responseDto.getAuthorizationDetails()); + assertTrue(responseDto.getExpiresAt() > Instant.now().toEpochMilli()); + } + @Test + public void shouldCreateAuthorizationRequestWithMissingTransactionId() { + VPRequestCreateDto vpRequestCreateDto = new VPRequestCreateDto(); + vpRequestCreateDto.setClientId("test_client_id"); + List mockInputDescriptorDtos = mock(); + List mockSubmissionRequirementDtos = mock(); + vpRequestCreateDto.setPresentationDefinition(new VPDefinitionResponseDto("test_id", mockInputDescriptorDtos, mockSubmissionRequirementDtos)); + + VPRequestResponseDto responseDto = service.createAuthorizationRequest(vpRequestCreateDto); + + assertNotNull(responseDto); + assertTrue(responseDto.getTransactionId().startsWith(Constants.TRANSACTION_ID_PREFIX)); + } + + @Test + public void shouldGetCurrentAuthorizationRequestStateForExistingRequest() { + AuthorizationRequestCreateResponse mockResponse = new AuthorizationRequestCreateResponse("req_id", "tx_id", null, Instant.now().toEpochMilli()+10000); + when(mockAuthorizationRequestCreateResponseRepository.findById("req_id")).thenReturn(java.util.Optional.of(mockResponse)); + when(mockVPSubmissionRepository.findById("req_id")).thenReturn(Optional.empty()); + + VPRequestStatusDto vpRequestStatusDto = service.getCurrentRequestStatus("req_id"); + + assertEquals(VPRequestStatus.ACTIVE, vpRequestStatusDto.getStatus()); + } + + @Test + public void shouldGetCurrentAuthorizationRequestStateForNonexistentRequest() { + when(mockVPSubmissionRepository.findById("req_id")).thenReturn(Optional.empty()); + AuthorizationRequestCreateResponse mockResponse = new AuthorizationRequestCreateResponse("req_id", "tx_id", null, Instant.now().toEpochMilli()+10000); + when(mockAuthorizationRequestCreateResponseRepository.findById("req_id")).thenReturn(java.util.Optional.of(mockResponse)); + + + VPRequestStatusDto vpRequestStatusDto = service.getCurrentRequestStatus("nonexistent_id"); + + assertNull(vpRequestStatusDto); + } +} \ No newline at end of file diff --git a/verify-service/src/test/java/io/inji/verify/utils/SecurityUtilsTest.java b/verify-service/src/test/java/io/inji/verify/utils/SecurityUtilsTest.java new file mode 100644 index 00000000..68813ec3 --- /dev/null +++ b/verify-service/src/test/java/io/inji/verify/utils/SecurityUtilsTest.java @@ -0,0 +1,37 @@ +package io.inji.verify.utils; + +import static org.junit.jupiter.api.Assertions.*; +import org.junit.jupiter.api.Test; + +import java.security.interfaces.RSAPublicKey; +import java.util.Base64; + +public class SecurityUtilsTest { + + @Test + public void shouldNotGenerateSameNonce() { + String nonce1 = SecurityUtils.generateNonce(); + String nonce2 = SecurityUtils.generateNonce(); + + assertNotEquals(nonce1, nonce2); + assertEquals(32, nonce1.length()); + } + + @Test + public void shouldNotReturnNullForValidPublicKey() throws Exception { + String pemString = "-----BEGIN PUBLIC KEY-----\n" + + "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyqvyIzBsuGyakCfSN4hw\n"+ + "Ozh+vGbq5ZExpS5qPRi6Lpns3Bx+AgUGAM4OfY9DOt8VuFNLmwbsjJt+WuyqAu1a\n"+ + "GIwWyRWjcszDsyorRtSGDzCVLspk9AH3Dp0QPO1eIlzQD69iWlMUZayre1S1b/IK\n"+ + "maCkFxpfDqS+fF8Sm9hp3OLjUsXH9/o2aGkuo1YspbyuWlcj4jaSYrZZ8szKhQqk\n"+ + "r+Hl6bS6uUuoKWKENQGP7HJMChM29ITnrDCf9ZdpLW5h/q2656ST20+wRHfOwNuT\n"+ + "Q8tqKn8P0B00vto8bEhadIpj53efNTTMmP6fnLhFEX+xOWVp4lJi8qM4Y0UMbbnx\n"+ + "ewIDAQAB\n"+ + "-----END PUBLIC KEY-----"; + byte[] encoded = Base64.getEncoder().encode(pemString.getBytes()); + + RSAPublicKey publicKey = SecurityUtils.readX509PublicKey(new String(encoded)); + + assertNotNull(publicKey); + } +} \ No newline at end of file diff --git a/verify-service/src/test/java/io/inji/verify/utils/UtilsTest.java b/verify-service/src/test/java/io/inji/verify/utils/UtilsTest.java new file mode 100644 index 00000000..98f5d3b2 --- /dev/null +++ b/verify-service/src/test/java/io/inji/verify/utils/UtilsTest.java @@ -0,0 +1,46 @@ +package io.inji.verify.utils; + +import io.mosip.vercred.vcverifier.constants.CredentialValidatorConstants; +import io.mosip.vercred.vcverifier.data.VerificationResult; +import io.inji.verify.enums.VerificationStatus; + +import static org.junit.jupiter.api.Assertions.*; + +import org.junit.jupiter.api.Test; + +public class UtilsTest { + + @Test + public void shouldGenerateIDWithGivenPrefix() { + String prefix = "TEST_"; + String id = Utils.generateID(prefix); + + assertTrue(id.startsWith(prefix)); + // Assert that the generated ID contains a UUID + assertTrue(id.contains("-")); + } + + @Test + public void shouldReturnVerificationStatusSuccessIfVCVerificationIsSuccessful() { + VerificationResult successResult = new VerificationResult(true, "",""); + VerificationStatus status = Utils.getVerificationStatus(successResult); + + assertEquals(VerificationStatus.SUCCESS, status); + } + + @Test + public void shouldReturnVerificationStatusExpiredIfVCIsExpired() { + VerificationResult expiredResult = new VerificationResult(true,"", CredentialValidatorConstants.ERROR_CODE_VC_EXPIRED); + VerificationStatus status = Utils.getVerificationStatus(expiredResult); + + assertEquals(VerificationStatus.EXPIRED, status); + } + + @Test + public void shouldReturnVerificationStatusFailedIfVCVerificationIsFailed() { + VerificationResult invalidResult = new VerificationResult(false, "",""); + VerificationStatus status = Utils.getVerificationStatus(invalidResult); + + assertEquals(VerificationStatus.INVALID, status); + } +} \ No newline at end of file