mirror of
https://github.com/block/buzz.git
synced 2026-10-27 04:30:52 +00:00
chore: remove dead API token references from GUI, docs, and config (#498)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,273 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
# =============================================================================
|
||||
# setup-keycloak.sh — Configure Keycloak for local OAuth testing
|
||||
# =============================================================================
|
||||
# Usage: ./scripts/setup-keycloak.sh
|
||||
#
|
||||
# Creates the `sprout` realm with:
|
||||
# - sprout-desktop client (public, direct access grants)
|
||||
# - Test users: tyler, alice, bob, charlie (password: password123)
|
||||
# - nostr_pubkey custom attribute on each user
|
||||
# - Protocol mapper: nostr_pubkey → JWT access token claim
|
||||
#
|
||||
# Keycloak is a LOCAL DEV STAND-IN for Okta/generic OIDC providers.
|
||||
# It is NOT a production dependency.
|
||||
#
|
||||
# Prerequisites:
|
||||
# - Keycloak running at http://localhost:8180 (docker compose up -d)
|
||||
# - curl and jq installed
|
||||
# =============================================================================
|
||||
set -euo pipefail
|
||||
|
||||
KEYCLOAK_URL="${KEYCLOAK_URL:-http://localhost:8180}"
|
||||
ADMIN_USER="${KEYCLOAK_ADMIN:-admin}"
|
||||
ADMIN_PASS="${KEYCLOAK_ADMIN_PASSWORD:-admin}"
|
||||
REALM="sprout"
|
||||
CLIENT_ID="sprout-desktop"
|
||||
TIMEOUT=120 # seconds to wait for Keycloak
|
||||
|
||||
# Colors
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m'
|
||||
|
||||
log() { echo -e "${BLUE}[keycloak-setup]${NC} $*"; }
|
||||
success(){ echo -e "${GREEN}[keycloak-setup]${NC} ✅ $*"; }
|
||||
warn() { echo -e "${YELLOW}[keycloak-setup]${NC} ⚠️ $*"; }
|
||||
error() { echo -e "${RED}[keycloak-setup]${NC} ❌ $*" >&2; }
|
||||
|
||||
# ---- Preflight --------------------------------------------------------------
|
||||
|
||||
for cmd in curl jq; do
|
||||
if ! command -v "$cmd" &>/dev/null; then
|
||||
error "Required tool not found: $cmd"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
# ---- Wait for Keycloak ------------------------------------------------------
|
||||
|
||||
log "Waiting for Keycloak at ${KEYCLOAK_URL}..."
|
||||
elapsed=0
|
||||
interval=5
|
||||
until curl -sf "${KEYCLOAK_URL}/health/ready" -o /dev/null 2>/dev/null; do
|
||||
if [[ ${elapsed} -ge ${TIMEOUT} ]]; then
|
||||
error "Timed out waiting for Keycloak (${TIMEOUT}s). Is it running?"
|
||||
error " docker compose up -d keycloak"
|
||||
exit 1
|
||||
fi
|
||||
echo -n "."
|
||||
sleep "${interval}"
|
||||
elapsed=$((elapsed + interval))
|
||||
done
|
||||
echo ""
|
||||
success "Keycloak is ready"
|
||||
|
||||
# ---- Get admin token --------------------------------------------------------
|
||||
|
||||
log "Authenticating as admin..."
|
||||
ADMIN_TOKEN=$(curl -sf \
|
||||
-X POST "${KEYCLOAK_URL}/realms/master/protocol/openid-connect/token" \
|
||||
-H "Content-Type: application/x-www-form-urlencoded" \
|
||||
-d "client_id=admin-cli" \
|
||||
-d "username=${ADMIN_USER}" \
|
||||
-d "password=${ADMIN_PASS}" \
|
||||
-d "grant_type=password" \
|
||||
| jq -r '.access_token')
|
||||
|
||||
if [[ -z "${ADMIN_TOKEN}" || "${ADMIN_TOKEN}" == "null" ]]; then
|
||||
error "Failed to get admin token. Check KEYCLOAK_ADMIN / KEYCLOAK_ADMIN_PASSWORD."
|
||||
exit 1
|
||||
fi
|
||||
success "Admin token obtained"
|
||||
|
||||
# Helper: authenticated API call
|
||||
kc() {
|
||||
local method="$1"; shift
|
||||
local path="$1"; shift
|
||||
curl -sf \
|
||||
-X "${method}" \
|
||||
"${KEYCLOAK_URL}/admin/realms${path}" \
|
||||
-H "Authorization: Bearer ${ADMIN_TOKEN}" \
|
||||
-H "Content-Type: application/json" \
|
||||
"$@"
|
||||
}
|
||||
|
||||
kc_root() {
|
||||
local method="$1"; shift
|
||||
local path="$1"; shift
|
||||
curl -sf \
|
||||
-X "${method}" \
|
||||
"${KEYCLOAK_URL}/admin${path}" \
|
||||
-H "Authorization: Bearer ${ADMIN_TOKEN}" \
|
||||
-H "Content-Type: application/json" \
|
||||
"$@"
|
||||
}
|
||||
|
||||
# ---- Create realm -----------------------------------------------------------
|
||||
|
||||
log "Checking for realm '${REALM}'..."
|
||||
REALM_EXISTS=$(curl -sf \
|
||||
"${KEYCLOAK_URL}/admin/realms/${REALM}" \
|
||||
-H "Authorization: Bearer ${ADMIN_TOKEN}" \
|
||||
-o /dev/null -w "%{http_code}" 2>/dev/null || true)
|
||||
|
||||
if [[ "${REALM_EXISTS}" == "200" ]]; then
|
||||
warn "Realm '${REALM}' already exists — skipping creation"
|
||||
else
|
||||
log "Creating realm '${REALM}'..."
|
||||
curl -sf \
|
||||
-X POST "${KEYCLOAK_URL}/admin/realms" \
|
||||
-H "Authorization: Bearer ${ADMIN_TOKEN}" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"realm": "'"${REALM}"'",
|
||||
"displayName": "Sprout",
|
||||
"enabled": true,
|
||||
"registrationAllowed": false,
|
||||
"loginWithEmailAllowed": true,
|
||||
"duplicateEmailsAllowed": false,
|
||||
"resetPasswordAllowed": false,
|
||||
"editUsernameAllowed": false,
|
||||
"bruteForceProtected": false
|
||||
}'
|
||||
success "Realm '${REALM}' created"
|
||||
fi
|
||||
|
||||
# ---- Create client ----------------------------------------------------------
|
||||
|
||||
log "Checking for client '${CLIENT_ID}'..."
|
||||
EXISTING_CLIENT=$(kc GET "/${REALM}/clients?clientId=${CLIENT_ID}" | jq -r '.[0].id // empty')
|
||||
|
||||
if [[ -n "${EXISTING_CLIENT}" ]]; then
|
||||
warn "Client '${CLIENT_ID}' already exists (id: ${EXISTING_CLIENT}) — skipping creation"
|
||||
CLIENT_UUID="${EXISTING_CLIENT}"
|
||||
else
|
||||
log "Creating client '${CLIENT_ID}'..."
|
||||
kc POST "/${REALM}/clients" -d '{
|
||||
"clientId": "'"${CLIENT_ID}"'",
|
||||
"name": "Sprout Desktop",
|
||||
"enabled": true,
|
||||
"publicClient": true,
|
||||
"directAccessGrantsEnabled": true,
|
||||
"standardFlowEnabled": true,
|
||||
"implicitFlowEnabled": false,
|
||||
"serviceAccountsEnabled": false,
|
||||
"redirectUris": [
|
||||
"http://localhost:*",
|
||||
"sprout://*"
|
||||
],
|
||||
"webOrigins": ["*"],
|
||||
"protocol": "openid-connect"
|
||||
}'
|
||||
|
||||
CLIENT_UUID=$(kc GET "/${REALM}/clients?clientId=${CLIENT_ID}" | jq -r '.[0].id')
|
||||
success "Client '${CLIENT_ID}' created (id: ${CLIENT_UUID})"
|
||||
fi
|
||||
|
||||
# ---- Add nostr_pubkey protocol mapper ---------------------------------------
|
||||
|
||||
log "Checking for nostr_pubkey protocol mapper..."
|
||||
MAPPER_EXISTS=$(kc GET "/${REALM}/clients/${CLIENT_UUID}/protocol-mappers/models" \
|
||||
| jq -r '.[] | select(.name == "nostr_pubkey") | .id // empty')
|
||||
|
||||
if [[ -n "${MAPPER_EXISTS}" ]]; then
|
||||
warn "Protocol mapper 'nostr_pubkey' already exists — skipping"
|
||||
else
|
||||
log "Creating nostr_pubkey → JWT claim mapper..."
|
||||
kc POST "/${REALM}/clients/${CLIENT_UUID}/protocol-mappers/models" -d '{
|
||||
"name": "nostr_pubkey",
|
||||
"protocol": "openid-connect",
|
||||
"protocolMapper": "oidc-usermodel-attribute-mapper",
|
||||
"consentRequired": false,
|
||||
"config": {
|
||||
"userinfo.token.claim": "true",
|
||||
"user.attribute": "nostr_pubkey",
|
||||
"id.token.claim": "true",
|
||||
"access.token.claim": "true",
|
||||
"claim.name": "nostr_pubkey",
|
||||
"jsonType.label": "String"
|
||||
}
|
||||
}'
|
||||
success "Protocol mapper 'nostr_pubkey' created"
|
||||
fi
|
||||
|
||||
# ---- Create users -----------------------------------------------------------
|
||||
|
||||
# Format: "username:nostr_pubkey"
|
||||
declare -a USERS=(
|
||||
"tyler:e5ebc6cdb579be112e336cc319b5989b4bb6af11786ea90dbe52b5f08d741b34"
|
||||
"alice:953d3363262e86b770419834c53d2446409db6d918a57f8f339d495d54ab001f"
|
||||
"bob:bb22a5299220cad76ffd46190ccbeede8ab5dc260faa28b6e5a2cb31b9aff260"
|
||||
"charlie:554cef57437abac34522ac2c9f0490d685b72c80478cf9f7ed6f9570ee8624ea"
|
||||
)
|
||||
|
||||
for entry in "${USERS[@]}"; do
|
||||
username="${entry%%:*}"
|
||||
pubkey="${entry##*:}"
|
||||
|
||||
log "Checking for user '${username}'..."
|
||||
EXISTING_USER=$(kc GET "/${REALM}/users?username=${username}&exact=true" | jq -r '.[0].id // empty')
|
||||
|
||||
if [[ -n "${EXISTING_USER}" ]]; then
|
||||
warn "User '${username}' already exists (id: ${EXISTING_USER}) — updating nostr_pubkey attribute"
|
||||
kc PUT "/${REALM}/users/${EXISTING_USER}" -d '{
|
||||
"attributes": {
|
||||
"nostr_pubkey": ["'"${pubkey}"'"]
|
||||
}
|
||||
}'
|
||||
success "User '${username}' updated"
|
||||
else
|
||||
log "Creating user '${username}'..."
|
||||
kc POST "/${REALM}/users" -d '{
|
||||
"username": "'"${username}"'",
|
||||
"email": "'"${username}"'@sprout.local",
|
||||
"firstName": "'"${username^}"'",
|
||||
"lastName": "Test",
|
||||
"enabled": true,
|
||||
"emailVerified": true,
|
||||
"credentials": [{
|
||||
"type": "password",
|
||||
"value": "password123",
|
||||
"temporary": false
|
||||
}],
|
||||
"attributes": {
|
||||
"nostr_pubkey": ["'"${pubkey}"'"]
|
||||
}
|
||||
}'
|
||||
success "User '${username}' created (nostr_pubkey: ${pubkey:0:16}...)"
|
||||
fi
|
||||
done
|
||||
|
||||
# ---- Summary ----------------------------------------------------------------
|
||||
|
||||
echo ""
|
||||
echo -e "${GREEN}═══════════════════════════════════════════════════════${NC}"
|
||||
echo -e "${GREEN} Keycloak realm setup complete! 🔑${NC}"
|
||||
echo -e "${GREEN}═══════════════════════════════════════════════════════${NC}"
|
||||
echo ""
|
||||
echo -e " ${BLUE}Admin UI${NC} http://localhost:8180 (admin / admin)"
|
||||
echo -e " ${BLUE}Realm${NC} ${REALM}"
|
||||
echo -e " ${BLUE}Client${NC} ${CLIENT_ID} (public, direct access grants)"
|
||||
echo ""
|
||||
echo -e " ${BLUE}Test users${NC} (password: password123)"
|
||||
echo -e " tyler e5ebc6cdb579be112e336cc319b5989b4bb6af11786ea90dbe52b5f08d741b34"
|
||||
echo -e " alice 953d3363262e86b770419834c53d2446409db6d918a57f8f339d495d54ab001f"
|
||||
echo -e " bob bb22a5299220cad76ffd46190ccbeede8ab5dc260faa28b6e5a2cb31b9aff260"
|
||||
echo -e " charlie 554cef57437abac34522ac2c9f0490d685b72c80478cf9f7ed6f9570ee8624ea"
|
||||
echo ""
|
||||
echo -e " ${YELLOW}Relay env vars for Keycloak:${NC}"
|
||||
echo -e " OKTA_JWKS_URI=http://localhost:8180/realms/sprout/protocol/openid-connect/certs"
|
||||
echo -e " OKTA_ISSUER=http://localhost:8180/realms/sprout"
|
||||
echo -e " OKTA_AUDIENCE=sprout-desktop"
|
||||
echo -e " OKTA_PUBKEY_CLAIM=nostr_pubkey"
|
||||
echo ""
|
||||
echo -e " ${YELLOW}Get a token (direct grant):${NC}"
|
||||
echo -e " curl -s -X POST http://localhost:8180/realms/sprout/protocol/openid-connect/token \\"
|
||||
echo -e " -d 'client_id=sprout-desktop&grant_type=password&username=tyler&password=password123' \\"
|
||||
echo -e " | jq -r .access_token"
|
||||
echo ""
|
||||
|
||||
exit 0
|
||||
Reference in New Issue
Block a user