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

Fix/oobi not found #594

Merged
merged 29 commits into from
Oct 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
9e7af48
fix: debug KeriWeb3Filter
jimcase Aug 14, 2024
f36f3a5
fix: debug keriVerifierBaseUrl
jimcase Aug 14, 2024
6431f2b
fix: compare user-verification and voting-app interaction with Keri s…
jimcase Aug 14, 2024
52d6fc8
fix: compare user-verification and voting-app interaction with Keri s…
jimcase Aug 14, 2024
0fb8b47
fix: handling oobi not found error
jimcase Aug 20, 2024
08c050e
fix: remove debug
jimcase Aug 20, 2024
2a5b97d
fix: remove debugs
jimcase Aug 20, 2024
a82dabc
fix: remove unnecessary port 4000
jimcase Aug 20, 2024
cdcb5d9
fix: debugging
jimcase Aug 21, 2024
aee0530
fix: debugging
jimcase Aug 21, 2024
ae4dfb4
fix: debugging test
jimcase Aug 21, 2024
a7786cb
fix: debugging test
jimcase Aug 21, 2024
68044f4
fix: doFilterInternal
jimcase Aug 21, 2024
e3284d5
fix: remove failed log
jimcase Aug 21, 2024
95c0dde
fix: add logs
jimcase Aug 21, 2024
eba26ec
fix: add logs
jimcase Aug 22, 2024
7640d17
fix: remove log
jimcase Aug 22, 2024
b7264bd
fix: remove logs
jimcase Aug 22, 2024
ac4c98c
fix: set logs
jimcase Aug 22, 2024
dc6a9b2
fix: set logs to keri verifier
jimcase Aug 22, 2024
31ac21e
fix: remove logs from keri verifier
jimcase Aug 22, 2024
bc945e3
feat: add key state endpoint in KeriVerificationClient
jimcase Aug 26, 2024
0bf8bf6
feat: add key state endpoint in KeriVerificationClient in voting-app …
jimcase Aug 26, 2024
497bf5c
Merge remote-tracking branch 'origin/main' into fix/oobi-not-found
jimcase Aug 29, 2024
6e4aa68
feat: new event
jimcase Sep 10, 2024
062a3e7
Merge remote-tracking branch 'origin/main' into fix/oobi-not-found
jimcase Sep 10, 2024
c73be34
feat: add TODO
jimcase Sep 10, 2024
1282436
fix: enum not null
jimcase Sep 12, 2024
315257b
fix: enum not null missing import
jimcase Sep 12, 2024
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
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,12 @@ def __init__(self, hby):
def on_get(self, req, resp):
# This should be a path param but is causing issues, query will do.
oobi = req.params.get('url')

if oobi is None or oobi == "":
raise falcon.HTTPBadRequest(description=f"required field url missing from request")

result = self.hby.db.roobi.get(keys=(oobi,))

if result:
resp.status = falcon.HTTP_200
resp.text = result.cid
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import static org.springframework.http.HttpMethod.GET;
import static org.springframework.http.HttpMethod.POST;
import static org.springframework.http.HttpStatus.BAD_REQUEST;
import static org.springframework.http.HttpStatus.NOT_FOUND;

@Component
@Slf4j
Expand Down Expand Up @@ -114,12 +115,14 @@ public Either<Problem, String> getOOBI(String oobi, Integer maxAttempts) {
while (attempt < attempts) {
try {
val response = restTemplate.exchange(url, GET, entity, String.class);

if (response.getStatusCode().is2xxSuccessful()) {
log.info("OOBI successfully retrieved after {} attempts", attempt+1);
return Either.right(response.getBody());
}
} catch (HttpClientErrorException e) {
if (e.getStatusCode() != BAD_REQUEST) {
if (e.getStatusCode() == NOT_FOUND) {
log.info("OOBI not found, continuing attempts... "+attempt);
} else {
return Either.left(Problem.builder()
.withTitle("OOBI_FETCH_ERROR")
.withDetail("Unable to fetch OOBI, reason: " + e.getMessage())
Expand All @@ -146,7 +149,91 @@ public Either<Problem, String> getOOBI(String oobi, Integer maxAttempts) {
return Either.left(Problem.builder()
.withTitle("OOBI_NOT_FOUND")
.withDetail("The OOBI was not found after " + attempts + " attempts.")
.withStatus(new HttpStatusAdapter(BAD_REQUEST))
.withStatus(new HttpStatusAdapter(NOT_FOUND))
.build());
}

public Either<Problem, Boolean> updateAndVerifyKeyState(String aid, Integer maxAttempts) {
val updateUrl = String.format("%s/keystate", keriVerifierBaseUrl);
val verifyUrl = String.format("%s/keystate/%s", keriVerifierBaseUrl, aid);

val headers = new HttpHeaders();
headers.add("Content-Type", "application/json");

val requestBody = new HashMap<String, String>();
requestBody.put("pre", aid);

val entity = new HttpEntity<Map<String, String>>(requestBody, headers);

// Attempt to update the key state
try {
val response = restTemplate.exchange(updateUrl, POST, entity, String.class);
if (response.getStatusCode().is2xxSuccessful()) {
log.info("Key state updated successfully for aid: {}", aid);
return verifyKeyState(verifyUrl, maxAttempts);
} else {
return Either.left(Problem.builder()
.withTitle("KEY_STATE_UPDATE_FAILED")
.withDetail("Failed to update key state.")
.withStatus(new HttpStatusAdapter(response.getStatusCode()))
.build());
}
} catch (HttpClientErrorException e) {
log.error("Unable to update key state, reason: {}", e.getMessage());
return Either.left(Problem.builder()
.withTitle("KEY_STATE_UPDATE_ERROR")
.withDetail("Unable to update key state, reason: " + e.getMessage())
.withStatus(new HttpStatusAdapter(e.getStatusCode()))
.build());
}
}

private Either<Problem, Boolean> verifyKeyState(String url, Integer maxAttempts) {
val headers = new HttpHeaders();
headers.add("Content-Type", "application/json");
val entity = new HttpEntity<Void>(headers);

int attempts = (maxAttempts == null) ? 1 : maxAttempts;
int attempt = 0;

while (attempt < attempts) {
try {
val response = restTemplate.exchange(url, GET, entity, String.class);
if (response.getStatusCode().is2xxSuccessful()) {
log.info("Key state verified successfully after {} attempts", attempt + 1);
return Either.right(true);
}
} catch (HttpClientErrorException e) {
if (e.getStatusCode() == NOT_FOUND) {
log.info("Key state not found, continuing attempts... " + (attempt + 1));
} else {
return Either.left(Problem.builder()
.withTitle("KEY_STATE_VERIFICATION_ERROR")
.withDetail("Unable to verify key state, reason: " + e.getMessage())
.withStatus(new HttpStatusAdapter(e.getStatusCode()))
.build());
}
}

attempt++;
if (attempt < attempts) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return Either.left(Problem.builder()
.withTitle("INTERRUPTED_ERROR")
.withDetail("Thread was interrupted while waiting to retry.")
.withStatus(new HttpStatusAdapter(NOT_FOUND))
.build());
}
}
}

return Either.left(Problem.builder()
.withTitle("KEY_STATE_VERIFICATION_FAILED")
.withDetail("The key state verification failed after " + attempts + " attempts.")
.withStatus(new HttpStatusAdapter(NOT_FOUND))
.build());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -428,9 +428,17 @@ private Either<Problem, IsVerifiedResponse> handleKeriVerification(DiscordCheckV

// Step 1: Check if OOBI is already registered
Either<Problem, String> oobiCheckResult = keriVerificationClient.getOOBI(oobi, 1);

if (oobiCheckResult.isRight()) {
log.info("OOBI already registered: {}", oobiCheckResult);
log.info("OOBI already registered: {}", oobiCheckResult.get());

// TODO: Review this implementation once the KERI watchers are operational.
// This solution is temporary and might need adjustments to integrate with the new KERI components
// Step 1.1:Update key state
Either<Problem, Boolean> keyStateUpdateResult = keriVerificationClient.updateAndVerifyKeyState(walletId, 60);
if (keyStateUpdateResult.isLeft()) {
return Either.left(keyStateUpdateResult.getLeft());
}

Either<Problem, Boolean> verificationResult = keriVerificationClient.verifySignature(walletId, signature, payload);

if (verificationResult.isLeft()) {
Expand Down Expand Up @@ -465,13 +473,18 @@ private Either<Problem, IsVerifiedResponse> handleKeriVerification(DiscordCheckV

log.info("OOBI registered successfully: {}", oobiM);

// Step 3: Attempt to verify OOBI registration up to 10 times
// Step 3: Attempt to verify OOBI registration up to 60 times
val oobiFetchResultE = keriVerificationClient.getOOBI(oobi, 60);
if (oobiFetchResultE.isLeft()) {
return Either.left(oobiFetchResultE.getLeft());
}

// Step 4: Verify signature after OOBI registration
// Step 4: Update key state
Either<Problem, Boolean> keyStateUpdateResult = keriVerificationClient.updateAndVerifyKeyState(walletId, 60);
if (keyStateUpdateResult.isLeft()) {
return Either.left(keyStateUpdateResult.getLeft());
}
// Step 5: Verify signature after OOBI registration
val verificationResultE = keriVerificationClient.verifySignature(walletId, signature, payload);
if (verificationResultE.isLeft()) {
return Either.left(verificationResultE.getLeft());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ max.pending.verification.attempts=${MAX_PENDING_VERIFICATION_ATTEMPTS:5}
spring.h2.console.enabled=${H2_CONSOLE_ENABLED:true}

phone.number.salt=${SALT:67274569c9671a4ae3f753b9647ca719}
discord.bot.eventId.binding=${DISCORD_BOT_EVENT_ID_BINDING:CF_SUMMIT_2024_10BCC}
discord.bot.eventId.binding=${DISCORD_BOT_EVENT_ID_BINDING:CF_SUMMIT_2024_15BCC}

discord.bot.username=${DISCORD_BOT_USERNAME:discord_bot}
discord.bot.password=${DISCORD_BOT_PASSWORD:test}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import static org.springframework.http.HttpMethod.GET;
import static org.springframework.http.HttpMethod.POST;
import static org.springframework.http.HttpStatus.BAD_REQUEST;
import static org.springframework.http.HttpStatus.NOT_FOUND;

@RequiredArgsConstructor
@Component
Expand Down Expand Up @@ -47,7 +48,6 @@ public Either<Problem, Boolean> verifySignature(String aid,

try {
val response = restTemplate.exchange(url, POST, entity, String.class);

if (response.getStatusCode().is2xxSuccessful()) {
return Either.right(true);
}
Expand Down Expand Up @@ -78,6 +78,7 @@ public Either<Problem, Boolean> registerOOBI(String oobi) {
requestBody.put("oobi", oobi);

val entity = new HttpEntity<Map<String, String>>(requestBody, headers);

try {
val response = restTemplate.exchange(url, POST, entity, String.class);

Expand Down Expand Up @@ -113,12 +114,14 @@ public Either<Problem, String> getOOBI(String oobi, Integer maxAttempts) {
while (attempt < attempts) {
try {
val response = restTemplate.exchange(url, GET, entity, String.class);

if (response.getStatusCode().is2xxSuccessful()) {
log.info("OOBI successfully retrieved after {} attempts", attempt+1);
return Either.right(response.getBody());
}
} catch (HttpClientErrorException e) {
if (e.getStatusCode() != BAD_REQUEST) {
if (e.getStatusCode() == NOT_FOUND) {
log.info("OOBI not found, continuing attempts...");
} else {
return Either.left(Problem.builder()
.withTitle("OOBI_FETCH_ERROR")
.withDetail("Unable to fetch OOBI, reason: " + e.getMessage())
Expand All @@ -145,8 +148,91 @@ public Either<Problem, String> getOOBI(String oobi, Integer maxAttempts) {
return Either.left(Problem.builder()
.withTitle("OOBI_NOT_FOUND")
.withDetail("The OOBI was not found after " + attempts + " attempts.")
.withStatus(new HttpStatusAdapter(BAD_REQUEST))
.withStatus(new HttpStatusAdapter(NOT_FOUND))
.build());
}

public Either<Problem, Boolean> updateAndVerifyKeyState(String aid, Integer maxAttempts) {
val updateUrl = String.format("%s/keystate", keriVerifierBaseUrl);
val verifyUrl = String.format("%s/keystate/%s", keriVerifierBaseUrl, aid);

val headers = new HttpHeaders();
headers.add("Content-Type", "application/json");

val requestBody = new HashMap<String, String>();
requestBody.put("pre", aid);

val entity = new HttpEntity<Map<String, String>>(requestBody, headers);

// Attempt to update the key state
try {
val response = restTemplate.exchange(updateUrl, POST, entity, String.class);
if (response.getStatusCode().is2xxSuccessful()) {
log.info("Key state updated successfully for aid: {}", aid);
return verifyKeyState(verifyUrl, maxAttempts);
} else {
return Either.left(Problem.builder()
.withTitle("KEY_STATE_UPDATE_FAILED")
.withDetail("Failed to update key state.")
.withStatus(new HttpStatusAdapter(response.getStatusCode()))
.build());
}
} catch (HttpClientErrorException e) {
log.error("Unable to update key state, reason: {}", e.getMessage());
return Either.left(Problem.builder()
.withTitle("KEY_STATE_UPDATE_ERROR")
.withDetail("Unable to update key state, reason: " + e.getMessage())
.withStatus(new HttpStatusAdapter(e.getStatusCode()))
.build());
}
}

private Either<Problem, Boolean> verifyKeyState(String url, Integer maxAttempts) {
val headers = new HttpHeaders();
headers.add("Content-Type", "application/json");
val entity = new HttpEntity<Void>(headers);

int attempts = (maxAttempts == null) ? 1 : maxAttempts;
int attempt = 0;

while (attempt < attempts) {
try {
val response = restTemplate.exchange(url, GET, entity, String.class);
if (response.getStatusCode().is2xxSuccessful()) {
log.info("Key state verified successfully after {} attempts", attempt + 1);
return Either.right(true);
}
} catch (HttpClientErrorException e) {
if (e.getStatusCode() == NOT_FOUND) {
log.info("Key state not found, continuing attempts... " + (attempt + 1));
} else {
return Either.left(Problem.builder()
.withTitle("KEY_STATE_VERIFICATION_ERROR")
.withDetail("Unable to verify key state, reason: " + e.getMessage())
.withStatus(new HttpStatusAdapter(e.getStatusCode()))
.build());
}
}

attempt++;
if (attempt < attempts) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return Either.left(Problem.builder()
.withTitle("INTERRUPTED_ERROR")
.withDetail("Thread was interrupted while waiting to retry.")
.withStatus(new HttpStatusAdapter(NOT_FOUND))
.build());
}
}
}

return Either.left(Problem.builder()
.withTitle("KEY_STATE_VERIFICATION_FAILED")
.withDetail("The key state verification failed after " + attempts + " attempts.")
.withStatus(new HttpStatusAdapter(NOT_FOUND))
.build());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ public class KeriWeb3Filter extends OncePerRequestFilter {
protected void doFilterInternal(HttpServletRequest req,
HttpServletResponse res,
FilterChain chain) throws ServletException, IOException {

val logonSystemM = loginSystemDetector.detect(req);
if (logonSystemM.isEmpty()) {
chain.doFilter(req, res);
Expand Down Expand Up @@ -125,53 +126,40 @@ protected void doFilterInternal(HttpServletRequest req,

// Step 1: Check if OOBI is already registered
Either<Problem, String> oobiCheckResult = keriVerificationClient.getOOBI(headerOobi, 1);
if (oobiCheckResult.isLeft()) {
sendBackProblem(objectMapper, res, oobiCheckResult.getLeft());
return;
}

// Log if OOBI is registered or not
log.info("OOBI status: {}", oobiCheckResult.get());
if (oobiCheckResult.isLeft()) {
log.info("OOBI not registered yet: {}", headerOobi);
// Step 2: Register OOBI if not already registered
val oobiRegistrationResultE = keriVerificationClient.registerOOBI(headerOobi);

if (oobiCheckResult.isRight()) {
log.info("OOBI already registered: {}", oobiCheckResult);
Either<Problem, Boolean> verificationResult = keriVerificationClient.verifySignature(headerAid, headerSignature, headerSignedJson);
if (oobiRegistrationResultE.isLeft()) {
sendBackProblem(objectMapper, res, oobiRegistrationResultE.getLeft());
return;
}

if (verificationResult.isEmpty()) {
val problem = Problem.builder()
.withTitle("KERI_SIGNATURE_VERIFICATION_FAILED")
.withDetail("Unable to verify KERI header signature, reason: " + verificationResult.swap().get().getDetail())
.withStatus(BAD_REQUEST)
.build();
log.info("OOBI registered successfully: {}", headerOobi);

sendBackProblem(objectMapper, res, problem);
// Step 3: Attempt to verify OOBI registration up to 60 times
val oobiFetchResultE = keriVerificationClient.getOOBI(headerOobi, 60);
if (oobiFetchResultE.isLeft()) {
sendBackProblem(objectMapper, res, oobiFetchResultE.getLeft());
return;
}
}

log.info("OOBI not registered yet: {}", headerOobi);
// Step 2: Register OOBI if not already registered
val oobiRegistrationResultE = keriVerificationClient.registerOOBI(headerOobi);

if (oobiRegistrationResultE.isLeft()) {
sendBackProblem(objectMapper, res, oobiRegistrationResultE.getLeft());
// Step 1.1:Update key state
Either<Problem, Boolean> keyStateUpdateResult = keriVerificationClient.updateAndVerifyKeyState(headerAid, 60);
if (keyStateUpdateResult.isLeft()) {
sendBackProblem(objectMapper, res, keyStateUpdateResult.getLeft());
return;
}

log.info("OOBI registered successfully: {}", headerOobi);

// Step 3: Attempt to verify OOBI registration up to 60 times
val oobiFetchResultE = keriVerificationClient.getOOBI(headerOobi, 60);
if (oobiFetchResultE.isLeft()) {
sendBackProblem(objectMapper, res, oobiFetchResultE.getLeft());
return;
}
Either<Problem, Boolean> verificationResult = keriVerificationClient.verifySignature(headerAid, headerSignature, headerSignedJson);

val keriVerificationResultE = keriVerificationClient.verifySignature(headerAid, headerSignature, headerSignedJson);
if (keriVerificationResultE.isEmpty()) {
if (verificationResult.isEmpty()) {
val problem = Problem.builder()
.withTitle("KERI_SIGNATURE_VERIFICATION_FAILED")
.withDetail("Unable to verify KERI header signature, reason: " + keriVerificationResultE.swap().get().getDetail())
.withDetail("Unable to verify KERI header signature, reason: " + verificationResult.swap().get().getDetail())
.withStatus(BAD_REQUEST)
.build();

Expand Down
Loading
Loading