{"record":{"id":"1e49e070f636a3ad","repo":"spring-projects/spring-security","slug":"empty-basic-authentication-token","errorCode":null,"errorMessage":"Empty basic authentication token","messagePattern":"Empty basic authentication token","errorType":"exception","errorClass":"BadCredentialsException","httpStatus":401,"severity":"error","filePath":"web/src/main/java/org/springframework/security/web/authentication/www/BasicAuthenticationConverter.java","lineNumber":89,"sourceCode":"\n\tpublic void setAuthenticationDetailsSource(\n\t\t\tAuthenticationDetailsSource<HttpServletRequest, ?> authenticationDetailsSource) {\n\t\tAssert.notNull(authenticationDetailsSource, \"AuthenticationDetailsSource required\");\n\t\tthis.authenticationDetailsSource = authenticationDetailsSource;\n\t}\n\n\t@Override\n\tpublic @Nullable UsernamePasswordAuthenticationToken convert(HttpServletRequest request) {\n\t\tString header = request.getHeader(HttpHeaders.AUTHORIZATION);\n\t\tif (header == null) {\n\t\t\treturn null;\n\t\t}\n\t\theader = header.trim();\n\t\tif (!StringUtils.startsWithIgnoreCase(header, AUTHENTICATION_SCHEME_BASIC)) {\n\t\t\treturn null;\n\t\t}\n\t\tif (header.equalsIgnoreCase(AUTHENTICATION_SCHEME_BASIC)) {\n\t\t\tthrow new BadCredentialsException(\"Empty basic authentication token\");\n\t\t}\n\t\tbyte[] base64Token = header.substring(6).getBytes(StandardCharsets.UTF_8);\n\t\tbyte[] decoded = decode(base64Token);\n\t\tString token = new String(decoded, getCredentialsCharset(request));\n\t\tint delim = token.indexOf(\":\");\n\t\tif (delim == -1) {\n\t\t\tthrow new BadCredentialsException(\"Invalid basic authentication token\");\n\t\t}\n\t\tUsernamePasswordAuthenticationToken result = UsernamePasswordAuthenticationToken\n\t\t\t.unauthenticated(token.substring(0, delim), token.substring(delim + 1));\n\t\tresult.setDetails(this.authenticationDetailsSource.buildDetails(request));\n\t\treturn result;\n\t}\n\n\tprivate byte[] decode(byte[] base64Token) {\n\t\ttry {\n\t\t\treturn Base64.getDecoder().decode(base64Token);\n\t\t}","sourceCodeStart":71,"sourceCodeEnd":107,"githubUrl":"https://github.com/spring-projects/spring-security/blob/96852e8860138a482cb13d1479573f24ff6443c6/web/src/main/java/org/springframework/security/web/authentication/www/BasicAuthenticationConverter.java#L71-L107","documentation":"BasicAuthenticationConverter.convert parses the Authorization header and requires content after the 'Basic' scheme. If the header is exactly 'Basic' (case-insensitive, possibly with trailing whitespace trimmed) with no Base64 payload, it throws BadCredentialsException('Empty basic authentication token'). The scheme is present but the credentials are missing entirely.","triggerScenarios":"An Authorization: Basic header with no value is sent — e.g. a client sends the scheme but no credentials, a gateway strips the Base64 part, or curl/testing tools send an incomplete header.","commonSituations":"HTTP clients sending an empty credentials string; reverse proxies or API gateways rewriting Authorization headers; misconfigured clients where username/password variables are empty; manual curl testing with 'Authorization: Basic' only.","solutions":["Fix the client to send 'Basic ' + Base64(username:password)","Verify proxies/gateways are not stripping the credential portion of the header","Ensure client credentials (env vars, config) are actually populated and not empty strings","Optionally pre-check the header client-side before sending"],"exampleFix":"// before\nrequest.header(\"Authorization\", \"Basic\"); // empty credentials\n// after\nString creds = Base64.getEncoder().encodeToString((user + \":\" + pass).getBytes(UTF_8));\nrequest.header(\"Authorization\", \"Basic \" + creds);","handlingStrategy":"try-catch","validationCode":"String h = request.getHeader(\"Authorization\");\nif (h == null || h.trim().equalsIgnoreCase(\"Basic\")) {\n    response.setHeader(\"WWW-Authenticate\", \"Basic realm=\\\"app\\\"\");\n    response.sendError(401, \"Missing basic credentials\");\n    return;\n}","typeGuard":"boolean hasBasicCredentials(String header) {\n    return header != null && header.trim().toLowerCase().startsWith(\"basic \")\n        && header.trim().length() > 6;\n}","tryCatchPattern":"try {\n    Authentication a = converter.convert(request);\n} catch (BadCredentialsException e) {\n    response.setHeader(\"WWW-Authenticate\", \"Basic realm=\\\"app\\\"\");\n    response.sendError(HttpServletResponse.SC_UNAUTHORIZED, e.getMessage());\n}","preventionTips":["Always send 'Basic ' + Base64(username:password) with a space after the scheme","Assert client credential config is non-empty at startup","Check proxies/gateways don't strip the credential part","Add contract tests asserting the exact Authorization header value"],"tags":["spring-security","basic-auth","http-header","credentials"],"backgroundTag":"missing-credentials","analyzedSha":"96852e8860138a482cb13d1479573f24ff6443c6","analyzedAt":"2026-09-10T23:25:23.477Z","contentChangedAt":"2026-09-10T23:25:23.477Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}