signalapp/Signal-Server · error · InvalidAuthorizationHeaderException

Missing credentials

Error message

Missing credentials

What it means

fromString throws InvalidAuthorizationHeaderException("Missing credentials") when the substring after the first space is empty, so Base64 decoding's IndexOutOfBoundsException (begin index past end) is caught and rethrown. The header had a scheme but no credential part.

Solutions

  1. Append base64(username:password) after 'Basic '
  2. Verify no proxy/gateway strips or truncates the Authorization header
  3. Check client templating/config actually fills in the credentials

Example fix

// before
Authorization: Basic
// after
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=
Defensive patterns

Strategy: validation

Validate before calling

int space = header.indexOf(' ');
if (space == -1 || header.substring(space + 1).isEmpty()) throw new IllegalArgumentException("missing basic credentials");

Try / catch

try { BasicAuthorizationHeader.fromString(header); } catch (InvalidAuthorizationHeaderException e) { throw new NotAuthorizedException("Basic"); }

Prevention

When it happens

Trigger: Header value is exactly "Basic " with trailing space and nothing after; scheme present but credentials dropped by an intermediary.

Common situations: Header truncation at proxies or by manual header editing; template placeholders like "Basic {{creds}}" left unsubstituted.

Related errors


AI-assisted analysis of signalapp/Signal-Server@100ab61c82 (2026-09-09). Data as JSON: /api/errors/1e0dc45aa7f82efa. Report an issue: GitHub.

Appendix: source

Thrown at service/src/main/java/org/whispersystems/textsecuregcm/auth/BasicAuthorizationHeader.java:46

      final int spaceIndex = header.indexOf(' ');

      if (spaceIndex == -1) {
        throw new InvalidAuthorizationHeaderException("Invalid authorization header: " + header);
      }

      final String authorizationType = header.substring(0, spaceIndex);

      if (!"Basic".equals(authorizationType)) {
        throw new InvalidAuthorizationHeaderException("Unsupported authorization method: " + authorizationType);
      }

      final String credentials;

      try {
        credentials = new String(Base64.getDecoder().decode(header.substring(spaceIndex + 1)));
      } catch (final IndexOutOfBoundsException e) {
        throw new InvalidAuthorizationHeaderException("Missing credentials");
      }

      if (StringUtils.isEmpty(credentials)) {
        throw new InvalidAuthorizationHeaderException("Bad decoded value: " + credentials);
      }

      final int credentialSeparatorIndex = credentials.indexOf(':');

      if (credentialSeparatorIndex == -1) {
        throw new InvalidAuthorizationHeaderException("Badly-formatted credentials: " + credentials);
      }

      final String usernameComponent = credentials.substring(0, credentialSeparatorIndex);

      final String username;
      final byte deviceId;
      {
        final Pair<String, Byte> identifierAndDeviceId =

View on GitHub (pinned to 100ab61c82)