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

Allow policies to be implemented with Java code #645

Merged
merged 1 commit into from
Jul 25, 2024
Merged

Conversation

waltkb
Copy link
Contributor

@waltkb waltkb commented Jul 24, 2024

This PR allows verification policies of the types CredentialDataValidatorPolicy, CredentialWrapperValidatorPolicy, JwtVerificationPolicy to be implemented from Java.

Examples

Examples for Java implemented policies are seen below:

Example 1 (Simple)

public class CustomCredentialDataValidatorPolicy extends JavaCredentialDataValidatorPolicy {
    public CustomCredentialDataValidatorPolicy() {
        super("java-custom-data-validator", "This is a custom data validator for Java");
    }

    @NotNull
    @Override
    public Object javaVerify(@NotNull JsonObject data, @Nullable Object args, @NotNull Map<String, ?> context) {
        if (!data.containsKey("my_verification")) {
            throw new IllegalArgumentException("Required attribute not found!");
        }

        String myVerificationContent = ((JsonPrimitive) Objects.requireNonNull(data.get("my_verification"))).getContent();

        if (!myVerificationContent.equalsIgnoreCase("hello world")) {
            throw new IllegalArgumentException("Greet the world!");
        }

        return myVerificationContent;
    }
}

Example 2 (Advanced)

public class CustomCredentialWrapperValidatorPolicy extends JavaCredentialWrapperValidatorPolicy {
    public CustomCredentialWrapperValidatorPolicy() {
        super("java-custom-credential-wrapper-validator", "This is a custom credential wrapper validator for Java");
    }

    @NotNull
    @Override
    public Object javaVerify(@NotNull JsonObject data, @Nullable Object args, @NotNull Map<String, ?> context) {
        // Getting the 'presenterDid' from data
        JsonElement issuerElement = data.get(JwsSignatureScheme.JwsOption.ISSUER);
        if (!(issuerElement instanceof JsonPrimitive)) {
            throw new IllegalArgumentException("Missing or invalid issuer in data");
        }
        String presenterDid = ((JsonPrimitive) issuerElement).getContent();

        // Getting the 'vp' from data
        JsonElement vpElement = data.get("vp");
        if (!(vpElement instanceof JsonObject vp)) {
            throw new IllegalArgumentException("No \"vp\" field in VP!");
        }

        // Getting the 'verifiableCredential' from 'vp'
        JsonElement credentialsElement = vp.get("verifiableCredential");
        if (!(credentialsElement instanceof JsonArray credentials)) {
            throw new IllegalArgumentException("No \"verifiableCredential\" field in \"vp\"!");
        }

        // Processing the credentials to get 'credentialSubjects'
        List<String> credentialSubjects = credentials.stream()
                .map(it -> {
                    if (!(it instanceof JsonPrimitive primitive)) {
                        throw new IllegalArgumentException("Invalid credential in \"verifiableCredential\"!");
                    }
                    String content = primitive.getContent();
                    JwsUtils.JwsParts decodedJws = JwsUtils.INSTANCE.decodeJws(content, false, false);
                    JsonObject payload = decodedJws.getPayload();
                    JsonElement subElement = payload.get("sub");
                    if (!(subElement instanceof JsonPrimitive)) {
                        throw new IllegalArgumentException("Invalid 'sub' in payload!");
                    }
                    return ((JsonPrimitive) subElement).getContent().split("#")[0];
                })
                .collect(Collectors.toList());

        // Returning the result based on 'credentialSubjects'
        boolean allMatch = credentialSubjects.stream().allMatch(sub -> sub.equals(presenterDid));
        if (allMatch) {
            return presenterDid;
        } else {
            throw new HolderBindingException(presenterDid, credentialSubjects);
        }
    }
}

@waltkb
Copy link
Contributor Author

waltkb commented Jul 24, 2024

Fixes #633

Copy link

@waltkb
Copy link
Contributor Author

waltkb commented Jul 24, 2024

waltid-examples is updated with these examples here walt-id/waltid-examples#5

@waltkb waltkb merged commit ba67b39 into main Jul 25, 2024
4 checks passed
@waltkb waltkb deleted the update-policies branch July 29, 2024 07:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
1 participant