Add passkeys project: WebAuthn ceremonies, a software authenticator and the one-time-token fallback
Fourth Maven project in the repository. Registration and authentication run end to end with no browser and no hardware key: VirtualAuthenticator emits real CBOR attestation objects and real ES256 assertion signatures, and tools/PasskeyCeremony.java drives the live HTTP endpoints with them. Profiles cover userVerification REQUIRED, DIRECT attestation, a disallowed origin and JDBC persistence. Eleven doc chapters and twelve captured transcripts under docs/passkeys and docs/output/pk-*.txt, all regenerated by passkeys/scripts/run-all.sh.
This commit is contained in:
63
passkeys/scripts/lib.sh
Executable file
63
passkeys/scripts/lib.sh
Executable file
@@ -0,0 +1,63 @@
|
||||
#!/usr/bin/env bash
|
||||
# Shared helpers. Sourced by every script in this directory.
|
||||
#
|
||||
# Two traps are baked in here because both have cost real time:
|
||||
#
|
||||
# * never `pkill -f spring-boot` - the pattern matches the shell that is running this
|
||||
# script and kills it. Kill by main class instead, which is what stop_app does.
|
||||
# * `mvn -o` cannot run the Boot plugin until one online build has cached it, so the first
|
||||
# run of run.sh is deliberately not offline.
|
||||
set -euo pipefail
|
||||
|
||||
MODULE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
OUTPUT_DIR="$(cd "$MODULE_DIR/.." && pwd)/docs/output"
|
||||
MAIN_CLASS="PasskeysDemoApplication"
|
||||
BASE_URL="${BASE_URL:-http://localhost:8080}"
|
||||
APP_LOG="${APP_LOG:-/tmp/passkeys-demo.log}"
|
||||
|
||||
mkdir -p "$OUTPUT_DIR"
|
||||
|
||||
stop_app() {
|
||||
for pid in $(ps -eo pid,cmd | grep "[${MAIN_CLASS:0:1}]${MAIN_CLASS:1}" | awk '{print $1}'); do
|
||||
kill -9 "$pid" 2>/dev/null || true
|
||||
done
|
||||
# ss -lptn sometimes reports the port with no PID, so a port-based kill silently does
|
||||
# nothing and the stale process keeps serving. Wait for the port to actually close.
|
||||
for _ in $(seq 1 20); do
|
||||
curl -sf -o /dev/null "$BASE_URL/health" || return 0
|
||||
sleep 0.5
|
||||
done
|
||||
}
|
||||
|
||||
start_app() {
|
||||
local profiles="${1:-}"
|
||||
stop_app
|
||||
cd "$MODULE_DIR"
|
||||
local args=(-B org.springframework.boot:spring-boot-maven-plugin:run)
|
||||
[ -n "$profiles" ] && args+=("-Dspring-boot.run.profiles=$profiles")
|
||||
setsid nohup mvn "${args[@]}" > "$APP_LOG" 2>&1 < /dev/null &
|
||||
for _ in $(seq 1 90); do
|
||||
curl -sf -o /dev/null "$BASE_URL/health" && { echo "started${profiles:+ with profiles: $profiles}"; return 0; }
|
||||
sleep 2
|
||||
done
|
||||
echo "the application did not come up; see $APP_LOG" >&2
|
||||
tail -40 "$APP_LOG" >&2
|
||||
return 1
|
||||
}
|
||||
|
||||
classpath() {
|
||||
cd "$MODULE_DIR"
|
||||
[ -f target/deps.txt ] || mvn -B -q dependency:build-classpath -Dmdep.outputFile=target/deps.txt -DincludeScope=runtime
|
||||
echo "target/classes:$(cat target/deps.txt)"
|
||||
}
|
||||
|
||||
ceremony() {
|
||||
cd "$MODULE_DIR"
|
||||
java --class-path "$(classpath)" tools/PasskeyCeremony.java "$@"
|
||||
}
|
||||
|
||||
header() {
|
||||
echo "=============================================================================="
|
||||
echo "$1"
|
||||
echo "=============================================================================="
|
||||
}
|
||||
Reference in New Issue
Block a user