Authentication and authorization¶
GeoSync is a browser-session application. It has three selectable modes:
central (current checked-in configuration), local (break-glass), and
keycloak (legacy OIDC). There is no implemented public API-key scheme and no
GeoSync JWT bearer contract. The bearer token used during OIDC callback is an
internal server-to-Keycloak userinfo call, not client authentication to
GeoSync.
Mode selection¶
geosync_auth_mode() chooses, in order:
- non-empty
GEOSYNC_AUTH_MODE; centralifCENTRAL_DATABASE_URLorCENTRAL_LOGIN_URLis set;centralif the request carries a non-emptyacugis_sessioncookie;config/auth.php's mode;local.
The checked-in config/auth.php selects central. Deployment values may be
loaded from deploy/geosync-auth.env or /etc/geosync-auth.env without
overwriting already-set environment variables. GEOSYNC_BASE_PATH may
override automatic /geosync-service or /geosync mount detection.
Central session mode¶
The browser sends raw cookie acugis_session. GeoSync hashes it as lowercase
SHA-256 and looks up dashboard_sessions.token_hash, requiring
expires_at > now() and an enabled dashboard_users row. The join is by
username. Group names come from auth_group_members/auth_groups, falling
back to the user's JSON groups. If direct Central DB resolution is unavailable
or fails, GeoSync tries authenticated GET /api/me (configured
CENTRAL_API_ME_URL, loopback :8888, then same-host /api/me).
Protected Central-mode requests:
- resolve the Central user;
- redirect unauthenticated users to
CENTRAL_LOGIN_URL(default/login) with a URL-encodednext; - require platform administrator status;
- hydrate the legacy PHP session key
qz_userwith a syntheticAdminobject whose ID isSUPER_ADMIN_ID.
An administrator is either dashboard_users.is_admin, or belongs
case-insensitively to administrator, administrators, admin, admins, or
dashboard-admin. Non-admin denial is HTTP 403 (JSON for /api/ or JSON
Accept, otherwise HTML). Central store failure is HTTP 503.
Central logout clears the PHP session and returns HTTP 303 to
CENTRAL_LOGOUT_URL (default /logout). Central login similarly redirects
with HTTP 303.
The repository also contains generic resource permission functions. Valid
permissions are view, edit, and admin; admin satisfies every check and
edit satisfies view. Administrator groups bypass resource checks, and the
Public group is implicitly included. The installed Phase 1A SQL grants
admin for service geosync only to administrators. The active prepend gate,
however, directly requires Central platform admin and does not call the
resource-level check.
Local mode¶
POST /admin/action/login.php accepts form fields submit, email, and
pwd. It loads public.user by email and applies password_verify, then
stores the row under PHP session key qz_user. Success and failure are browser
redirects, not JSON:
- success:
Location: ../../index.php; - failure:
Location: ../../login.php?err=....
Administrative action scripts generally require qz_user.accesslevel ==
'Admin'; read pages may require only a session or enforce ownership. Ownership
is based on owner_id, sharing constants, and the special
SUPER_ADMIN_ID. There is no CSRF token in the reviewed form action handlers;
the PHP session cookie is therefore the critical credential and callers should
use same-origin controls and HTTPS.
Public signup/verification files remain present but
geosync_registration_disabled.php blocks them before handler logic.
Legacy Keycloak OIDC¶
GET /auth/oidc/login.php creates a 16-byte random state, stores its hex value
in the session, and redirects to the issuer authorization endpoint with
authorization-code flow, scopes openid profile email, client ID, exact
redirect URI, and state.
GET /auth/oidc/callback.php?code=...&state=...:
- requires and constant-time validates one-use state;
- exchanges the code at the Keycloak token endpoint using the configured client secret;
- calls userinfo with the returned access token;
- extracts realm roles plus roles under
resource_access[client_id]; - optionally requires any role listed in
required_roles_any; - stores
kc_sub, email, name, and normalized roles in$_SESSION['auth']; - maps role
adminorgeosync_adminto legacyAdmin, all others toUser, and stores a compatibilityqz_userobject; - redirects to
post_login_redirect.
The implementation decodes access-token claims to read roles but does not locally verify the JWT signature/issuer/audience; successful token exchange and userinfo are relied upon. Do not expose the checked-in OIDC client secret; it must be rotated and supplied through deployment secret management. This documentation intentionally omits all secret values.
Legacy logout clears the PHP session and redirects to Keycloak's end-session
endpoint with client ID, an absolute post-logout URI, and id_token_hint when
available.
Google, GitHub, and Microsoft provider OAuth files¶
Top-level auth-google.php, auth-github.php, and auth-microsoft.php are
additional legacy OAuth authorization-code callbacks. Their configuration is
via constants in admin/incl/const.php; account auto-creation is governed by
DISABLE_OAUTH_USER_CREATION. Each uses OAuth state, looks up a local user by
provider email, and otherwise can create a local User.
These files contain placeholder qcarta redirect/viewer paths and are not
selected by geosync_auth_mode(). Treat them as legacy/incomplete integration,
not a supported API login contract.
Cookies, headers, and proxy identity¶
- Client authentication is a session cookie:
acugis_sessionin Central mode and the configured PHP session cookie containingqz_userin local/OIDC compatibility mode. /api/proxy.phpaccepts any ofuser_id,qz_user, or OIDCkc_subsession indicators. It returns HTTP 401 text when none exists.- When proxying an allowed operation, it sets upstream
Content-Type: application/jsonandX-User-IDto the resolved legacy session user ID (possibly empty for a pure OIDC session). This header is generated by GeoSync; clients must not rely on supplying it themselves. - The proxy forwards upstream status only when it is 400 or greater. Many
legacy admin actions return HTTP 200 with
{"success":false,...}and do not set JSON content type. Always evaluate the JSONsuccessmember. - No API key header, HTTP Basic API contract,
Authorization: Bearerhandling, refresh-token endpoint, or machine-to-machine grant was found.
Public-path exceptions¶
Central prepend excludes /login.php, /logout.php, /signup.php,
/admin/action/login.php, /admin/action/signup.php, and
/admin/action/verify.php. “Public” here means bypassing the Central prepend;
signup/verify are separately disabled, and local login still validates
credentials. OIDC endpoints are exempted by the older auth_gate.php when
that deployment mechanism is used.