Skip to content

Captcha + privacy on signup, profile picture upload, Keycloak SPIs#11

Merged
felixevers merged 3 commits into
mainfrom
claude/add-captcha-privacy-signup-x15Hc
May 20, 2026
Merged

Captcha + privacy on signup, profile picture upload, Keycloak SPIs#11
felixevers merged 3 commits into
mainfrom
claude/add-captcha-privacy-signup-x15Hc

Conversation

@felixevers
Copy link
Copy Markdown
Member

Summary

Adds the three pieces requested for signup hardening and account profile pictures, plus the Keycloak SPIs that back them and the deployment docs.

Frontend (Keycloakify theme)

  • Cloudflare Turnstile widget on the Register page (script-loaded, hidden cf-turnstile-response input). Submit is blocked until the captcha resolves a token.
  • Privacy policy checkbox on the same page linking to https://helpwave.de/privacy. Submit is blocked until ticked.
  • Profile picture upload + remove UI in AccountSettings (replaces the previous "coming soon" placeholder) talking to the new SPI; client-side type + size validation.
  • New i18n keys in en-US.arb / de-DE.arb; translations.ts regenerated.
  • KcContext extended per-page (turnstileSiteKey on register; profilePictureApiUrl + profilePictureUrl on account). Keycloakify env vars TURNSTILE_SITE_KEY and PROFILE_PICTURE_API_URL exposed via kc.gen.tsx.

Backend — new keycloak-extensions/ Maven multi-module (KC 26.6.0)

  • helpwave-turnstile-authenticatorFormAction SPI. Site key + secret configurable per registration flow in the admin console. POSTs the token to https://challenges.cloudflare.com/turnstile/v0/siteverify and fails registration on bad / missing token.
  • helpwave-privacy-acceptanceFormAction SPI. Requires the checkbox; writes privacy_policy_accepted, privacy_policy_accepted_at (ISO‑8601) and privacy_policy_version (optional, configurable) user attributes when registration completes.
  • helpwave-profile-pictureRealmResourceProvider mounted at /realms/{realm}/helpwave-picture. Authenticates with the standard Keycloak bearer token, accepts raw image bytes or multipart/form-data, scales to 512 / 256 / 128 / 64 px square JPEGs with Thumbnailator (re-encoded → metadata stripped), uploads to any S3-compatible bucket (AWS SDK v2; Cloudflare R2 supported via custom endpoint). The primary URL is stored on the standard OIDC picture attribute; thumbnails on picture_thumb_64|128|256. DELETE cleans up the previous version's objects + attributes. Shaded JAR is ~13.5 MB.

We didn't find a maintained community plugin covering KC 26 for either Turnstile or R2-backed avatars that we'd trust in production, so all three are built from scratch (as you preferred).

Deployment

  • README.md rewritten with a build matrix, jar inventory, admin-console wiring for the two form actions, full R2 + S3 env-var / SPI key configuration tables, and theme env vars.
  • .github/workflows/ci.yaml now sets up Java 17, runs lint + typecheck, builds the Maven modules, and attaches all four jars to the GitHub release.
  • .gitignore ignores keycloak-extensions/**/target/.

Version

package.json bumped 0.1.140.2.0 to trigger the publish workflow once this lands on main.

Test plan

  • npm ci && npm run lint && npm run typecheck && npm run build-keycloak-theme (all pass locally)
  • cd keycloak-extensions && mvn -DskipTests package (all 3 jars build; profile-picture shaded JAR contains AWS SDK + Thumbnailator)
  • Drop all four jars into Keycloak providers/, run kc.sh build
  • In admin console: duplicate the registration flow, add Cloudflare Turnstile (helpwave) (Required) + Privacy Policy Acceptance (helpwave) (Required), bind it as the realm's Registration flow
  • Configure SPI helpwave-picture via env vars (see README) pointing at an R2 bucket
  • Walk through /realms/<realm>/.../registrations with the Turnstile widget visible; verify token validation fails on tampered tokens and succeeds otherwise
  • Confirm privacy_policy_accepted_at is populated on the new user
  • Upload a >5 MB picture (rejected client- and server-side), an unsupported type (rejected), and a valid JPEG (stored + thumbs visible; picture attribute set)
  • Confirm DELETE /realms/<realm>/helpwave-picture removes both bucket objects and attributes

Generated by Claude Code

Frontend (Keycloakify theme):
- Register.tsx now renders a Cloudflare Turnstile widget and a privacy
  policy checkbox linking to https://helpwave.de/privacy. Submission is
  blocked until both are satisfied.
- AccountSettings.tsx replaces the "coming soon" placeholder with a real
  profile picture upload (and remove) flow that talks to the new SPI.
- Adds translation keys for the captcha + privacy + picture UI in
  en-US and de-DE.
- Extends KcContext with turnstileSiteKey (register) and
  profilePictureApiUrl / profilePictureUrl (account); exposes
  TURNSTILE_SITE_KEY and PROFILE_PICTURE_API_URL as Keycloakify env vars.

Backend (new keycloak-extensions/ Maven multi-module):
- helpwave-turnstile-authenticator: FormAction SPI that renders the
  Turnstile widget server-side and verifies the token against
  Cloudflare's siteverify endpoint. Site key + secret are configured
  per registration flow in the Keycloak admin console.
- helpwave-privacy-acceptance: FormAction SPI that requires the
  privacy checkbox and stores acceptance metadata on the user as
  privacy_policy_accepted / privacy_policy_accepted_at /
  privacy_policy_version attributes.
- helpwave-profile-picture: RealmResource SPI exposing
  /realms/{realm}/helpwave-picture. Authenticates with the standard
  bearer token, scales uploads to 512/256/128/64 px square JPEGs with
  Thumbnailator and stores them in any S3-compatible bucket (AWS S3 or
  Cloudflare R2) via AWS SDK v2. Primary URL is written to the
  standard OIDC `picture` attribute; thumbnails to picture_thumb_*.

Deployment:
- README rewritten with build instructions, jar inventory, admin-console
  steps for the form actions and full storage configuration matrix
  (SPI keys + env vars) for R2 and AWS S3 setups.
- CI workflow now builds the Maven modules in addition to the theme,
  runs lint + typecheck, and attaches all four jars to the release.

Version bumped to 0.2.0 to trigger publish.
@cloudflare-workers-and-pages
Copy link
Copy Markdown

cloudflare-workers-and-pages Bot commented May 20, 2026

Deploying id-helpwave-de with  Cloudflare Pages  Cloudflare Pages

Latest commit: e70c044
Status: ✅  Deploy successful!
Preview URL: https://c1f12288.id-helpwave-de.pages.dev
Branch Preview URL: https://claude-add-captcha-privacy-s.id-helpwave-de.pages.dev

View logs

@felixevers felixevers self-assigned this May 20, 2026
claude added 2 commits May 20, 2026 12:23
- New docs/deployment-nixos.md covers fetching all 4 release jars,
  services.keycloak.plugins wiring, the long
  spi-realm-restapi-extension-helpwave-picture-* SPI key prefix that
  Keycloak actually expects (with NixOS _secret file integration),
  TURNSTILE_SITE_KEY / PROFILE_PICTURE_API_URL theme env vars via
  systemd.services.keycloak.serviceConfig.Environment, and both
  manual-admin-console and declarative-realm-export setups for the
  Turnstile + Privacy form actions.
- Corrects the env-var names in README.md (the previous
  KC_SPI_HELPWAVE_PICTURE_DEFAULT_* and KC_HELPWAVE_* prefixes were
  wrong) and links to the new NixOS guide.
Replaces the small middle-of-page Chip with a full-width sticky banner
plus a 4 px viewport outline keyed off a per-realm accent color and a
[TEAM]/[ADMIN] document-title prefix. Customer realms render no banner
and look exactly as before.

- New RealmBanner component: sticky-top bar, icon (Users/ShieldAlert/Tag),
  bold uppercase headline ("TEAM WORKSPACE · team", "ADMINISTRATOR PORTAL
  · master"), short subtitle, plus inset box-shadow on body for the
  outline. Admin realms get a diagonal-stripe background for extra
  attention; team realms get a solid bar.
- realmColor.ts now exposes a RealmTheme (kind/color/cssToken/intensity)
  and getRealmKind helper, so future code paths can branch on realm kind
  without re-hashing the name. getRealmColor kept as a thin shim.
- Drops the obsolete RealmChip from both PageLayout and AccountPageLayout
  (the banner subsumes it) and deletes the file.
- Adds i18n keys realmBannerTeam / realmBannerAdmin / realmBannerOther
  and matching subtitles in en-US and de-DE.

Bumps the version to 0.3.0 to release the new theme jar.
@felixevers felixevers merged commit 4530a56 into main May 20, 2026
4 checks passed
@felixevers felixevers deleted the claude/add-captcha-privacy-signup-x15Hc branch May 20, 2026 13:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants