Wiki PoC Keycloak Configuration ==================================== Keycloak: auth.josie.cloud (v26.5.3, operator-managed on OCP) Realm: josie Client ID: wiki-poc Client Secret: WtJRfotqQ5yQWluWgrTxslOqJWXLxTsb Client UUID: af288081-ed1b-4a1a-be1e-552b1cb8464c Redirect URIs: - http://127.0.0.1:8083/index.php?title=Special:PluggableAuthLogin - http://127.0.0.1:8083/index.php?title=Special:LinkSSO/callback - http://127.0.0.1:8083/index.php/Special:PluggableAuthLogin - http://127.0.0.1:8083/index.php/Special:LinkSSO/callback Web Origins: - http://127.0.0.1:8083 Protocol Mappers: - group-membership: maps Keycloak groups to "groups" claim in tokens Group Sync Config: - Wiki Admins (Keycloak group) -> sysop + bureaucrat (MediaWiki groups) Test User (Keycloak): - Username: testdev - Password: testpass - Groups: Developers - Keycloak sub: a135bad2-5164-44bc-a5e9-c6ff4cc21af9 Test Users (MediaWiki): - Admin / admin1234admin (sysop) - TestSysop / testpass12345 (sysop) Branch: sso-integration (2 commits on top of upstream) Codebase: /home/josie/development/archlinux/archwiki/ Implementation (committed): - extensions/SSOLink/extension.json: extension manifest, hook handler registration - extensions/SSOLink/includes/SpecialLinkSSO.php: Special:LinkSSO page - GET: shows linking status (linked/unlinked) with link/unlink buttons - POST action=link: CSRF-validated, OIDC discovery, state generation, Keycloak redirect - GET callback: state validation, code exchange, userinfo, write to openid_connect table - POST action=unlink: CSRF-validated, delete from openid_connect table - extensions/SSOLink/includes/SSOLinkHooks.php: PluggableAuthUserAuthorization hook - Denies SSO login when Keycloak sub is not linked to a wiki account - Prevents auto-creation of new accounts for unlinked SSO users - extensions/SSOLink/i18n/en.json: 18 i18n messages - extensions/SSOLink/i18n/qqq.json: message documentation - extensions/PluggableAuth: submodule (REL1_45, v7.5.0) - extensions/OpenIDConnect: submodule (REL1_45, v8.3.0) LocalSettings.php Config (gitignored): - wfLoadExtension('PluggableAuth') - wfLoadExtension('OpenIDConnect') - wfLoadExtension('SSOLink') - $wgPluggableAuth_EnableLocalLogin = true - $wgPluggableAuth_EnableLocalProperties = false - $wgOpenIDConnect_MigrateUsersByEmail = false - $wgOpenIDConnect_MigrateUsersByUserName = false - $wgPluggableAuth_Config['Arch Linux SSO'] with providerURL, clientID, clientsecret, groupsyncs - $wgSSOLinkProviderURL / ClientID / ClientSecret Dev Setup: - podman network: archwiki-dev - MariaDB: podman run -d --name archwiki-db --network archwiki-dev -e MARIADB_ROOT_PASSWORD=archwiki -e MARIADB_DATABASE=archwiki -e MARIADB_USER=archwiki -e MARIADB_PASSWORD=archwiki -p 127.0.0.1:13307:3306 mariadb:11 - PHP-FPM: podman run -d --name archwiki-app --network archwiki-dev -v /path/to/archwiki:/var/www/mediawiki:z -p 127.0.0.1:9083:9000 php:8.3-fpm - nginx: podman run -d --name archwiki-web --network archwiki-dev -v /path/to/archwiki:/var/www/mediawiki:z,ro -v /path/to/nginx-poc.conf:/etc/nginx/conf.d/default.conf:z,ro -p 127.0.0.1:8083:80 nginx:alpine - After installing PHP extensions: docker-php-ext-configure gd --with-freetype --with-jpeg && docker-php-ext-install intl mysqli gd xml zip opcache - Composer deps: cd extensions/OpenIDConnect && composer install --no-dev - If you restart archwiki-app, also restart archwiki-web (podman networking) - Port 8083 (archweb=8080, aurweb=8082) Flows verified: - Account linking: local login -> Special:LinkSSO -> Keycloak -> linked - SSO login: login page -> Arch Linux SSO -> Keycloak -> logged in as linked account - Unlinked SSO rejection: login page -> Arch Linux SSO -> Keycloak -> "User not authorized" - Unlinking: Special:LinkSSO -> unlink -> unlinked - Post-unlink SSO rejection: login -> Arch Linux SSO -> rejected again - Page title: "Link SSO Account" (not raw "linksso") Infrastructure Changes (branch: archwiki-sso in infrastructure repo): Repo: /home/josie/development/archlinux/infrastructure/ Base: master (includes archweb OIDC commit 34a809e0) Commits: 1dd5536a archwiki: Add Keycloak OIDC client and group mapper 20991b2e archwiki: Add OIDC configuration defaults ba93fe2d archwiki: Add composer and OpenIDConnect dependency install a66c8b87 archwiki: Add SSO configuration to LocalSettings.php 4f648586 archwiki: Remove unused scopes variable and make composer task idempotent Files: - tf-stage2/keycloak.tf: vault_archwiki data source, openid_archwiki client, group mapper - roles/archwiki/defaults/main.yml: oidc_client_id, oidc_provider_url, oidc_enable_local_login - roles/archwiki/tasks/main.yml: composer package, idempotent composer install task - roles/archwiki/templates/LocalSettings.php.j2: PluggableAuth + OpenIDConnect + SSOLink config Production client ID: openid_archwiki Production provider URL: https://accounts.archlinux.org/realms/archlinux/ Production redirect URIs: - https://wiki.archlinux.org/index.php?title=Special:PluggableAuthLogin - https://wiki.archlinux.org/index.php?title=Special:LinkSSO/callback Generated client secret: a285178f9f67f2c034b6733b3a0041165bbd8ea76ea7efdfcb221d4263ef7fa6 (must be added to vault_archwiki.yml as vault_archwiki_openid_client_secret) Deployment Prerequisites: 1. Merge archwiki sso-integration branch (adds PluggableAuth, OpenIDConnect, SSOLink extensions) 2. Add vault_archwiki_openid_client_secret to group_vars/all/vault_archwiki.yml 3. Update archwiki_version in defaults/main.yml to a release including SSO extensions 4. terraform apply (creates Keycloak client) 5. Ansible deploy (picks up new LocalSettings.php config) 6. Verify group mapping paths (Wiki/Admins) against actual token claims (full.path=false in group mapper means leaf group name only) Bugs Found During PoC: - $wgPluggableAuth_EnableAutoCreation does not exist in PluggableAuth 7.5.0 (no-op) - $wgGroupPermissions['*']['autocreateaccount'] = false also doesn't prevent PluggableAuth auto-creation - Correct fix: PluggableAuthUserAuthorization hook that checks openid_connect table - MW installer requires 10+ char passwords (admin1234 too short) - After restarting archwiki-app container, archwiki-web loses connection (restart both) - MediaWiki special page title key is lowercase page name (e.g. "linksso"), not prefixed - openid_connect table columns oidc_subject and oidc_issuer are tinyblob, not varchar - OpenIDConnect extension stores issuer WITH trailing slash from providerURL config