#!/usr/bin/env sh set -eu if [ ! -f .env ]; then echo "missing .env" >&2 exit 1 fi set -a . ./.env set +a : "${KC_BOOTSTRAP_ADMIN_USERNAME:?set KC_BOOTSTRAP_ADMIN_USERNAME in .env}" : "${KC_BOOTSTRAP_ADMIN_PASSWORD:?set KC_BOOTSTRAP_ADMIN_PASSWORD in .env}" : "${GOOGLE_CLIENT_ID:?set GOOGLE_CLIENT_ID in .env}" : "${GOOGLE_CLIENT_SECRET:?set GOOGLE_CLIENT_SECRET in .env}" ./scripts/configure-broker-user-profile.sh keycloak_url="${KEYCLOAK_URL:-http://localhost:8080}" realm="${KEYCLOAK_REALM:-keycloak-patterns}" 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 )" payload="$( jq -n \ --arg client_id "$GOOGLE_CLIENT_ID" \ --arg client_secret "$GOOGLE_CLIENT_SECRET" \ '{ alias: "google", displayName: "Sign in with Google", providerId: "google", enabled: true, updateProfileFirstLoginMode: "off", trustEmail: false, storeToken: false, addReadTokenRoleOnCreate: false, authenticateByDefault: false, linkOnly: false, firstBrokerLoginFlowAlias: "first broker login", config: { clientId: $client_id, clientSecret: $client_secret, defaultScope: "openid profile email", syncMode: "IMPORT" } }' )" endpoint="$keycloak_url/admin/realms/$realm/identity-provider/instances" status="$( curl -sS -o /dev/null -w '%{http_code}' \ -H "Authorization: Bearer $admin_token" \ "$endpoint/google" )" if [ "$status" = "200" ]; then curl -fsS -X PUT \ -H "Authorization: Bearer $admin_token" \ -H "Content-Type: application/json" \ --data "$payload" \ "$endpoint/google" action="updated" else curl -fsS -X POST \ -H "Authorization: Bearer $admin_token" \ -H "Content-Type: application/json" \ --data "$payload" \ "$endpoint" action="created" fi mapper_endpoint="$endpoint/google/mappers" upsert_mapper() { mapper_name="$1" mapper_type="$2" mapper_config="$3" mapper_id="$( curl -fsS \ -H "Authorization: Bearer $admin_token" \ "$mapper_endpoint" | jq -r --arg name "$mapper_name" ' .[] | select(.name == $name) | .id ' | head -1 )" mapper_payload="$( jq -n \ --arg name "$mapper_name" \ --arg alias "google" \ --arg mapper "$mapper_type" \ --argjson config "$mapper_config" \ '{ name: $name, identityProviderAlias: $alias, identityProviderMapper: $mapper, config: $config }' )" if [ -n "$mapper_id" ]; then curl -fsS -X PUT \ -H "Authorization: Bearer $admin_token" \ -H "Content-Type: application/json" \ --data "$mapper_payload" \ "$mapper_endpoint/$mapper_id" else curl -fsS -X POST \ -H "Authorization: Bearer $admin_token" \ -H "Content-Type: application/json" \ --data "$mapper_payload" \ "$mapper_endpoint" fi } upsert_mapper \ "google-stable-username" \ "oidc-username-idp-mapper" \ '{"template":"${ALIAS}.${CLAIM.sub}","target":"LOCAL"}' upsert_mapper \ "google-email" \ "oidc-user-attribute-idp-mapper" \ '{"syncMode":"INHERIT","claim":"email","user.attribute":"email"}' upsert_mapper \ "google-given-name" \ "oidc-user-attribute-idp-mapper" \ '{"syncMode":"INHERIT","claim":"given_name","user.attribute":"firstName"}' upsert_mapper \ "google-family-name" \ "oidc-user-attribute-idp-mapper" \ '{"syncMode":"INHERIT","claim":"family_name","user.attribute":"lastName"}' upsert_mapper \ "google-picture" \ "oidc-user-attribute-idp-mapper" \ '{"syncMode":"INHERIT","claim":"picture","user.attribute":"picture"}' upsert_mapper \ "google-hosted-domain" \ "oidc-user-attribute-idp-mapper" \ '{"syncMode":"INHERIT","claim":"hd","user.attribute":"hd"}' upsert_mapper \ "google-example-domain-role" \ "oidc-role-idp-mapper" \ '{"syncMode":"INHERIT","claim":"hd","claim.value":"example.test","role":"employee-role"}' echo "Google Identity Provider $action for realm '$realm'" echo "Register this exact Google redirect URI:" echo "$keycloak_url/realms/$realm/broker/google/endpoint"