Skip to content

Commit

Permalink
Allow more than one key
Browse files Browse the repository at this point in the history
  • Loading branch information
slinkydeveloper committed Jun 3, 2024
1 parent 8f90998 commit d8d4c30
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,21 @@
import com.nimbusds.jwt.SignedJWT;
import dev.restate.sdk.auth.RequestIdentityVerifier;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class RestateRequestIdentityVerifier implements RequestIdentityVerifier {
private static final String SIGNATURE_SCHEME_HEADER = "x-restate-signature-scheme";
private static final String SIGNATURE_SCHEME_V1 = "v1";
private static final String SIGNATURE_SCHEME_UNSIGNED = "unsigned";
private static final String JWT_HEADER = "x-restate-jwt-v1";
private static final String IDENTITY_V1_PREFIX = "publickeyv1_";

private final JWSVerifier verifier;
private final JWSVerifier[] verifiers;

private RestateRequestIdentityVerifier(JWSVerifier verifier) {
this.verifier = verifier;
private RestateRequestIdentityVerifier(List<JWSVerifier> verifier) {
this.verifiers = verifier.toArray(JWSVerifier[]::new);
}

@Override
Expand All @@ -37,10 +41,12 @@ public void verifyRequest(Headers headers) throws Exception {
case SIGNATURE_SCHEME_V1:
String jwtHeader = expectHeader(headers, JWT_HEADER);
SignedJWT signedJWT = SignedJWT.parse(jwtHeader);
if (!signedJWT.verify(verifier)) {
throw new IllegalStateException("Verification of JWT token failed");
for (JWSVerifier verifier : verifiers) {
if (signedJWT.verify(verifier)) {
return;
}
}
break;
throw new IllegalStateException("Verification of JWT token failed");
case SIGNATURE_SCHEME_UNSIGNED:
throw new IllegalStateException("Request has no identity, but one was expected");
default:
Expand All @@ -58,15 +64,27 @@ private String expectHeader(Headers headers, String key) {

/** Create the {@link RequestIdentityVerifier} from key strings. */
public static RequestIdentityVerifier fromKey(String key) {
return fromKeys(key);
}

/** Create the {@link RequestIdentityVerifier} from key strings. */
public static RequestIdentityVerifier fromKeys(String ...keys) {
if (keys.length == 0) {
throw new IllegalArgumentException("You must provide at least one key");
}
return new RestateRequestIdentityVerifier(Arrays.stream(keys).map(RestateRequestIdentityVerifier::parseKey).collect(Collectors.toList()));
}

private static JWSVerifier parseKey(String key) {
if (!key.startsWith(IDENTITY_V1_PREFIX)) {
throw new IllegalArgumentException(
"Identity v1 jwt public keys are expected to start with " + IDENTITY_V1_PREFIX);
"Identity v1 jwt public keys are expected to start with " + IDENTITY_V1_PREFIX);
}

byte[] decoded = Base58.decode(key.substring(IDENTITY_V1_PREFIX.length()));
if (decoded.length != 32) {
throw new IllegalArgumentException(
"Decoded key should have length of 32, was " + decoded.length);
"Decoded key should have length of 32, was " + decoded.length);
}

OctetKeyPair jwk = new OctetKeyPair.Builder(Curve.Ed25519, Base64URL.encode(decoded)).build();
Expand All @@ -77,7 +95,6 @@ public static RequestIdentityVerifier fromKey(String key) {
} catch (JOSEException e) {
throw new RuntimeException("Cannot create the verifier", e);
}

return new RestateRequestIdentityVerifier(verifier);
return verifier;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public class RestateRequestIdentityVerifierTest {

@Test
void parseKey() {
RestateRequestIdentityVerifier.fromKey(
RestateRequestIdentityVerifier.fromKeys(
"publickeyv1_ChjENKeMvCtRnqG2mrBK1HmPKufgFUc98K8B3ononQvp");
}
}

0 comments on commit d8d4c30

Please sign in to comment.