Files
harmony/harmony_zitadel_auth/Cargo.toml
Reda Tarzalt 96e7d43b2f
Some checks failed
Run Check Script / check (pull_request) Failing after 38s
add auth to frontend through lib (#284)
Adds OIDC login support to the harmony-fleet-operator web dashboard using Zitadel SSO.

pkce was the recommended option for this since we don't need to hold on to any secret. We compute a value on server before sending the data to Zitadel who validates authenticity by recomputing the hash and comparing the two values.

pkce Auth flow

 1. User visits a protected dashboard route, like /devices.
 2. If no valid harmony_fleet_session cookie exists, the app redirects to /login.
 3. /login creates:
     - random state
     - random pkce_code_verifier
     - derived code_challenge = base64url(sha256(pkce_code_verifier))
 4. The app stores state and pkce_code_verifier in a temporary HTTP-only login-attempt cookie.
 5. The browser is redirected to Zitadel’s authorize endpoint with:
     - client_id
     - redirect_uri
     - scope
     - state
     - code_challenge
     - code_challenge_method=S256
 6. After SSO login, Zitadel redirects back to /auth/callback?code=...&state=....
 7. The callback handler:
     - parses the raw query into a strict success/failure enum
     - reads the temporary login-attempt cookie
     - validates returned state
     - exchanges code + pkce_code_verifier for tokens
     - validates the returned ID token using OIDC discovery/JWKS
     - creates a local harmony_fleet_session cookie
     - redirects to /
 8. Protected routes validate the local dashboard session cookie on each request.
 9. /logout clears the dashboard session cookie and redirects to /login.

---

 Auth middleware responses depending on request type:

 - normal browser request: redirect to /login
 - SSE request: 401 authentication required
 - HTMX request: 401 with HX-Redirect: /login (HTMX redirect is more idiomatic than through Axum for this)

Reviewed-on: #284
Reviewed-by: johnride <jg@nationtech.io>
Co-authored-by: Reda Tarzalt <tarzaltreda@gmail.com>
Co-committed-by: Reda Tarzalt <tarzaltreda@gmail.com>
2026-05-19 20:37:08 +00:00

31 lines
806 B
TOML

[package]
name = "harmony_zitadel_auth"
edition = "2024"
version.workspace = true
readme.workspace = true
license.workspace = true
[features]
default = []
axum = ["dep:axum", "dep:axum-extra"]
[dependencies]
anyhow.workspace = true
base64.workspace = true
chrono = { workspace = true, features = ["serde"] }
rand.workspace = true
reqwest.workspace = true
serde.workspace = true
serde_json.workspace = true
sha2 = "0.10"
url.workspace = true
tokio = { workspace = true, features = ["time"] }
arc-swap = "1"
time = "0.3"
tracing = { workspace = true }
jsonwebtoken = "9"
openidconnect = { version = "4", default-features = false, features = ["reqwest", "rustls-tls"] }
axum = { version = "0.8", optional = true }
axum-extra = { version = "0.10", features = ["cookie", "cookie-private"], optional = true }