GET /auth-required
Returns 401 with a WWW-Authenticate challenge when no Authorization header is present. If any Authorization header is sent — regardless of its value — returns 200. This lets clients exercise the full challenge-response cycle without needing real credentials.
scheme
Challenge scheme: basic, bearer, digest, or none. Default: basic. The none value returns 401 with no WWW-Authenticate header, which is a real-world bug in some servers.
realm
Realm value for the challenge. Sanitized to [a-zA-Z0-9._- ] and capped at 64 chars. Default: catastrophic.io.
# First call — no Authorization, get 401 with challenge
curl -i 'https://chaos.catastrophic.io/auth-required'
# Bearer challenge
curl -i 'https://chaos.catastrophic.io/auth-required?scheme=bearer'
# Send any Authorization header to get 200
curl -i -H 'Authorization: Bearer fake-token' \
'https://chaos.catastrophic.io/auth-required?scheme=bearer'
# Misbehaving server — 401 with no WWW-Authenticate header
curl -i 'https://chaos.catastrophic.io/auth-required?scheme=none'
import base64, urllib.request, urllib.error
url = "https://chaos.catastrophic.io/auth-required"
try:
urllib.request.urlopen(url)
except urllib.error.HTTPError as e:
print(e.code, e.headers.get("WWW-Authenticate")) # 401, Basic realm="..."
creds = base64.b64encode(b"user:pass").decode()
req = urllib.request.Request(url, headers={"Authorization": f"Basic {creds}"})
print(urllib.request.urlopen(req).status) # 200
// Browser or Node 18+
const url = "https://chaos.catastrophic.io/auth-required";
const r1 = await fetch(url);
console.log(r1.status, r1.headers.get("www-authenticate")); // 401
const creds = btoa("user:pass");
const r2 = await fetch(url, { headers: { Authorization: `Basic ${creds}` } });
console.log(r2.status); // 200
package main
import (
"encoding/base64"
"fmt"
"net/http"
)
func main() {
url := "https://chaos.catastrophic.io/auth-required"
r1, _ := http.Get(url)
fmt.Println(r1.StatusCode, r1.Header.Get("WWW-Authenticate")) // 401
r1.Body.Close()
req, _ := http.NewRequest("GET", url, nil)
creds := base64.StdEncoding.EncodeToString([]byte("user:pass"))
req.Header.Set("Authorization", "Basic "+creds)
r2, _ := http.DefaultClient.Do(req)
fmt.Println(r2.StatusCode) // 200
r2.Body.Close()
}
// Cargo.toml: reqwest = { version = "0.12", features = ["blocking"] }
// base64 = "0.22"
use base64::{engine::general_purpose, Engine};
fn main() -> Result<(), Box> {
let url = "https://chaos.catastrophic.io/auth-required";
let client = reqwest::blocking::Client::new();
let r1 = client.get(url).send()?;
println!("{} {:?}", r1.status(), r1.headers().get("www-authenticate"));
let creds = general_purpose::STANDARD.encode("user:pass");
let r2 = client
.get(url)
.header("Authorization", format!("Basic {creds}"))
.send()?;
println!("{}", r2.status());
Ok(())
}
// Java 11+ HttpClient
import java.net.URI;
import java.net.http.*;
import java.util.Base64;
public class AuthRequired {
public static void main(String[] args) throws Exception {
var client = HttpClient.newHttpClient();
var url = URI.create("https://chaos.catastrophic.io/auth-required");
var r1 = client.send(HttpRequest.newBuilder(url).build(),
HttpResponse.BodyHandlers.discarding());
System.out.println(r1.statusCode() + " "
+ r1.headers().firstValue("WWW-Authenticate").orElse(""));
var creds = Base64.getEncoder().encodeToString("user:pass".getBytes());
var r2 = client.send(
HttpRequest.newBuilder(url).header("Authorization", "Basic " + creds).build(),
HttpResponse.BodyHandlers.discarding());
System.out.println(r2.statusCode());
}
}
// .NET 6+
using System.Net.Http.Headers;
using var client = new HttpClient();
var url = "https://chaos.catastrophic.io/auth-required";
var r1 = await client.GetAsync(url);
Console.WriteLine($"{(int)r1.StatusCode} {r1.Headers.WwwAuthenticate}");
var creds = Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes("user:pass"));
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", creds);
var r2 = await client.GetAsync(url);
Console.WriteLine((int)r2.StatusCode);
require "net/http"
require "base64"
uri = URI("https://chaos.catastrophic.io/auth-required")
res1 = Net::HTTP.get_response(uri)
puts "#{res1.code} #{res1["WWW-Authenticate"]}"
req = Net::HTTP::Get.new(uri)
req["Authorization"] = "Basic #{Base64.strict_encode64('user:pass')}"
res2 = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |h| h.request(req) }
puts res2.code
# PowerShell 5.1: Invoke-WebRequest throws on 401.
try {
Invoke-WebRequest -Uri 'https://chaos.catastrophic.io/auth-required'
} catch {
$resp = $_.Exception.Response
$resp.StatusCode.value__ # 401
$resp.Headers['WWW-Authenticate'] # Basic realm="catastrophic.io"
}
# Retry with credentials
$r = Invoke-WebRequest -Uri 'https://chaos.catastrophic.io/auth-required' `
-Headers @{ Authorization = 'Basic ' + [Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes('user:pass')) }
$r.StatusCode # 200