Search code examples
javabase64wildflyjersey-client

Base64 encoding exception with BASIC authentication of Jersey client


I have a Jersey client running on Wildfly 9 with BASIC authentication enabled. This works well in general, but when using passwords with special characters (such as German umlauts) I get this exception, related to Base64 encoding:

Caused by: java.lang.ArrayIndexOutOfBoundsException: 255
        at org.glassfish.jersey.internal.util.Base64.encode(Base64.java:112)
        at org.glassfish.jersey.internal.util.Base64.encodeAsString(Base64.java:160)
        at org.glassfish.jersey.client.filter.HttpBasicAuthFilter.<init>(HttpBasicAuthFilter.java:98)
        at org.glassfish.jersey.client.filter.HttpBasicAuthFilter.<init>(HttpBasicAuthFilter.java:72)

Any idea what I might be doing wrong?


Solution

  • This is a known bug.

    As a workaround you can set the Authorization header directly instead of using the HttpAuthenticationFeature.HTTP_AUTHENTICATION_BASIC_USERNAME and HttpAuthenticationFeature.HTTP_AUTHENTICATION_BASIC_PASSWORD properties.

    Old code:

    Invocation.Builder builder = …;
    builder
        .property(HttpAuthenticationFeature.HTTP_AUTHENTICATION_BASIC_USERNAME, username)
        .property(HttpAuthenticationFeature.HTTP_AUTHENTICATION_BASIC_PASSWORD, password);
    

    New code:

    import java.nio.charset.StandardCharsets;
    import java.util.Base64;
    import javax.ws.rs.core.HttpHeaders;
    
    // …
        builder.header(HttpHeaders.AUTHORIZATION, calculateAuthentication(username, password));
    // …
    
    private String calculateAuthentication(final String username, final byte[] password) {
        final byte[] prefix = (username + ":").getBytes(StandardCharsets.UTF_8);
        final byte[] usernamePassword = new byte[prefix.length + password.length];
        System.arraycopy(prefix, 0, usernamePassword, 0, prefix.length);
        System.arraycopy(password, 0, usernamePassword, prefix.length, password.length);
        return "Basic " + Base64.getEncoder().encodeToString(usernamePassword);
    }