Basic Auth Generator — Java source
Build HTTP Basic Access Authentication headers from a username and password, or decode an existing Authorization header back to its credentials. UTF-8 safe and fully client-side, with a shareable link.
This is the Java implementation — the same logic the interactive tool runs, in a shareable, citable form.
// basic-auth-generator — HTTP Basic-Auth header encode/decode.
//
// Language: Java (17, standard library only)
// Source: CosmoDev polyglot showcase port of the Basic Auth Generator tool,
// ported from src/lib/basic-auth.ts (the canonical TypeScript
// implementation) and kept in lock-step with cli/basic-auth-generator.
// License: display source — part of CosmoDev's polyglot tool pages.
//
// Design goals:
// - Pure + deterministic; never throws (parseHeader returns Optional.empty()
// on malformed input).
// - Functionally equivalent to the TS reference + Go twin: same inputs ->
// same outputs, same reject behavior on malformed headers.
// - Self-contained: the JDK only (java.util.Base64 is the RFC 4648 standard
// codec, the direct equivalent of Go's encoding/base64 StdEncoding).
//
// The class is package-private on purpose: the polyglot showcase names this
// file java.java, and javac requires only *public* classes to match their
// filename. Two JDK quirks are compensated for below — java.util.Base64's
// basic decoder accepts unpadded input, and new String(bytes, UTF_8) silently
// replaces invalid sequences with U+FFFD — so both get the strict
// Go-equivalent behavior.
import java.nio.ByteBuffer;
import java.nio.charset.CharacterCodingException;
import java.nio.charset.CodingErrorAction;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.Locale;
import java.util.Optional;
/**
* HTTP Basic-Auth header encode/decode, ported from src/lib/basic-auth.ts
* (the canonical TypeScript implementation) and kept in lock-step with
* cli/basic-auth-generator.
*/
final class BasicAuthGenerator {
private BasicAuthGenerator() {}
/**
* A parsed username/password pair. Mirrors the Go twin's Credentials
* struct and the TS BasicAuthCredentials interface.
*/
record Credentials(String user, String pass) {}
/**
* Build an HTTP Basic-Auth header value: {@code "Basic " + base64(user:pass)}.
* Mirrors {@code BuildHeader} in the Go twin and {@code buildBasicAuth} in
* the TS source. The UTF-8 byte representation is encoded, so multibyte
* credentials (e.g. {@code café:päss}) work.
*/
static String buildHeader(String user, String pass) {
byte[] raw = (user + ":" + pass).getBytes(StandardCharsets.UTF_8);
return "Basic " + Base64.getEncoder().encodeToString(raw);
}
/**
* Parse a {@code "Basic <token>"} header back into credentials, or
* {@code Optional.empty()} if the header is malformed or the credentials
* have no colon separator. Logic mirrors {@code ParseHeader} in the Go
* twin exactly: trim the header, require a case-insensitive
* {@code "basic "} prefix, trim the remaining token, base64-decode it
* (rejecting invalid characters), then split on the FIRST colon so a
* password containing colons round-trips.
*/
static Optional<Credentials> parseHeader(String header) {
String h = header.strip();
String prefix = "basic ";
if (h.length() < prefix.length()
|| !h.substring(0, prefix.length()).toLowerCase(Locale.ROOT).equals(prefix)) {
return Optional.empty();
}
String token = h.substring(prefix.length()).strip();
// The basic decoder ignores nothing and accepts missing padding, so
// strip whitespace and enforce the multiple-of-4 length ourselves —
// exactly like Go's StdEncoding.
String cleaned = token.replaceAll("\\s+", "");
if (cleaned.length() % 4 != 0) {
return Optional.empty();
}
byte[] decoded;
try {
decoded = Base64.getDecoder().decode(cleaned);
} catch (IllegalArgumentException e) {
return Optional.empty();
}
String text = decodeUtf8Strict(decoded);
if (text == null) {
return Optional.empty();
}
int colon = text.indexOf(':');
if (colon < 0) {
return Optional.empty();
}
return Optional.of(new Credentials(text.substring(0, colon), text.substring(colon + 1)));
}
/**
* Strict UTF-8 decode: {@code new String(bytes, UTF_8)} silently replaces
* malformed sequences with U+FFFD; the Go/Rust twins reject them, so this
* decoder reports them and maps the failure to null.
*/
private static String decodeUtf8Strict(byte[] bytes) {
try {
return StandardCharsets.UTF_8.newDecoder()
.onMalformedInput(CodingErrorAction.REPORT)
.onUnmappableCharacter(CodingErrorAction.REPORT)
.decode(ByteBuffer.wrap(bytes))
.toString();
} catch (CharacterCodingException e) {
return null;
}
}
// ---------- showcase-only demo (canonical suite lives in src/lib) ----------
public static void main(String[] args) {
String h = buildHeader("user", "pass");
if (!h.equals("Basic dXNlcjpwYXNz")) throw new AssertionError(h);
System.out.println(h);
String[][] roundTrips = {{"alice", "s3cr3t"}, {"", "x"}, {"x", ""}, {"u", "a:b:c"}};
for (String[] pair : roundTrips) {
Credentials c = parseHeader(buildHeader(pair[0], pair[1])).orElseThrow();
if (!c.user().equals(pair[0]) || !c.pass().equals(pair[1])) {
throw new AssertionError("round trip failed for " + pair[0] + ":" + pair[1]);
}
}
String[] malformed = {
"Bearer xyz", "", "Basic !!!not-base64!!!", "Basic bm9jb2xvbg==", // "nocolon"
};
for (String bad : malformed) {
if (parseHeader(bad).isPresent()) throw new AssertionError(bad + " should be rejected");
}
System.out.println("all basic-auth-generator demo checks passed");
}
}
Also available in 13 other languages
Every CosmoDev tool ships its pure logic in TypeScript (web) and Go (CLI), with authored implementations in a dozen-plus languages — the same contract, ported. Compare all languages side by side →