diff --git a/README_did_web.md b/README_did_web.md index 8f51ca75a..c4dedea96 100644 --- a/README_did_web.md +++ b/README_did_web.md @@ -28,9 +28,7 @@ Following tools the MIW development team used successfully: 5. set ORG_GRADLE_PROJECT_githubUserName and ORG_GRADLE_PROJECT_githubToken values in [dev.env](dev-assets%2Fdid-web%2Fdev.env) 6. Setup [dev.env](dev-assets%2Fdid-web%2Fdev.env) values either in application.yaml or in IDE -7. -Run [ManagedIdentityWalletsApplication.java](src%2Fmain%2Fjava%2Forg%2Feclipse%2Ftractusx%2Fmanagedidentitywallets%2FManagedIdentityWalletsApplication.java) -in IDE +7. Run [ManagedIdentityWalletsApplication.java](src%2Fmain%2Fjava%2Forg%2Feclipse%2Ftractusx%2Fmanagedidentitywallets%2FManagedIdentityWalletsApplication.java) in IDE 8. Open API doc on http://localhost:8080 9. Click on Authorize on swagger UI and on the dialog click again on Authorize. 10. Login with username=catena-x and password=password @@ -60,7 +58,7 @@ Currently the minimum is 80% | name | description | default value | |------------------------------|-----------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------| -| APPLICATION_PORT | port number of application | 8087 | +| APPLICATION_PORT | port number of application | 8080 | | APPLICATION_ENVIRONMENT | Environment of the application ie. local, dev, int and prod | local | | DB_HOST | Database host | localhost | | DB_PORT | Port of database | 5432 | @@ -88,4 +86,4 @@ Currently the minimum is 80% 1. https://www.testcontainers.org/modules/databases/postgres/ 2. https://github.com/dasniko/testcontainers-keycloak -3. https://github.com/smartSenseSolutions/smartsense-java-commons \ No newline at end of file +3. https://github.com/smartSenseSolutions/smartsense-java-commons diff --git a/dev-assets/did-web/dev.env b/dev-assets/did-web/dev.env index f408d87dd..6df97b82d 100644 --- a/dev-assets/did-web/dev.env +++ b/dev-assets/did-web/dev.env @@ -22,7 +22,7 @@ VC_EXPIRY_DATE=01-01-2025 SUPPORTED_FRAMEWORK_VC_TYPES=cx-behavior-twin=Behavior Twin,cx-pcf=PCF,cx-quality=Quality,cx-resiliency=Resiliency,cx-sustainability=Sustainability,cx-traceability=ID_3.0_Trace KEYCLOAK_REALM=miw_test KEYCLOAK_CLIENT_ID=miw_private_client -AUTH_SERVER_URL:http://localhost:8081 +AUTH_SERVER_URL=http://localhost:8081 ## Github user name ORG_GRADLE_PROJECT_githubUserName= diff --git a/dev-assets/did-web/miw_test_realm.json b/dev-assets/did-web/miw_test_realm.json index 3f67c7e3f..203954e74 100644 --- a/dev-assets/did-web/miw_test_realm.json +++ b/dev-assets/did-web/miw_test_realm.json @@ -866,11 +866,13 @@ "clientAuthenticatorType": "client-secret", "redirectUris": [ "http://localhost/*", - "http://localhost:8087/*" + "http://localhost:8087/*", + "http://localhost:8080/*" ], "webOrigins": [ "http://localhost", - "http://localhost:8087" + "http://localhost:8087", + "http://localhost:8080" ], "notBefore": 0, "bearerOnly": false, diff --git a/src/main/java/org/eclipse/tractusx/managedidentitywallets/controller/DidDocumentController.java b/src/main/java/org/eclipse/tractusx/managedidentitywallets/controller/DidDocumentController.java index 5cfdb90af..78650f991 100644 --- a/src/main/java/org/eclipse/tractusx/managedidentitywallets/controller/DidDocumentController.java +++ b/src/main/java/org/eclipse/tractusx/managedidentitywallets/controller/DidDocumentController.java @@ -22,6 +22,7 @@ package org.eclipse.tractusx.managedidentitywallets.controller; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; import org.eclipse.tractusx.managedidentitywallets.constant.RestURI; @@ -51,13 +52,13 @@ public class DidDocumentController { */ @Operation(description = "Resolve the DID document for a given DID or BPN", summary = "Resolve DID Document") @GetMapping(path = RestURI.DID_DOCUMENTS, produces = MediaType.APPLICATION_JSON_VALUE) - public ResponseEntity getDidDocument(@PathVariable(name = "identifier") String identifier) { + public ResponseEntity getDidDocument(@Parameter(description = "Did or BPN") @PathVariable(name = "identifier") String identifier) { return ResponseEntity.status(HttpStatus.OK).body(service.getDidDocument(identifier)); } @Operation(description = "Resolve the DID document for a given BPN", summary = "Resolve DID Document") @GetMapping(path = RestURI.DID_RESOLVE, produces = MediaType.APPLICATION_JSON_VALUE) - public ResponseEntity getDidResolve(@PathVariable(name = "bpn") String bpn) { + public ResponseEntity getDidResolve(@Parameter(description = "Did or BPN") @PathVariable(name = "bpn") String bpn) { return ResponseEntity.status(HttpStatus.OK).body(service.getDidDocument(bpn)); } } diff --git a/src/main/java/org/eclipse/tractusx/managedidentitywallets/controller/PresentationController.java b/src/main/java/org/eclipse/tractusx/managedidentitywallets/controller/PresentationController.java index c6a910e29..bed7f77d0 100644 --- a/src/main/java/org/eclipse/tractusx/managedidentitywallets/controller/PresentationController.java +++ b/src/main/java/org/eclipse/tractusx/managedidentitywallets/controller/PresentationController.java @@ -22,6 +22,7 @@ package org.eclipse.tractusx.managedidentitywallets.controller; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.ExampleObject; import io.swagger.v3.oas.annotations.tags.Tag; @@ -92,43 +93,65 @@ public ResponseEntity> createPresentation(@RequestBody Map> validatePresentation(@RequestBody Map data, - @RequestParam(name = "audience", required = false) String audience, - @RequestParam(name = "asJwt", required = false, defaultValue = "false") boolean asJwt, - @RequestParam(name = "withCredentialExpiryDate", required = false, defaultValue = "false") boolean withCredentialExpiryDate, - @RequestParam(name = "withCredentialsValidation", required = false, defaultValue = "false") boolean withCredentialsValidation + @Parameter(description = "Audience to validate in VP (Only supported in case of JWT formatted VP)") @RequestParam(name = "audience", required = false) String audience, + @Parameter(description = "Pass true in case of VP is in JWT format") @RequestParam(name = "asJwt", required = false, defaultValue = "false") boolean asJwt, + @Parameter(description = "Check expiry of VC(Only supported in case of JWT formatted VP)") @RequestParam(name = "withCredentialExpiryDate", required = false, defaultValue = "false") boolean withCredentialExpiryDate ) { - return ResponseEntity.status(HttpStatus.CREATED).body(presentationService.validatePresentation(data, asJwt, withCredentialExpiryDate, withCredentialsValidation)); + return ResponseEntity.status(HttpStatus.CREATED).body(presentationService.validatePresentation(data, asJwt, withCredentialExpiryDate, audience)); } } diff --git a/src/main/java/org/eclipse/tractusx/managedidentitywallets/controller/WalletController.java b/src/main/java/org/eclipse/tractusx/managedidentitywallets/controller/WalletController.java index e53eb5903..5eae366d5 100644 --- a/src/main/java/org/eclipse/tractusx/managedidentitywallets/controller/WalletController.java +++ b/src/main/java/org/eclipse/tractusx/managedidentitywallets/controller/WalletController.java @@ -22,6 +22,7 @@ package org.eclipse.tractusx.managedidentitywallets.controller; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.ExampleObject; import io.swagger.v3.oas.annotations.tags.Tag; @@ -56,6 +57,17 @@ public class WalletController extends BaseController { * @param request the request * @return the response entity */ + @io.swagger.v3.oas.annotations.parameters.RequestBody(content = { + @Content(examples = { + + @ExampleObject(name = "Create wallet with BPN", value = """ + { + "bpn": "BPNL000000000001", + "name": "smartSense" + } + """) + }) + }) @Operation(summary = "Create Wallet", description = "Permission: **add_wallets** \n\n Create a wallet and store it") @PostMapping(path = RestURI.WALLETS, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) public ResponseEntity createWallet(@Valid @RequestBody CreateWalletRequest request) { @@ -106,7 +118,8 @@ public ResponseEntity createWallet(@Valid @RequestBody CreateWalletReque } """)) }) - public ResponseEntity> storeCredential(@RequestBody Map data, @PathVariable(name = "identifier") String identifier, Principal principal) { + public ResponseEntity> storeCredential(@RequestBody Map data, + @Parameter(description = "Did or BPN") @PathVariable(name = "identifier") String identifier, Principal principal) { return ResponseEntity.status(HttpStatus.CREATED).body(service.storeCredential(data, identifier, getBPNFromToken(principal))); } @@ -120,7 +133,7 @@ public ResponseEntity> storeCredential(@RequestBody Map getWalletByIdentifier(@PathVariable(name = "identifier") String identifier, - @RequestParam(name = "withCredentials", defaultValue = "false") boolean withCredentials, + @Parameter(description = "Did or BPN") @RequestParam(name = "withCredentials", defaultValue = "false") boolean withCredentials, Principal principal) { return ResponseEntity.status(HttpStatus.OK).body(service.getWalletByIdentifier(identifier, withCredentials, getBPNFromToken(principal))); diff --git a/src/main/java/org/eclipse/tractusx/managedidentitywallets/service/PresentationService.java b/src/main/java/org/eclipse/tractusx/managedidentitywallets/service/PresentationService.java index 3e6f7398b..a5aaf25e4 100644 --- a/src/main/java/org/eclipse/tractusx/managedidentitywallets/service/PresentationService.java +++ b/src/main/java/org/eclipse/tractusx/managedidentitywallets/service/PresentationService.java @@ -38,6 +38,7 @@ import org.eclipse.tractusx.ssi.lib.exception.DidDocumentResolverNotRegisteredException; import org.eclipse.tractusx.ssi.lib.exception.JwtException; import org.eclipse.tractusx.ssi.lib.jwt.SignedJwtFactory; +import org.eclipse.tractusx.ssi.lib.jwt.SignedJwtValidator; import org.eclipse.tractusx.ssi.lib.jwt.SignedJwtVerifier; import org.eclipse.tractusx.ssi.lib.model.did.Did; import org.eclipse.tractusx.ssi.lib.model.did.DidParser; @@ -155,7 +156,7 @@ public Map createPresentation(Map data, boolean } - public Map validatePresentation(Map vp, boolean asJwt, boolean withCredentialExpiryDate, boolean withCredentialsValidation) { + public Map validatePresentation(Map vp, boolean asJwt, boolean withCredentialExpiryDate, String audience) { Map response = new HashMap<>(); if (asJwt) { @@ -165,9 +166,8 @@ public Map validatePresentation(Map vp, boolean response.put("vp", jwt); try { SignedJWT signedJWT = SignedJWT.parse(jwt); - //validate - //TODO need to verify with withCredentialExperationDate and withCredentialsValidation + //validate jwt signature DidWebParser didParser = new DidWebParser(); var httpClient = HttpClient.newHttpClient(); var enforceHttps = true; @@ -177,13 +177,25 @@ public Map validatePresentation(Map vp, boolean new DidWebDocumentResolver(httpClient, didParser, enforceHttps)); SignedJwtVerifier jwtVerifier = new SignedJwtVerifier(didDocumentResolverRegistry); + jwtVerifier.verify(signedJWT); - jwtVerifier.verify(signedJWT); - response.put("valid", true); + //validate audience + if (StringUtils.hasText(audience)) { + SignedJwtValidator jwtValidator = new SignedJwtValidator(); + jwtValidator.validateAudiences(signedJWT, audience); + } + //validate date + if (withCredentialExpiryDate) { + SignedJwtValidator jwtValidator = new SignedJwtValidator(); + jwtValidator.validateDate(signedJWT); + } + + response.put("valid", true); } catch (JwtException | DidDocumentResolverNotRegisteredException | ParseException e) { log.error("Can not verify VP as JWT ", e); + response.put("valid", false); } } else { diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index 97ac45cdf..9a9f338bb 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -72,7 +72,7 @@ miw: enabled: true realm: ${KEYCLOAK_REALM:miw_test} clientId: ${KEYCLOAK_CLIENT_ID:miw_private_client} - auth-server-url: ${AUTH_SERVER_URL:https://dev-auth.keenlyco.com} + auth-server-url: ${AUTH_SERVER_URL:https://localhost:8080} auth-url: ${miw.security.auth-server-url}/realms/${miw.security.realm}/protocol/openid-connect/auth token-url: ${miw.security.auth-server-url}/realms/${miw.security.realm}/protocol/openid-connect/token refresh-token-url: ${miw.security.token-url} \ No newline at end of file