Skip to content

Commit

Permalink
fix: add test and validation
Browse files Browse the repository at this point in the history
  • Loading branch information
mustafasalfiti authored and nitin-vavdiya committed May 14, 2024
1 parent bb0b30c commit 842e437
Show file tree
Hide file tree
Showing 7 changed files with 914 additions and 30 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ public class StringPool {
public static final String ALLOWED_VEHICLE_BRANDS = "allowedVehicleBrands";
public static final String VERIFIABLE_CREDENTIALS = "verifiableCredentials";
public static final String VP = "vp";
public static final String VC = "vc";
public static final String VALID = "valid";
public static final String VALIDATE_AUDIENCE = "validateAudience";
public static final String VALIDATE_EXPIRY_DATE = "validateExpiryDate";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@

package org.eclipse.tractusx.managedidentitywallets.service;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.nimbusds.jwt.SignedJWT;
import com.smartsensesolutions.java.commons.FilterRequest;
import com.smartsensesolutions.java.commons.base.repository.BaseRepository;
import com.smartsensesolutions.java.commons.base.service.BaseService;
Expand All @@ -29,6 +31,8 @@
import com.smartsensesolutions.java.commons.sort.Sort;
import com.smartsensesolutions.java.commons.sort.SortType;
import com.smartsensesolutions.java.commons.specification.SpecificationUtil;

import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.text.StringEscapeUtils;
Expand All @@ -40,6 +44,7 @@
import org.eclipse.tractusx.managedidentitywallets.dao.entity.Wallet;
import org.eclipse.tractusx.managedidentitywallets.dao.repository.HoldersCredentialRepository;
import org.eclipse.tractusx.managedidentitywallets.dao.repository.IssuersCredentialRepository;
import org.eclipse.tractusx.managedidentitywallets.dto.CredentialVerificationRequest;
import org.eclipse.tractusx.managedidentitywallets.dto.CredentialsResponse;
import org.eclipse.tractusx.managedidentitywallets.dto.IssueDismantlerCredentialRequest;
import org.eclipse.tractusx.managedidentitywallets.dto.IssueFrameworkCredentialRequest;
Expand All @@ -52,11 +57,15 @@
import org.eclipse.tractusx.ssi.lib.did.resolver.DidResolver;
import org.eclipse.tractusx.ssi.lib.did.web.DidWebResolver;
import org.eclipse.tractusx.ssi.lib.did.web.util.DidWebParser;
import org.eclipse.tractusx.ssi.lib.exception.proof.JwtExpiredException;
import org.eclipse.tractusx.ssi.lib.jwt.SignedJwtValidator;
import org.eclipse.tractusx.ssi.lib.jwt.SignedJwtVerifier;
import org.eclipse.tractusx.ssi.lib.model.did.DidDocument;
import org.eclipse.tractusx.ssi.lib.model.verifiable.credential.VerifiableCredential;
import org.eclipse.tractusx.ssi.lib.model.verifiable.credential.VerifiableCredentialSubject;
import org.eclipse.tractusx.ssi.lib.model.verifiable.credential.VerifiableCredentialType;
import org.eclipse.tractusx.ssi.lib.proof.LinkedDataProofValidation;
import org.eclipse.tractusx.ssi.lib.serialization.SerializeUtil;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.stereotype.Service;
Expand All @@ -66,7 +75,9 @@
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.net.http.HttpClient;
import java.text.ParseException;
import java.time.Instant;
import java.util.*;

Expand All @@ -75,6 +86,7 @@
*/
@Service
@Slf4j
@RequiredArgsConstructor
public class IssuersCredentialService extends BaseService<IssuersCredential, Long> {

/**
Expand All @@ -93,26 +105,7 @@ public class IssuersCredentialService extends BaseService<IssuersCredential, Lon

private final CommonService commonService;

/**
* Instantiates a new Issuers credential service.
*
* @param issuersCredentialRepository the issuers credential repository
* @param miwSettings the miw settings
* @param credentialSpecificationUtil the credential specification util
* @param walletKeyService the wallet key service
* @param holdersCredentialRepository the holders credential repository
* @param commonService the common service
*/
public IssuersCredentialService(IssuersCredentialRepository issuersCredentialRepository, MIWSettings miwSettings,
SpecificationUtil<IssuersCredential> credentialSpecificationUtil,
WalletKeyService walletKeyService, HoldersCredentialRepository holdersCredentialRepository, CommonService commonService) {
this.issuersCredentialRepository = issuersCredentialRepository;
this.miwSettings = miwSettings;
this.credentialSpecificationUtil = credentialSpecificationUtil;
this.walletKeyService = walletKeyService;
this.holdersCredentialRepository = holdersCredentialRepository;
this.commonService = commonService;
}
private final ObjectMapper objectMapper;


@Override
Expand Down Expand Up @@ -449,31 +442,105 @@ public CredentialsResponse issueCredentialUsingBaseWallet(String holderDid, Map<

return cr;
}


private JWTVerificationResult verifyVCAsJWT(String jwt, DidResolver didResolver, boolean withCredentialsValidation, boolean withCredentialExpiryDate) throws IOException, ParseException {
SignedJWT signedJWT = SignedJWT.parse(jwt);
Map<String, Object> claims = objectMapper.readValue(signedJWT.getPayload().toBytes(), Map.class);
String vcClaim = objectMapper.writeValueAsString(claims.get("vc"));
Map<String, Object> map = SerializeUtil.fromJson(vcClaim);
VerifiableCredential verifiableCredential = new VerifiableCredential(map);

//took this approach to avoid issues in sonarQube
return new JWTVerificationResult(validateSignature(withCredentialsValidation , signedJWT, didResolver) && validateJWTExpiryDate(withCredentialExpiryDate, signedJWT), verifiableCredential);

}

private record JWTVerificationResult(boolean valid, VerifiableCredential verifiableCredential) {

}

private boolean validateSignature(boolean withValidateSignature, SignedJWT signedJWT, DidResolver didResolver) {
if(!withValidateSignature) {
return true;
}
//validate jwt signature
try {
SignedJwtVerifier jwtVerifier = new SignedJwtVerifier(didResolver);
return jwtVerifier.verify(signedJWT);
} catch (Exception e) {
log.error("Can not verify signature of jwt", e);
return false;
}
}
private boolean validateJWTExpiryDate(boolean withExpiryDate , SignedJWT signedJWT) {
if(!withExpiryDate) {
return true;
}
try {
SignedJwtValidator jwtValidator = new SignedJwtValidator();
jwtValidator.validateDate(signedJWT);
return true;
} catch (Exception e) {
if (!(e instanceof JwtExpiredException)) {
log.error("Can not validate jwt expiry date ", e);
}
return false;
}
}

/**
* Credentials validation map.
*
* @param verificationRequest the verifiable credential
* @param withCredentialExpiryDate the with credential expiry date
* @return the map
*/
public Map<String, Object> credentialsValidation(CredentialVerificationRequest verificationRequest, boolean withCredentialExpiryDate) {
return credentialsValidation(verificationRequest, true, withCredentialExpiryDate);
}

/**
* Credentials validation map.
*
* @param data the data
* @param withCredentialExpiryDate the with credential expiry date
* @return the map
*/
@SneakyThrows
public Map<String, Object> credentialsValidation(Map<String, Object> data, boolean withCredentialExpiryDate) {
VerifiableCredential verifiableCredential = new VerifiableCredential(data);
public Map<String, Object> credentialsValidation(CredentialVerificationRequest verificationRequest, boolean withCredentialsValidation , boolean withCredentialExpiryDate) {
HttpClient httpClient = HttpClient.newBuilder()
.followRedirects(HttpClient.Redirect.ALWAYS)
.build();

DidResolver didResolver = new DidWebResolver(HttpClient.newHttpClient(), new DidWebParser(), miwSettings.enforceHttps());
DidResolver didResolver = new DidWebResolver(httpClient, new DidWebParser(), miwSettings.enforceHttps());
Map<String, Object> response = new TreeMap<>();
boolean valid;
VerifiableCredential verifiableCredential;
boolean dateValidation = true;

if (verificationRequest.containsKey(StringPool.VC_JWT_KEY)) {
JWTVerificationResult result = verifyVCAsJWT((String) verificationRequest.get(StringPool.VC_JWT_KEY), didResolver, withCredentialsValidation, withCredentialExpiryDate);
verifiableCredential = result.verifiableCredential;
valid = result.valid;
} else {

LinkedDataProofValidation proofValidation = LinkedDataProofValidation.newInstance(didResolver);
verifiableCredential = new VerifiableCredential(verificationRequest);
LinkedDataProofValidation proofValidation = LinkedDataProofValidation.newInstance(didResolver);

boolean valid = proofValidation.verify(verifiableCredential);

Map<String, Object> response = new TreeMap<>();
if (withCredentialsValidation) {
valid = proofValidation.verify(verifiableCredential);
} else {
valid = true;
}

//check expiry
boolean dateValidation = CommonService.validateExpiry(withCredentialExpiryDate, verifiableCredential, response);
dateValidation = CommonService.validateExpiry(withCredentialExpiryDate, verifiableCredential,
response);
}

response.put(StringPool.VALID, valid && dateValidation);
response.put("vc", verifiableCredential);
response.put(StringPool.VC, verificationRequest);

return response;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;
import java.util.regex.Pattern;

Expand Down Expand Up @@ -193,7 +194,7 @@ public static String vcAsJwt(Wallet issuerWallet, Wallet holderWallet, Verifiabl
x25519PrivateKey privateKey = walletKeyService.getPrivateKeyByWalletId(issuerWallet.getId());
// JWT Factory

SignedJWT vcJWT = vcFactory.createVCJwt(issuerDid, holderDid, Date.from(vc.getExpirationDate()), vc,
SignedJWT vcJWT = vcFactory.createVCJwt(issuerDid, holderDid, vc,
privateKey,
walletKeyService.getWalletKeyIdByWalletId(issuerWallet.getId()));

Expand Down
Loading

0 comments on commit 842e437

Please sign in to comment.