#![allow(clippy::uninlined_format_args)]
use openai_ergonomic::{Client, Config, Result};
use std::env;
#[tokio::main]
async fn main() -> Result<()> {
println!("=== Authentication Patterns ===\n");
println!("1. Environment Variable Authentication:");
env_var_auth().await?;
println!("\n2. Direct API Key:");
direct_api_key().await?;
println!("\n3. Organization Configuration:");
organization_config()?;
println!("\n4. Project Configuration:");
project_config()?;
println!("\n5. Custom Headers:");
custom_headers()?;
println!("\n6. Proxy Configuration:");
proxy_config()?;
println!("\n7. Multiple Client Configurations:");
multiple_clients()?;
println!("\n8. Configuration Validation:");
config_validation()?;
println!("\n9. Secure Key Management:");
secure_key_management();
Ok(())
}
async fn env_var_auth() -> Result<()> {
if env::var("OPENAI_API_KEY").is_err() {
println!("Warning: OPENAI_API_KEY not set");
println!("Set it with: export OPENAI_API_KEY=your-key-here");
return Ok(());
}
let client = Client::from_env()?.build();
println!("Client created from environment variables");
match client.send_chat(client.chat_simple("Hello")).await {
Ok(response) => {
if let Some(content) = response.content() {
println!("Response: {}", content);
} else {
println!("Response: (no content)");
}
}
Err(e) => println!("Error: {}", e),
}
Ok(())
}
async fn direct_api_key() -> Result<()> {
let api_key = "sk-your-api-key-here"; let config = Config::builder().api_key(api_key).build();
let client = Client::builder(config)?.build();
println!("Client created with direct API key");
match client.send_chat(client.chat_simple("Hello")).await {
Ok(response) => {
if let Some(content) = response.content() {
println!("Response: {}", content);
} else {
println!("Response: (no content)");
}
}
Err(e) => println!("Expected error with demo key: {}", e),
}
Ok(())
}
fn organization_config() -> Result<()> {
let config = Config::builder()
.api_key("your-api-key")
.organization("org-123456789")
.build();
let _client = Client::builder(config)?.build();
println!("Client configured with organization ID");
Ok(())
}
fn project_config() -> Result<()> {
let config = Config::builder()
.api_key("your-api-key")
.project("proj-abc123")
.build();
let _client = Client::builder(config)?.build();
println!("Client configured with project ID");
Ok(())
}
fn custom_headers() -> Result<()> {
let config = Config::builder().api_key("your-api-key").build();
let _client = Client::builder(config)?.build();
println!("Client configured (custom headers not yet supported)");
println!("Custom headers feature planned for future implementation");
Ok(())
}
fn proxy_config() -> Result<()> {
let config = Config::builder().api_key("your-api-key").build();
let _client = Client::builder(config)?.build();
println!("Client configured (proxy support not yet available)");
println!("Proxy configuration feature planned for future implementation");
Ok(())
}
fn multiple_clients() -> Result<()> {
use reqwest_middleware::ClientBuilder;
use std::time::Duration;
let prod_http_client = ClientBuilder::new(
reqwest::Client::builder()
.timeout(Duration::from_secs(60))
.build()
.expect("Failed to build reqwest client"),
)
.build();
let prod_config = Config::builder()
.api_key("prod-api-key")
.organization("org-prod")
.http_client(prod_http_client)
.max_retries(5)
.build();
let prod_client = Client::builder(prod_config)?.build();
let dev_http_client = ClientBuilder::new(
reqwest::Client::builder()
.timeout(Duration::from_secs(10))
.build()
.expect("Failed to build reqwest client"),
)
.build();
let dev_config = Config::builder()
.api_key("dev-api-key")
.organization("org-dev")
.api_base("https://api.openai-dev.com") .http_client(dev_http_client)
.build();
let dev_client = Client::builder(dev_config)?.build();
let test_config = Config::builder()
.api_key("test-api-key")
.api_base("http://localhost:8080") .build();
let _test_client = Client::builder(test_config)?.build();
println!("Created multiple clients:");
println!("- Production client with retries");
println!("- Development client with custom endpoint");
println!("- Test client with mock server");
let _client = if cfg!(debug_assertions) {
&dev_client
} else {
&prod_client
};
println!(
"Using {} client",
if cfg!(debug_assertions) {
"dev"
} else {
"prod"
}
);
Ok(())
}
fn config_validation() -> Result<()> {
fn validate_api_key(key: &str) -> bool {
key.starts_with("sk-") && key.len() > 20
}
fn validate_org_id(org: &str) -> bool {
org.starts_with("org-") && org.len() > 4
}
let api_key = "sk-test-key-123456789";
let org_id = "org-12345";
if !validate_api_key(api_key) {
println!("Warning: API key format appears invalid");
}
if !validate_org_id(org_id) {
println!("Warning: Organization ID format appears invalid");
}
if validate_api_key(api_key) {
let config = Config::builder()
.api_key(api_key)
.organization(org_id)
.build();
let _client = Client::builder(config)?.build();
println!("Configuration validated and client created");
}
Ok(())
}
fn secure_key_management() {
println!("Secure Key Management Best Practices:");
println!();
println!("1. Never hardcode API keys in source code");
println!("2. Use environment variables for local development");
if let Ok(key) = env::var("OPENAI_API_KEY") {
println!(" API key loaded from environment (length: {})", key.len());
}
println!("3. Use proper secrets management in production:");
println!(" - AWS Secrets Manager");
println!(" - Azure Key Vault");
println!(" - HashiCorp Vault");
println!(" - Kubernetes Secrets");
println!("4. Rotate API keys regularly");
println!("5. Use different API keys for each environment:");
let keys_by_env = vec![
("development", "OPENAI_API_KEY_DEV"),
("staging", "OPENAI_API_KEY_STAGING"),
("production", "OPENAI_API_KEY_PROD"),
];
for (env_name, env_var) in keys_by_env {
if env::var(env_var).is_ok() {
println!(" {} key configured", env_name);
} else {
println!(" {} key not found", env_name);
}
}
println!("6. Monitor API key usage:");
println!(" - Set up usage alerts");
println!(" - Track per-project costs");
println!(" - Audit access logs");
#[cfg(unix)]
{
use std::fs;
use std::os::unix::fs::PermissionsExt;
let secret_file = "/tmp/openai_secret";
if let Ok(metadata) = fs::metadata(secret_file) {
let permissions = metadata.permissions();
if permissions.mode() & 0o777 == 0o600 {
println!("7. Secret file has correct permissions (600)");
} else {
println!("7. Warning: Secret file permissions too open!");
}
}
}
}