use oauth_device_flows::{DeviceFlow, DeviceFlowConfig, Provider};
use std::time::Duration;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let config = DeviceFlowConfig::new()
.client_id("your-client-id-here") .scopes(vec![
"https://graph.microsoft.com/User.Read",
"https://graph.microsoft.com/Files.Read",
"offline_access", ])
.poll_interval(Duration::from_secs(5))
.max_attempts(60);
let mut device_flow = DeviceFlow::new(Provider::Microsoft, config)?;
println!("Starting Microsoft OAuth Device Flow...");
let auth_response = device_flow.initialize().await?;
println!("\n🔐 Authentication Required");
println!("────────────────────────");
println!("1. Open this URL in your browser:");
println!(" {}", auth_response.verification_uri());
println!();
println!("2. Enter this code:");
println!(" {}", auth_response.user_code());
println!();
#[cfg(feature = "qr-codes")]
if let Ok(qr_code) = auth_response.generate_qr_code() {
println!("Or scan this QR code:");
println!("{}", qr_code);
println!();
}
println!("⏳ Waiting for you to complete authentication...");
println!(
" (This will timeout in {} seconds)",
auth_response.expires_in().as_secs()
);
println!();
match device_flow.poll_for_token().await {
Ok(token_response) => {
println!("✅ Authentication successful!");
println!(" Token type: {}", token_response.token_type);
println!(" Expires in: {:?}", token_response.expires_in);
println!(" Scopes: {:?}", token_response.scope);
println!(
" Has refresh token: {}",
token_response.refresh_token.is_some()
);
let token_manager = oauth_device_flows::TokenManager::new(
token_response,
Provider::Microsoft,
DeviceFlowConfig::new().client_id("your-client-id-here"),
)?;
println!("\n🚀 Making API call to Microsoft Graph...");
let client = reqwest::Client::new();
let response = client
.get("https://graph.microsoft.com/v1.0/me")
.header("Authorization", token_manager.authorization_header())
.send()
.await?;
if response.status().is_success() {
let user_info: serde_json::Value = response.json().await?;
println!(
" User: {}",
user_info["displayName"].as_str().unwrap_or("Unknown")
);
println!(
" Email: {}",
user_info["mail"].as_str().unwrap_or("Unknown")
);
} else {
println!(" API call failed: {}", response.status());
}
}
Err(e) => {
eprintln!("❌ Authentication failed: {}", e);
match e {
oauth_device_flows::DeviceFlowError::AuthorizationDenied => {
eprintln!(" The user denied the authorization request.");
}
oauth_device_flows::DeviceFlowError::ExpiredToken => {
eprintln!(" The device code expired. Please try again.");
}
oauth_device_flows::DeviceFlowError::MaxAttemptsExceeded(max) => {
eprintln!(" Timed out after {} attempts. Please try again.", max);
}
_ => {
eprintln!(" Error details: {}", e);
}
}
}
}
Ok(())
}