{"record":{"id":"22cf93b9dd0b9f3a","repo":"signalapp/Signal-Server","slug":"badly-formatted-credentials","errorCode":null,"errorMessage":"Badly-formatted credentials: ","messagePattern":"Badly-formatted credentials: ","errorType":"http","errorClass":"InvalidAuthorizationHeaderException","httpStatus":401,"severity":"error","filePath":"service/src/main/java/org/whispersystems/textsecuregcm/auth/BasicAuthorizationHeader.java","lineNumber":56,"sourceCode":"        throw new InvalidAuthorizationHeaderException(\"Unsupported authorization method: \" + authorizationType);\n      }\n\n      final String credentials;\n\n      try {\n        credentials = new String(Base64.getDecoder().decode(header.substring(spaceIndex + 1)));\n      } catch (final IndexOutOfBoundsException e) {\n        throw new InvalidAuthorizationHeaderException(\"Missing credentials\");\n      }\n\n      if (StringUtils.isEmpty(credentials)) {\n        throw new InvalidAuthorizationHeaderException(\"Bad decoded value: \" + credentials);\n      }\n\n      final int credentialSeparatorIndex = credentials.indexOf(':');\n\n      if (credentialSeparatorIndex == -1) {\n        throw new InvalidAuthorizationHeaderException(\"Badly-formatted credentials: \" + credentials);\n      }\n\n      final String usernameComponent = credentials.substring(0, credentialSeparatorIndex);\n\n      final String username;\n      final byte deviceId;\n      {\n        final Pair<String, Byte> identifierAndDeviceId =\n            AccountAuthenticator.getIdentifierAndDeviceId(usernameComponent);\n\n        username = identifierAndDeviceId.first();\n        deviceId = identifierAndDeviceId.second();\n      }\n\n      final String password = credentials.substring(credentialSeparatorIndex + 1);\n\n      if (StringUtils.isAnyBlank(username, password)) {\n        throw new InvalidAuthorizationHeaderException(\"Username or password were blank\");","sourceCodeStart":38,"sourceCodeEnd":74,"githubUrl":"https://github.com/signalapp/Signal-Server/blob/100ab61c82627582c867d19e1c0561ba2781e927/service/src/main/java/org/whispersystems/textsecuregcm/auth/BasicAuthorizationHeader.java#L38-L74","documentation":"Thrown while parsing a Basic authorization header when the Base64-decoded credentials do not match the expected 'username:password' format — specifically when the decoded string contains no ':' separator, so no username/password split can be performed. The faulting input is the Authorization header supplied by the client; it results in a 401 response via InvalidAuthorizationHeaderException.","triggerScenarios":"Base64 payload decodes to a single token with no colon, e.g. base64(\"somepassword\") or a raw token passed as basic credentials.","commonSituations":"Clients treating the Signal auth password alone as full credentials instead of number:password; forgetting the deviceId/username portion.","solutions":["Encode credentials as '<username>:<password>' where username is the account (e.g. +15551234567 or +15551234567.1 for a device)","Base64-encode the full colon-joined string","Check client credential construction joins with ':'"],"exampleFix":"// before\nString creds = base64(password);\n// after\nString creds = base64(username + \":\" + password);","handlingStrategy":"validation","validationCode":"String decoded = new String(Base64.getDecoder().decode(credentialPart), StandardCharsets.UTF_8);\nif (decoded.indexOf(':') == -1) throw new IllegalArgumentException(\"credentials must be 'username:password'\");","typeGuard":null,"tryCatchPattern":"try { BasicAuthorizationHeader.fromString(header); } catch (InvalidAuthorizationHeaderException e) { throw new NotAuthorizedException(\"Basic\"); }","preventionTips":["Always join username and password with ':' before Base64 encoding","Store credentials as a structured pair, not a single token"],"tags":["basic-auth","malformed","credentials"],"backgroundTag":"invalid-argument-format","analyzedSha":"100ab61c82627582c867d19e1c0561ba2781e927","analyzedAt":"2026-09-09T13:29:47.883Z","contentChangedAt":"2026-09-09T13:29:47.883Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}