Skip to main content

hyperdb_api_salesforce/
lib.rs

1// Copyright (c) 2026, Salesforce, Inc. All rights reserved.
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3
4//! Salesforce Data Cloud authentication (OAuth Access Token + DC JWT).
5//!
6//! This crate implements the token flow for connecting to the Salesforce
7//! Data Cloud Hyper query engine:
8//!
9//! 1. Obtain an **OAuth Access Token** from Salesforce
10//! 2. Exchange it for a **DC JWT** (Data Cloud JSON Web Token)
11//! 3. Send the DC JWT as the `Authorization` header with every gRPC call
12//!
13//! # Authentication Modes
14//!
15//! Three modes are supported for Step 1 (obtaining an OAuth Access Token):
16//!
17//! - **Password**: Username + password + client secret (OAuth password grant)
18//! - **`PrivateKey`**: JWT Bearer Token Flow using RSA private key (recommended
19//!   for server-to-server; no OAuth Refresh Token involved)
20//! - **`RefreshToken`**: Uses a long-lived **OAuth Refresh Token** + client secret
21//!
22//! # Token Caching
23//!
24//! Both the OAuth Access Token and the DC JWT are cached independently.
25//! The OAuth Access Token is only refreshed when genuinely expired, to avoid
26//! unnecessary OAuth Refresh Token rotation that would invalidate tokens
27//! held by other connections.  The DC JWT is refreshed proactively based
28//! on both its expiry time and its age (maxAge check).
29//!
30//! # Example: JWT Bearer Token Flow
31//!
32//! ```no_run
33//! use hyperdb_api_salesforce::{SalesforceAuthConfig, AuthMode, DataCloudTokenProvider};
34//!
35//! # async fn example() -> Result<(), Box<dyn std::error::Error>> {
36//! let private_key_pem = std::fs::read_to_string("server.key")?;
37//!
38//! let config = SalesforceAuthConfig::new(
39//!     "https://login.salesforce.com",
40//!     "your-connected-app-client-id",
41//! )?
42//! .auth_mode(AuthMode::private_key("user@example.com", &private_key_pem)?);
43//!
44//! let mut provider = DataCloudTokenProvider::new(config)?;
45//!
46//! // Get a valid DC JWT (automatically handles OAuth Access Token + exchange)
47//! let dc_jwt = provider.get_token().await?;
48//!
49//! println!("Authorization: {}", dc_jwt.bearer_token());
50//! println!("Tenant URL: {}", dc_jwt.tenant_url_str());
51//! # Ok(())
52//! # }
53//! ```
54//!
55//! # Two-Stage Token Flow
56//!
57//! 1. **OAuth Access Token**: Authenticate with Salesforce
58//!    - Endpoint: `{login_url}/services/oauth2/token`
59//!    - Returns: `access_token`, `instance_url`
60//!
61//! 2. **DC JWT**: Exchange OAuth Access Token for a Data Cloud JWT
62//!    - Endpoint: `{instance_url}/services/a360/token`
63//!    - Grant type: `urn:salesforce:grant-type:external:cdp`
64//!    - Returns: `access_token` (the DC JWT), `instance_url`, `expires_in`
65//!
66//! # Security
67//!
68//! - Private keys are stored using `zeroize` for secure memory handling
69//! - Tokens are cached and automatically refreshed before expiration
70//! - All HTTP communication uses TLS
71
72#![warn(missing_docs, rust_2018_idioms, clippy::all)]
73
74mod config;
75mod error;
76mod jwt;
77mod provider;
78mod token;
79
80pub use config::{AuthMode, SalesforceAuthConfig};
81pub use error::{SalesforceAuthError, SalesforceAuthResult};
82pub use provider::{DataCloudTokenProvider, SharedTokenProvider};
83pub use token::{DataCloudToken, OAuthToken};