use composio_sdk::ComposioClient;
use std::env;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let api_key = env::var("COMPOSIO_API_KEY")
.expect("COMPOSIO_API_KEY environment variable must be set");
let client = ComposioClient::builder().api_key(api_key).build()?;
println!("=== Authentication Link Creation Example ===\n");
let user_id = "user_demo_123";
println!("Creating session for user: {}", user_id);
let session = client
.create_session(user_id)
.toolkits(vec!["github", "gmail", "slack"])
.send()
.await?;
println!("✓ Session created: {}\n", session.session_id());
println!("--- Example 1: Basic Auth Link ---");
println!("Creating auth link for GitHub...");
match session.create_auth_link("github", None).await {
Ok(link) => {
println!("✓ Auth link created successfully!");
println!(" Link Token: {}", link.link_token);
println!(" Redirect URL: {}", link.redirect_url);
if let Some(account_id) = link.connected_account_id {
println!(" Connected Account: {}", account_id);
} else {
println!(" Connected Account: None (new connection)");
}
println!("\n 👉 User should visit: {}\n", link.redirect_url);
}
Err(e) => {
println!("✗ Failed to create auth link: {}", e);
}
}
println!("--- Example 2: Auth Link with Callback ---");
println!("Creating auth link for Gmail with callback...");
let callback_url = "https://example.com/auth/callback";
match session
.create_auth_link("gmail", Some(callback_url.to_string()))
.await
{
Ok(link) => {
println!("✓ Auth link created successfully!");
println!(" Link Token: {}", link.link_token);
println!(" Redirect URL: {}", link.redirect_url);
println!(" Callback URL: {}", callback_url);
println!(
"\n After authentication, user will be redirected to:"
);
println!(
" {}?status=<success|failed>&connected_account_id=<id>\n",
callback_url
);
}
Err(e) => {
println!("✗ Failed to create auth link: {}", e);
}
}
println!("--- Example 3: Handling Existing Connection ---");
println!("Attempting to create auth link for already connected toolkit...");
match session.create_auth_link("github", None).await {
Ok(link) => {
if link.connected_account_id.is_some() {
println!("✓ User already has a connected account!");
println!(" Connected Account: {:?}", link.connected_account_id);
println!(" Link can be used to re-authenticate if needed.");
} else {
println!("✓ New auth link created");
}
}
Err(e) => {
println!("✗ Error: {}", e);
println!(" This might happen if:");
println!(" - Toolkit is invalid");
println!(" - Connection already exists and cannot be recreated");
println!(" - Network or API error occurred");
}
}
println!("\n--- Example 4: Creating Links for Multiple Toolkits ---");
let toolkits = vec!["slack", "notion", "linear"];
for toolkit in toolkits {
println!("Creating auth link for {}...", toolkit);
match session.create_auth_link(toolkit, None).await {
Ok(link) => {
println!(" ✓ {}: {}", toolkit, link.redirect_url);
}
Err(e) => {
println!(" ✗ {}: {}", toolkit, e);
}
}
}
println!("\n=== Authentication Flow ===");
println!("1. Generate auth link using create_auth_link()");
println!("2. Send redirect_url to user (via chat, email, or UI)");
println!("3. User visits URL and completes OAuth flow");
println!("4. User is redirected to callback_url (if provided)");
println!("5. Check connection status using session.list_toolkits()");
println!("\n=== Best Practices ===");
println!("• Use callback URLs in production for better UX");
println!("• Store link_token for tracking auth sessions");
println!("• Handle errors gracefully (invalid toolkit, existing connection)");
println!("• Check connection status before creating new links");
println!("• Use in-chat auth (manage_connections=true) for conversational flows");
println!("• Use manual auth for onboarding or settings pages");
Ok(())
}