gitshark

Clone repository

git clone https://gitshark.de/git/workaround/Gitshark.git
git clone git@gitshark.de:workaround/Gitshark.git

← Commits

๐Ÿ”ง (OIDC): Add PKCE support

ce85beac1938dbc51304cae4f4e225e2e1f5669b ยท Miggi ยท 2026-06-26T13:53:55Z

Changes

3 files changed, +51 -0

MODIFY README.md +2 -0
diff --git a/README.md b/README.md
index 921d574..f128cbe 100644
--- a/README.md
+++ b/README.md
@@ -66,6 +66,8 @@
66 66 | `GITSHARK_SSH_HOST_KEY` | `data/ssh/host-key` | Persisted SSH host key file |
67 67 | `QUARKUS_DATASOURCE_JDBC_URL` / `_USERNAME` / `_PASSWORD` | โ€” (Dev Services in dev/test) | PostgreSQL connection |
68 68 | `QUARKUS_OIDC_AUTH_SERVER_URL` / `_CLIENT_ID` / `_CREDENTIALS_SECRET` | โ€” (Keycloak Dev Services in dev/test) | OIDC provider |
69 +| `QUARKUS_OIDC_AUTHENTICATION_STATE_SECRET` | โ€” (dev/test use a fixed dev secret) | Encrypts the OIDC state cookie carrying the PKCE `code_verifier`; โ‰ฅ 32 chars, stable across pods |
70 +| `QUARKUS_OIDC_TOKEN_STATE_ENCRYPTION_SECRET` | โ€” (falls back to credentials secret) | Encrypts the post-login session cookie holding the tokens; โ‰ฅ 32 chars, set explicitly for multi-pod |
69 71 | `GITSHARK_FEDERATION_ENABLED` | `false` | Master switch for ForgeFed federation |
70 72 | `GITSHARK_FEDERATION_BASE_URL` | โ€” | Public HTTPS origin (e.g. `https://shark.example`); actor IDs derive from it and are permanent |
71 73 | `GITSHARK_FEDERATION_PEER_ALLOWLIST` | โ€” (empty = deny all) | Comma-separated peer hosts allowed to send/receive federation traffic |
MODIFY src/main/resources/application.properties +17 -0
diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties
index 8b6b7f4..663b387 100644
--- a/src/main/resources/application.properties
+++ b/src/main/resources/application.properties
@@ -23,6 +23,23 @@
23 23 quarkus.oidc.logout.path=/logout
24 24 quarkus.oidc.logout.post-logout-path=/
25 25
26 +# PKCE: kanidm enforces PKCE for the authorization code flow. The code_verifier rides through the
27 +# redirect inside the state cookie, which must be encrypted with a stable, explicitly-set secret so
28 +# every pod agrees on the key (otherwise a callback can land on a pod that cannot decrypt the cookie).
29 +# Production supplies QUARKUS_OIDC_AUTHENTICATION_STATE_SECRET (>= 32 chars) via environment.
30 +# token-state-manager.encryption-secret protects the post-login session cookie holding the tokens;
31 +# it falls back to credentials.secret, but set it explicitly for multi-pod deployments.
32 +quarkus.oidc.authentication.pkce-required=true
33 +quarkus.oidc.authentication.state-secret=${QUARKUS_OIDC_AUTHENTICATION_STATE_SECRET:}
34 +quarkus.oidc.token-state-manager.encryption-secret=${QUARKUS_OIDC_TOKEN_STATE_ENCRYPTION_SECRET:}
35 +%dev,test.quarkus.oidc.authentication.state-secret=dev-only-oidc-state-secret-0123456789
36 +
37 +# Behind the K3s ingress: trust X-Forwarded-* so OIDC builds the external https redirect_uri.
38 +quarkus.http.proxy.proxy-address-forwarding=true
39 +quarkus.http.proxy.allow-x-forwarded=true
40 +quarkus.oidc.authentication.force-redirect-https-scheme=true
41 +%dev,test.quarkus.oidc.authentication.force-redirect-https-scheme=false
42 +
26 43 # Dev-only convenience (see DevDataSeeder / UserProvisioningService):
27 44 # - seed-data: on dev startup, create user alice + a public "demo" repo with one commit (idempotent).
28 45 # - adopt-username: let a login adopt the seeded same-username row even though Keycloak Dev Services
ADD src/test/java/de/workaround/account/OidcPkceConfigTest.java +32 -0
diff --git a/src/test/java/de/workaround/account/OidcPkceConfigTest.java b/src/test/java/de/workaround/account/OidcPkceConfigTest.java
new file mode 100644
index 0000000..987daf5
--- /dev/null
+++ b/src/test/java/de/workaround/account/OidcPkceConfigTest.java
@@ -0,0 +1,32 @@
1 +package de.workaround.account;
2 +
3 +import static org.junit.jupiter.api.Assertions.assertTrue;
4 +
5 +import org.eclipse.microprofile.config.ConfigProvider;
6 +import org.junit.jupiter.api.Test;
7 +
8 +import io.quarkus.test.junit.QuarkusTest;
9 +
10 +/**
11 + * PKCE must be enabled for the OIDC authorization code flow: kanidm (the production identity provider)
12 + * enforces PKCE for confidential clients. The state cookie that carries the PKCE code_verifier across
13 + * the redirect must be encrypted with an explicitly configured secret so multiple pods agree on the key.
14 + */
15 +@QuarkusTest
16 +class OidcPkceConfigTest {
17 +
18 + @Test
19 + void pkceIsRequiredForCodeFlow() {
20 + boolean pkceRequired = ConfigProvider.getConfig()
21 + .getValue("quarkus.oidc.authentication.pkce-required", Boolean.class);
22 + assertTrue(pkceRequired, "quarkus.oidc.authentication.pkce-required must be true");
23 + }
24 +
25 + @Test
26 + void stateCookieSecretIsConfigurable() {
27 + String secret = ConfigProvider.getConfig()
28 + .getOptionalValue("quarkus.oidc.authentication.state-secret", String.class)
29 + .orElse("");
30 + assertTrue(secret.length() >= 32, "state-secret must be >= 32 chars; was " + secret.length());
31 + }
32 +}

Keyboard shortcuts

?Show this help
g hGo home
EscClose dialog