aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/com/juick/ActivityPubManager.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/com/juick/ActivityPubManager.java')
-rw-r--r--src/main/java/com/juick/ActivityPubManager.java58
1 files changed, 58 insertions, 0 deletions
diff --git a/src/main/java/com/juick/ActivityPubManager.java b/src/main/java/com/juick/ActivityPubManager.java
index 566cc1fd..461f4731 100644
--- a/src/main/java/com/juick/ActivityPubManager.java
+++ b/src/main/java/com/juick/ActivityPubManager.java
@@ -19,6 +19,7 @@ package com.juick;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
+import com.juick.model.AnonymousUser;
import com.juick.model.Message;
import com.juick.model.Reaction;
import com.juick.model.User;
@@ -46,10 +47,14 @@ import io.pebbletemplates.pebble.template.PebbleTemplate;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import org.springframework.context.ApplicationEventPublisher;
import org.springframework.core.convert.ConversionService;
import org.springframework.http.MediaType;
import org.springframework.web.util.UriComponents;
import org.springframework.web.util.UriComponentsBuilder;
+import org.tomitribe.auth.signatures.MissingRequiredHeaderException;
+import org.tomitribe.auth.signatures.Signature;
+import org.tomitribe.auth.signatures.Verifier;
import javax.annotation.Nonnull;
import javax.inject.Inject;
@@ -57,7 +62,9 @@ import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;
import java.net.URI;
+import java.security.Key;
import java.security.NoSuchAlgorithmException;
+import java.security.SignatureException;
import java.time.Instant;
import java.util.*;
import java.util.stream.Collectors;
@@ -80,6 +87,10 @@ public class ActivityPubManager implements ActivityListener, NotificationListene
ConversionService conversionService;
@Inject
ObjectMapper jsonMapper;
+ @Inject
+ private ApplicationEventPublisher applicationEventPublisher;
+ @Inject
+ private KeystoreManager keystoreManager;
@Override
public void processFollowEvent(@Nonnull FollowEvent followEvent) {
@@ -420,4 +431,51 @@ public class ActivityPubManager implements ActivityListener, NotificationListene
throw new HttpNotFoundException();
}
}
+
+ public User verifyActor(String method, String path, Map<String, String> headers) {
+ String signatureString = headers.get("signature");
+ if (StringUtils.isNotEmpty(signatureString)) {
+ Signature signature = Signature.fromString(signatureString);
+ var keyId = UriComponentsBuilder.fromUriString(signature.getKeyId()).fragment(null).build().toUri();
+ var user = activityPubService.getUserByAccountUri(keyId.toASCIIString());
+ Key key = null;
+ Actor actor = null;
+ if (!user.isAnonymous()) {
+ // local user
+ key = keystoreManager.getPublicKey();
+ } else {
+ var context = activityPubService.get(keyId);
+ if (context.isPresent()) {
+ actor = (Actor) context.get();
+ key = KeystoreManager.publicKeyOf(actor);
+ }
+ }
+ if (key != null) {
+ Verifier verifier = new Verifier(key, signature);
+ try {
+ boolean result = verifier.verify(method.toLowerCase(), path, headers);
+ if (result) {
+ if (!user.isAnonymous()) {
+ return user;
+ } else {
+ if (actor != null) {
+ User person = new User();
+ person.setUri(URI.create(actor.getId()));
+ if (actor.isSuspended()) {
+ logger.info("{} is suspended, deleting", actor.getId());
+ applicationEventPublisher
+ .publishEvent(new DeleteUserEvent(this, actor.getId()));
+ }
+ return person;
+ }
+ }
+ }
+ } catch (NoSuchAlgorithmException | SignatureException | MissingRequiredHeaderException
+ | IOException e) {
+ logger.warn("Verification error for {}: {}", signature.getKeyId(), e.getMessage());
+ }
+ }
+ }
+ return AnonymousUser.INSTANCE;
+ }
}