Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add specific version for lombok and improved logging of Java Springboot Example #371

Merged
merged 7 commits into from
Oct 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .cargo/config
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
[target.i686-linux-android]
linker = "i686-linux-android16-clang"
linker = "i686-linux-android19-clang"

[target.armv7-linux-androideabi]
linker = "armv7a-linux-androideabi16-clang"
linker = "armv7a-linux-androideabi19-clang"

[target.aarch64-linux-android]
linker = "aarch64-linux-android21-clang"
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ jobs:
- name: Install Rust old stable with incremental compilation
uses: actions-rs/toolchain@v1
with:
toolchain: 1.66.0
toolchain: 1.70.0
profile: minimal
default: true

Expand Down Expand Up @@ -117,13 +117,13 @@ jobs:
- name: Setup Android SDK
uses: android-actions/setup-android@v2
- name: Install NDK
run: sdkmanager --install "build-tools;29.0.3" "ndk;22.0.7026061" "cmdline-tools;latest"
run: sdkmanager --install "build-tools;33.0.2" "ndk;25.2.9519653" "cmdline-tools;latest"
- name: Install gcc-multilib
run: |
sudo apt update
sudo apt install gcc-multilib -y
- name: Build Android Archive
run: AR_i686_linux_android=$ANDROID_SDK_ROOT/ndk/22.0.7026061/toolchains/llvm/prebuilt/linux-x86_64/i686-linux-android/bin/ar PATH=$ANDROID_SDK_ROOT/ndk/22.0.7026061/toolchains/llvm/prebuilt/linux-x86_64/bin:$PATH TARGET_CC=$(which clang) cargo build --lib --target i686-linux-android
run: AR=$ANDROID_SDK_ROOT/ndk/25.2.9519653/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ar RANLIB=$ANDROID_SDK_ROOT/ndk/25.2.9519653/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ranlib TARGET_CC=$ANDROID_SDK_ROOT/ndk/25.2.9519653/toolchains/llvm/prebuilt/linux-x86_64/bin/i686-linux-android19-clang PATH=$ANDROID_SDK_ROOT/ndk/25.2.9519653/toolchains/llvm/prebuilt/linux-x86_64/bin:$PATH cargo build --lib --target i686-linux-android

test_http:
runs-on: ubuntu-latest
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/target
Cargo.lock
__pycache__/
*~
3 changes: 1 addition & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@

[![](https://img.shields.io/github/workflow/status/spruceid/didkit/ci)](https://github.com/spruceid/didkit/actions?query=workflow%3Aci+branch%3Amain) [![](https://img.shields.io/badge/Docker-19.03.x-blue)](https://www.docker.com/) [![](https://img.shields.io/badge/Rust-v1.51.0-orange)](https://www.rust-lang.org/) [![](https://img.shields.io/badge/ssi-v0.1-green)](https://www.github.com/spruceid/ssi) [![](https://img.shields.io/badge/License-Apache--2.0-green)](https://github.com/spruceid/didkit/blob/main/LICENSE) [![](https://img.shields.io/twitter/follow/spruceid?label=Follow&style=social)](https://twitter.com/spruceid)
[![](https://img.shields.io/github/workflow/status/spruceid/didkit/ci)](https://github.com/spruceid/didkit/actions?query=workflow%3Aci+branch%3Amain) [![](https://img.shields.io/badge/Docker-19.03.x-blue)](https://www.docker.com/) [![](https://img.shields.io/badge/ssi-v0.1-green)](https://www.github.com/spruceid/ssi) [![](https://img.shields.io/badge/License-Apache--2.0-green)](https://github.com/spruceid/didkit/blob/main/LICENSE) [![](https://img.shields.io/twitter/follow/spruceid?label=Follow&style=social)](https://twitter.com/spruceid)

Check out the DIDKit documentation [here](https://spruceid.dev/didkit/didkit/).

Expand Down
15 changes: 15 additions & 0 deletions examples/java-springboot/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
<version>1.18.20</version>
</dependency>

<dependency>
Expand All @@ -89,6 +90,20 @@
<scope>system</scope>
<systemPath>${basedir}/didkit.jar</systemPath>
</dependency>

<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.21.0</version>
</dependency>

<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.21.0</version>
</dependency>


</dependencies>

<build>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.slf4j.Logger;

@Configuration
public class WebConfig {

@Bean
public BCryptPasswordEncoder bCryptPasswordEncoder() {
return new BCryptPasswordEncoder();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,16 @@
import java.util.Map;
import java.util.UUID;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;


@RestController
@AllArgsConstructor
public class CredentialOfferController {
private final UserService userService;
private final StringRedisTemplate redisTemplate;
private static Logger logger = LogManager.getLogger();

private static final DateTimeFormatter dateFormat = DateTimeFormatter.ISO_INSTANT.withZone(ZoneId.from(ZoneOffset.UTC));

Expand All @@ -40,6 +45,7 @@ public CredentialOffer credentialOfferGet(
final Resource keyFile;
final String key;
final String issuer;
logger.info("GET /credential-offer/" + token);

try {
keyFile = new FileSystemResource(Resources.key);
Expand Down Expand Up @@ -93,6 +99,7 @@ public Map<String, Object> credentialOfferPost(
@PathVariable("token") String token,
@RequestParam("subject_id") String did
) throws Exception {
logger.info("/credential-offer/" + token);
final String username = redisTemplate.opsForValue().get(token);
final User user = (User) userService.loadUserByUsername(username);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,16 @@
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;


@RestController
@AllArgsConstructor
public class VerifiablePresentationRequestController {
private final UserService userService;
private final StringRedisTemplate redisTemplate;
private static Logger logger = LogManager.getLogger();

@Autowired
private final ConcurrentHashMap<String, WebSocketSession> sessionMap;
Expand All @@ -43,6 +47,7 @@ public class VerifiablePresentationRequestController {
public VerifiablePresentationRequest vpRequestGet(
@PathVariable("challenge") String challenge
) {
logger.info("GET /verifiable-presentation-request/" + challenge);
return new VerifiablePresentationRequest(
"VerifiablePresentationRequest",
Collections.singletonList(new VerifiablePresentationRequestQuery(
Expand All @@ -66,35 +71,46 @@ public void vpRequestPost(
@PathVariable("challenge") String challenge,
@RequestParam("presentation") String presentation
) throws Exception {
logger.info("POST /verifiable-presentation-request/" + challenge);
final Resource keyFile;
final String key;

logger.info("Attempting to load key");
try {
keyFile = new FileSystemResource(Resources.key);
key = Files.readString(keyFile.getFile().toPath());
} catch (Exception e) {
logger.error("POST verifiable-presentation-request failed to load key");
throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, "Failed to load key");
}

logger.info("VerifiablePresentation.verifyPresentation");
final Map<String, Object> vc = VerifiablePresentation.verifyPresentation(key, presentation, challenge);
final Map<String, Object> credentialSubject = (Map<String, Object>) vc.get("credentialSubject");

final String username = credentialSubject.get("alumniOf").toString();
logger.info("userService.loadUserByUsername");
final User user = (User) userService.loadUserByUsername(username);

final String uuid = UUID.randomUUID().toString();
redisTemplate.opsForValue().set(uuid, user.getUsername());
redisTemplate.expire(uuid, Duration.ofSeconds(90));

if (sessionMap.containsKey(challenge)) {
logger.info("SessionMap has a challenge");
try {
logger.info("Trying to send message");
sessionMap.get(challenge).sendMessage(new TextMessage(uuid));
} catch (Exception e) {
logger.error("POST Failed to return sign in token");
throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, "Failed to return sign in token");
}
sessionMap.remove(challenge);
} else {
logger.info("SessionMap does not have a challenge");
logger.error("POST invalid or expired token");
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Invalid or expired token");
}
logger.info("Success");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,17 @@
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;


@RestController
public class VersionController {
private static Logger logger = LogManager.getLogger();

@RequestMapping("/version")
public String version() {
logger.info("GET /version");
return DIDKit.getVersion();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.time.Duration;
import java.util.UUID;

Expand All @@ -22,20 +25,24 @@
public class UserController {
private final UserService userService;
private final StringRedisTemplate redisTemplate;
private static Logger logger = LogManager.getLogger();

@GetMapping("/sign-up")
String signUpGet(User user) {
logger.info("GET /sign-up");
return "sign-up";
}

@PostMapping("/sign-up")
String signUpPost(User user) {
logger.info("POST /sign-up");
userService.signUp(user);
return "redirect:/sign-in";
}

@GetMapping("/sign-in")
ModelAndView signIn() throws Exception {
logger.info("GET /sign-in");
final String uuid = UUID.randomUUID().toString();
final String url = "https://" + Resources.baseUrl + "/verifiable-presentation-request/" + uuid;
final ModelAndView model = QRCode.getModelAndView("sign-in", url);
Expand All @@ -47,6 +54,7 @@ ModelAndView signIn() throws Exception {
ModelAndView credential(
@AuthenticationPrincipal User user
) throws Exception {
logger.info("GET /credential");
final String uuid = UUID.randomUUID().toString();
redisTemplate.opsForValue().set(uuid, user.getUsername());
redisTemplate.expire(uuid, Duration.ofSeconds(90));
Expand All @@ -60,6 +68,7 @@ ModelAndView credentialOffer(
@RequestParam("did") String did,
ModelAndView model
) throws Exception {
logger.info("POST /credential");
final String credential = userService.issueCredential(did, user);
model.addObject("credential", credential);
return model;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,28 +6,40 @@
import org.springframework.http.HttpStatus;
import org.springframework.web.server.ResponseStatusException;

import java.util.AbstractList;
import java.util.List;
import java.util.Map;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;


public class VerifiablePresentation {
private static Logger logger = LogManager.getLogger();

public static Map<String, Object> verifyPresentation(
final String key,
final String presentation,
final String challenge
) throws Exception {
logger.info("Converting String VP into Map<String, Object>");
logger.info("VP: " + presentation);
final ObjectMapper mapper = new ObjectMapper();

final Map<String, Object> presentationMap = mapper.readValue(presentation, new TypeReference<>() {
});
final Map<String, Object> presentationMap =
mapper.readValue(presentation, new TypeReference<>() {});

return VerifiablePresentation.verifyPresentation(key, presentationMap, challenge);
return VerifiablePresentation
.verifyPresentation(key, presentationMap, challenge);
}

public static Map<String, Object> verifyPresentation(
final String key,
final Map<String, Object> presentation,
final String challenge
) {
logger.info("Attempting to verify Map presentation");

final ObjectMapper mapper = new ObjectMapper();

try {
Expand All @@ -40,20 +52,29 @@ public static Map<String, Object> verifyPresentation(
final String vpStr = mapper.writeValueAsString(presentation);
final String optionsStr = mapper.writeValueAsString(options);

logger.info("vpStr: " + vpStr);
logger.info("optionsStr: " + optionsStr);


final String result = DIDKit.verifyPresentation(vpStr, optionsStr);
final Map<String, Object> resultMap = mapper.readValue(result, new TypeReference<>() {
});
logger.info("DIDKit.verifyPresentation result: " + result);
final Map<String, Object> resultMap =
mapper.readValue(result, new TypeReference<>() { });

if (((List<String>) resultMap.get("errors")).size() > 0) {
System.out.println("[ERROR] VP: " + resultMap.get("errors"));
logger.error("VP: " + resultMap.get("errors"));
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Invalid presentation");
}
} catch (Exception e) {
logger.error("Failed to verify presentation: " + e.toString());
throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, "Failed to verify presentation");
}

//Select the first vc if we have multiple in the presentation
final Object vcs = presentation.get("verifiableCredential");
final Map<String, Object> vc = (Map<String, Object>) (vcs instanceof Object[] ? ((Object[]) vcs)[0] : vcs);
logger.info("vcs type: " + vcs.getClass());
//final Map<String, Object> vc = (Map<String, Object>) (vcs instanceof Object[] ? ((Object[]) vcs)[0] : vcs);
final Map<String, Object> vc = getFirstVc(vcs);

try {
final DIDKitOptions options = new DIDKitOptions(
Expand All @@ -79,4 +100,22 @@ public static Map<String, Object> verifyPresentation(

return vc;
}

private static Map<String, Object> getFirstVc(Object vcs) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

3 separate methods overloaded on the instance types would be preferable here.


if(vcs instanceof Object[]) {
Object r = ((Object[]) vcs)[0];
logger.info("r type: " + r.getClass());
return (Map<String, Object>) r;
}
else if(vcs instanceof AbstractList) {
Object r = ((AbstractList) vcs).get(0);
logger.info("r type: " + r.getClass());
return (Map<String, Object>) r;
}
else {
logger.info("vc type: " + vcs.getClass());
return (Map<String, Object>) vcs;
}
}
}
4 changes: 2 additions & 2 deletions http/src/credentials.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use anyhow::Context;
use axum::{http::StatusCode, Extension, Json};
use didkit::{
ssi::ldp::{now_ms, Error as LdpError},
ssi::ldp::{now_ns, Error as LdpError},
ContextLoader, CredentialOrJWT, JWTOrLDPOptions, ProofFormat, VerifiableCredential,
VerificationResult, DID_METHODS,
};
Expand Down Expand Up @@ -42,7 +42,7 @@ pub async fn issue(
None => return Err((StatusCode::NOT_FOUND, "Missing key".to_string()).into()),
};
if credential.issuance_date.is_none() {
credential.issuance_date = Some(now_ms().into());
credential.issuance_date = Some(now_ns().into());
}
if let Err(e) = credential.validate_unsigned() {
return Err((StatusCode::BAD_REQUEST, e.to_string()).into());
Expand Down
Loading