#!/usr/bin/env sh set -eu mode="${1:-}" case "$mode" in vulnerable|secure) ;; *) echo "usage: $0 vulnerable|secure" >&2 exit 1 ;; esac if [ ! -f .env ]; then echo "missing .env" >&2 exit 1 fi set -a . ./.env set +a keycloak_url="${KEYCLOAK_URL:-http://localhost:8080}" realm="${KEYCLOAK_REALM:-keycloak-patterns}" admin_base="$keycloak_url/admin/realms/$realm" vulnerable_flow="vulnerable first broker login" idp_url="$admin_base/identity-provider/instances/mock-google" admin_token="$( curl -fsS \ -d client_id=admin-cli \ -d grant_type=password \ -d "username=$KC_BOOTSTRAP_ADMIN_USERNAME" \ -d "password=$KC_BOOTSTRAP_ADMIN_PASSWORD" \ "$keycloak_url/realms/master/protocol/openid-connect/token" | jq -er .access_token )" auth_header="Authorization: Bearer $admin_token" encode() { jq -rn --arg value "$1" '$value | @uri' } flows="$(curl -fsS -H "$auth_header" "$admin_base/authentication/flows")" flow_id="$( printf '%s' "$flows" | jq -r --arg alias "$vulnerable_flow" ' .[] | select(.alias == $alias) | .id ' | head -1 )" if [ -n "$flow_id" ]; then existing_executions="$( curl -fsS -H "$auth_header" \ "$admin_base/authentication/flows/$(encode "$vulnerable_flow")/executions" )" if printf '%s' "$existing_executions" | jq -e ' any(.[]; .authenticationFlow == true) ' >/dev/null; then idp_before_delete="$(curl -fsS -H "$auth_header" "$idp_url")" printf '%s' "$idp_before_delete" | jq '.firstBrokerLoginFlowAlias = "first broker login"' | curl -fsS -X PUT \ -H "$auth_header" \ -H "Content-Type: application/json" \ --data @- \ "$idp_url" curl -fsS -X DELETE \ -H "$auth_header" \ "$admin_base/authentication/flows/$flow_id" flow_id="" fi fi if [ -z "$flow_id" ]; then curl -fsS -X POST \ -H "$auth_header" \ -H "Content-Type: application/json" \ --data "$( jq -n --arg alias "$vulnerable_flow" '{ alias: $alias, description: "INSECURE LEARNING FLOW - automatic email linking", providerId: "basic-flow", topLevel: true, builtIn: false }' )" \ "$admin_base/authentication/flows" fi executions_url="$admin_base/authentication/flows/$(encode "$vulnerable_flow")/executions" executions="$(curl -fsS -H "$auth_header" "$executions_url")" create_user_id="$( printf '%s' "$executions" | jq -r '.[] | select(.providerId == "idp-create-user-if-unique") | .id' | head -1 )" if [ -z "$create_user_id" ]; then curl -fsS -X POST \ -H "$auth_header" \ -H "Content-Type: application/json" \ --data '{"provider":"idp-create-user-if-unique"}' \ "$admin_base/authentication/flows/$(encode "$vulnerable_flow")/executions/execution" executions="$(curl -fsS -H "$auth_header" "$executions_url")" create_user_id="$( printf '%s' "$executions" | jq -r '.[] | select(.providerId == "idp-create-user-if-unique") | .id' | head -1 )" fi auto_link_id="$( printf '%s' "$executions" | jq -r '.[] | select(.providerId == "idp-auto-link") | .id' | head -1 )" if [ -z "$auto_link_id" ]; then curl -fsS -X POST \ -H "$auth_header" \ -H "Content-Type: application/json" \ --data '{"provider":"idp-auto-link"}' \ "$admin_base/authentication/flows/$(encode "$vulnerable_flow")/executions/execution" executions="$(curl -fsS -H "$auth_header" "$executions_url")" auto_link_id="$( printf '%s' "$executions" | jq -r '.[] | select(.providerId == "idp-auto-link") | .id' | head -1 )" fi if [ "$mode" = "vulnerable" ]; then curl -fsS -X PUT \ -H "$auth_header" \ -H "Content-Type: application/json" \ --data "$(jq -n --arg id "$create_user_id" '{id: $id, requirement: "ALTERNATIVE"}')" \ "$executions_url" curl -fsS -X PUT \ -H "$auth_header" \ -H "Content-Type: application/json" \ --data "$(jq -n --arg id "$auto_link_id" '{id: $id, requirement: "ALTERNATIVE"}')" \ "$executions_url" selected_flow="$vulnerable_flow" else selected_flow="first broker login" fi idp="$(curl -fsS -H "$auth_header" "$idp_url")" printf '%s' "$idp" | jq --arg flow "$selected_flow" '.firstBrokerLoginFlowAlias = $flow' | curl -fsS -X PUT \ -H "$auth_header" \ -H "Content-Type: application/json" \ --data @- \ "$idp_url" assigned="$( curl -fsS -H "$auth_header" "$idp_url" | jq -r .firstBrokerLoginFlowAlias )" test "$assigned" = "$selected_flow" if [ "$mode" = "secure" ]; then secure_executions="$( curl -fsS -H "$auth_header" \ "$admin_base/authentication/flows/$(encode "first broker login")/executions" )" printf '%s' "$secure_executions" | jq -e ' any(.[]; .providerId == "idp-confirm-link" and .requirement == "REQUIRED" ) and (any(.[]; .providerId == "idp-auto-link" and .requirement != "DISABLED" ) | not) ' >/dev/null fi echo "mock-google First Broker Login mode: $mode ($selected_flow)"