mirror of
https://github.com/lancedb/lancedb.git
synced 2026-09-22 04:55:39 +00:00
Stacked on #4173 (`jack/restore-oidc-flows`, base branch mirrored to this repo so the diff shows only this change); context from review: https://github.com/lancedb/lancedb/pull/4173#issuecomment-5674048100. Rebase to `main` once #4173 and #4179 merge. ## What moved to the `oauth2` crate (5.0, no default features) - Authorization URL generation and CSRF state (`authorize_url`, `CsrfToken`) - PKCE S256 challenge/verifier generation and code exchange - Client-credentials, authorization-code, refresh-token, and device-code grant request construction - Device authorization request and the device token polling loop (`authorization_pending`, `slow_down` +5s, expiry deadline, denial, network backoff capped at 10s) - Standard success/error response parsing (`RequestTokenError`) - Token-endpoint client authentication and standards-compliant parameter encoding (RFC 6749 2.3.1 Basic encoding) LanceDB keeps ownership of OIDC discovery (compared `openidconnect`: no measurable win for our 3-field metadata + strict validation, at real dependency cost), HTTPS-or-loopback endpoint enforcement, the loopback callback server, browser/stderr prompts, token caching and refresh orchestration, and the dedicated hardened Azure IMDS source, which is unchanged. ## Client authentication methods New `ClientAuthMethod` enum (`none` | `client_secret_basic` | `client_secret_post`), exposed in Rust, Python, and Node. Unset resolves to `client_secret_basic` when a secret is present (RFC 6749 2.3.1 recommendation and the normal Okta confidential-app default, so a default Okta app works without weakening its configuration) and to `none` for public clients (PKCE/device). Explicit `none` with a secret, or basic/post without one, is rejected. The method applies to client credentials, code exchange, refresh, and device requests. Deliberate behavior change: confidential clients previously always sent the secret in the POST body; they now default to Basic (Keycloak accepts both). No `audience`/`resource` parameters were added: the supported target is an Okta custom authorization server with the API audience configured server-side, so client-provided audience parameters are unnecessary; `add_extra_param` support exists if a concrete provider contract ever needs them. ## Device polling behavior changes (deliberate, tested) - The first token poll now happens immediately rather than after one interval (RFC 8628 allows both). - Transient failures (HTTP 429, 5xx, `temporarily_unavailable`, network errors) now retry with exponential backoff capped at 10s instead of retrying at the fixed interval; polling never spins faster than once per second even if a server reports a zero interval. ## Security and compatibility - Issuer and discovered endpoints (and device verification URIs) still require HTTPS except explicit loopback HTTP, enforced before any crate URL type is built - Token HTTP client keeps the hardened redirect policy that refuses insecure redirect targets; regression test added - Errors never embed raw response bodies (avoids leaking tokens through parse failures); all credential types stay redacted in Debug - Transient conditions (429/5xx/`temporarily_unavailable`) remain retryable in device polling and hard errors elsewhere; refresh keeps rotation and reauthentication semantics - Existing public APIs stay source-compatible except the added `OAuthConfig.client_auth_method` field ## Tests Rust: client-auth methods across code exchange/refresh/client-credentials/device (none/basic/post), auth-method resolution and validation, transient device retries, denial/expiry, redirect rejection, malformed-response leak check, PKCE URL assertions, redaction. Python and Node: enum values, conversion, unknown-method errors, config defaults. Manual Okta validation recipe (no automated Okta credentials): create a custom authorization server with an API audience, one confidential web app (Basic) for authorization-code, one native app (PKCE, no secret), one native device app; point `issuer_url` at the custom server, set `client_auth_method` only for the POST-required case; verify token acquisition, refresh after expiry, and `x-lancedb-credential-type: oidc` against a LanceDB deployment. Never commit tenant URLs or secrets. Co-authored-by: Xuanwo <github@xuanwo.io>
95 lines
4.3 KiB
TOML
95 lines
4.3 KiB
TOML
[workspace]
|
|
members = ["rust/lancedb", "nodejs", "python"]
|
|
resolver = "2"
|
|
|
|
[workspace.package]
|
|
edition = "2024"
|
|
authors = ["LanceDB Devs <dev@lancedb.com>"]
|
|
license = "Apache-2.0"
|
|
repository = "https://github.com/lancedb/lancedb"
|
|
description = "Serverless, low-latency vector database for AI applications"
|
|
keywords = ["lancedb", "lance", "database", "vector", "search"]
|
|
categories = ["database-implementations"]
|
|
rust-version = "1.91.0"
|
|
|
|
[workspace.dependencies]
|
|
lance = { "version" = "=13.0.0-beta.3", default-features = false, "tag" = "v13.0.0-beta.3", "git" = "https://github.com/lance-format/lance.git" }
|
|
lance-core = { "version" = "=13.0.0-beta.3", "tag" = "v13.0.0-beta.3", "git" = "https://github.com/lance-format/lance.git" }
|
|
lance-datagen = { "version" = "=13.0.0-beta.3", "tag" = "v13.0.0-beta.3", "git" = "https://github.com/lance-format/lance.git" }
|
|
lance-file = { "version" = "=13.0.0-beta.3", "tag" = "v13.0.0-beta.3", "git" = "https://github.com/lance-format/lance.git" }
|
|
lance-io = { "version" = "=13.0.0-beta.3", default-features = false, "tag" = "v13.0.0-beta.3", "git" = "https://github.com/lance-format/lance.git" }
|
|
lance-index = { "version" = "=13.0.0-beta.3", "tag" = "v13.0.0-beta.3", "git" = "https://github.com/lance-format/lance.git" }
|
|
lance-linalg = { "version" = "=13.0.0-beta.3", "tag" = "v13.0.0-beta.3", "git" = "https://github.com/lance-format/lance.git" }
|
|
lance-namespace = { "version" = "=13.0.0-beta.3", "tag" = "v13.0.0-beta.3", "git" = "https://github.com/lance-format/lance.git" }
|
|
lance-namespace-impls = { "version" = "=13.0.0-beta.3", default-features = false, "tag" = "v13.0.0-beta.3", "git" = "https://github.com/lance-format/lance.git" }
|
|
lance-table = { "version" = "=13.0.0-beta.3", "tag" = "v13.0.0-beta.3", "git" = "https://github.com/lance-format/lance.git" }
|
|
lance-testing = { "version" = "=13.0.0-beta.3", "tag" = "v13.0.0-beta.3", "git" = "https://github.com/lance-format/lance.git" }
|
|
lance-datafusion = { "version" = "=13.0.0-beta.3", "tag" = "v13.0.0-beta.3", "git" = "https://github.com/lance-format/lance.git" }
|
|
lance-encoding = { "version" = "=13.0.0-beta.3", "tag" = "v13.0.0-beta.3", "git" = "https://github.com/lance-format/lance.git" }
|
|
lance-arrow = { "version" = "=13.0.0-beta.3", "tag" = "v13.0.0-beta.3", "git" = "https://github.com/lance-format/lance.git" }
|
|
lancedb = { path = "rust/lancedb", default-features = false }
|
|
ahash = "0.8"
|
|
# Note that this one does not include pyarrow
|
|
arrow = { version = "58.0.0", optional = false }
|
|
arrow-array = "58.0.0"
|
|
arrow-buffer = "58.0.0"
|
|
arrow-data = "58.0.0"
|
|
arrow-ipc = "58.0.0"
|
|
arrow-ord = "58.0.0"
|
|
arrow-schema = "58.0.0"
|
|
arrow-select = "58.0.0"
|
|
arrow-cast = "58.0.0"
|
|
arrow-flight = { version = "58.0.0", features = ["flight-sql-experimental"] }
|
|
async-trait = "0"
|
|
# Smithy JSON 0.63 requires the pre-1.7 Document representation; allow the MSRV pin.
|
|
aws-smithy-types = ">=1.3.6, <1.7"
|
|
bytes = "1"
|
|
datafusion = { version = "54.0.0", default-features = false }
|
|
datafusion-catalog = "54.0.0"
|
|
datafusion-common = { version = "54.0.0", default-features = false }
|
|
datafusion-execution = "54.0.0"
|
|
datafusion-expr = "54.0.0"
|
|
datafusion-functions = "54.0.0"
|
|
datafusion-physical-plan = "54.0.0"
|
|
datafusion-physical-expr = "54.0.0"
|
|
datafusion-sql = "54.0.0"
|
|
env_logger = "0.11"
|
|
half = { "version" = "2.7.1", default-features = false, features = [
|
|
"num-traits",
|
|
] }
|
|
futures = "0.3"
|
|
log = "0.4"
|
|
metrics = "0.24"
|
|
metrics-util = "0.19"
|
|
moka = { version = "0.12", features = ["future"] }
|
|
object_store = "0.14.1"
|
|
pin-project = "1.0.7"
|
|
rand = "0.9"
|
|
snafu = "0.8"
|
|
url = "2"
|
|
num-traits = "0.2"
|
|
oauth2 = { version = "5.0", default-features = false }
|
|
regex = "1.10"
|
|
semver = "1.0.25"
|
|
serde = "1"
|
|
serde_json = "1"
|
|
tempfile = "3.5.0"
|
|
tokio = { version = "1.23", features = ["rt-multi-thread", "sync"] }
|
|
tonic = { version = "0.14", features = ["tls-native-roots", "tls-ring"] }
|
|
uuid = { version = "1.7.0", features = ["v4", "v7"] }
|
|
chrono = { version = "0.4", default-features = false, features = ["clock"] }
|
|
|
|
[profile.ci]
|
|
debug = "line-tables-only"
|
|
inherits = "dev"
|
|
incremental = false
|
|
|
|
# This rule applies to every package except workspace members (dependencies
|
|
# such as `arrow` and `tokio`). It disables debug info and related features on
|
|
# dependencies so their binaries stay smaller, improving cache reuse.
|
|
[profile.ci.package."*"]
|
|
debug = false
|
|
debug-assertions = false
|
|
strip = "debuginfo"
|
|
incremental = false
|