Skip to content

Commit 311db2e

Browse files
committed
feat(security): add OIDC bearer token authentication
Enables native and HTTP clients to authenticate using an OIDC bearer token, bypassing pgwire (which remains SCRAM-SHA-256 only). JwksRegistry refactor: - Introduces DecodedToken<'_> to share the decode + split step across all three validation entry points without re-splitting the token. - validate(): now delegates to decode_unverified, find_provider, resolve_key, verify_signature_and_time helpers. - validate_with_provider(): verifies against a named static provider (bypasses iss-based lookup); returns JwtClaims for claim-mapping. - validate_with_catalog_provider(): verifies against a catalog provider whose JWKS URI is supplied at call time (no server restart needed after CREATE OIDC PROVIDER). - refetch_catalog_key(): rate-limited on-demand JWKS re-fetch for catalog providers, sharing the same key cache as static providers. - build_identity() / parse_role_infallible() extracted as top-level functions; infallible Role::from_str handled by exhaustive match on the never type instead of unwrap. OIDC verify path (security/oidc/): - verify_bearer_token(): decodes iss from the token, looks up the matching provider in the catalog, delegates to validate_with_catalog_provider, applies claim-mapping rules, and constructs an ephemeral AuthenticatedIdentity with auth_method = OidcBearer and the database set derived from the claim mapping. - claim_mapping::apply_claim_mapping(): evaluates ordered rules against the decoded JwtClaims, accumulating default_database, accessible databases, and role grants. Wildcard claim value "*" matches any non-empty claim. - Tokens with no matching rule that assigns a database are rejected with OidcNoDefaultDatabase rather than silently routing to the default DB. Auth method plumbing: - AuthMethod::OidcBearer variant added to the enum and session protocol. - ProtoAuth::OidcBearer (with optional provider hint) added to the wire type in nodedb-types. - Native dispatch: OidcBearer handled before the existing JSON dispatch path so it avoids constructing a synthetic body. - pgwire session_auth: oidc_bearer case added alongside trust/password/ api_key; records AuthSuccess audit event and auth metrics. - Session registration: register_session now accepts token_expiry_ms so the idle-sweep loop can enforce token lifetime independently of the TCP connection. Error variants: - SessionIdleTimeout, SessionTokenExpired, SessionKilledByAdmin, SessionUserDropped, OidcUnknownProvider, OidcNoDefaultDatabase added with corresponding NodeDbError mappings in error_from.rs.
1 parent 951992c commit 311db2e

14 files changed

Lines changed: 791 additions & 101 deletions

File tree

nodedb-types/src/protocol/auth.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,15 @@ pub enum AuthMethod {
2020
Password { username: String, password: String },
2121
#[serde(rename = "api_key")]
2222
ApiKey { token: String },
23+
/// OIDC bearer token (native / HTTP clients only; NOT pgwire).
24+
#[serde(rename = "oidc_bearer")]
25+
OidcBearer {
26+
token: String,
27+
/// Optional provider name hint. When absent the provider is resolved by
28+
/// the `iss` claim in the token.
29+
#[serde(default)]
30+
provider: Option<String>,
31+
},
2332
}
2433

2534
fn default_username() -> String {

nodedb/src/control/security/identity/authenticated.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,8 @@ pub enum AuthMethod {
109109
Certificate,
110110
/// Trust mode (no authentication — dev only).
111111
Trust,
112+
/// OIDC bearer token (native / HTTP clients only; NOT pgwire).
113+
OidcBearer,
112114
}
113115

114116
#[cfg(test)]

0 commit comments

Comments
 (0)