use anyhow::Result;
use kunobi_auth::client::{AuthClient, ServiceConfig};
use super::config::{AuthMode, CliConfig};
const DEVICE_GRANT_SCOPE: &str = "openid profile email offline_access";
pub async fn login(
context_override: Option<&str>,
endpoint_override: Option<&str>,
device: bool,
) -> Result<()> {
let config = CliConfig::load()?;
let config = config.resolve(context_override, endpoint_override)?;
let endpoint = config.endpoint.as_str();
if config.auth != AuthMode::Oidc {
println!(
"Context uses auth={}. Browser/device login is only needed for auth=oidc.",
config.auth
);
return Ok(());
}
println!("Discovering auth configuration from {endpoint}...");
let service_config = ServiceConfig::discover(endpoint).await?;
let client = AuthClient::new(service_config)?;
if device {
println!("Starting device authorization flow...");
client
.device_login(DEVICE_GRANT_SCOPE, |prompt| {
eprintln!();
if let Some(complete) = &prompt.verification_uri_complete {
eprintln!(" Open this URL on any browser:");
eprintln!(" {complete}");
eprintln!();
eprintln!(
" Or visit {} and enter code: {}",
prompt.verification_uri, prompt.user_code
);
} else {
eprintln!(" Open this URL on any browser:");
eprintln!(" {}", prompt.verification_uri);
eprintln!();
eprintln!(" Then enter code: {}", prompt.user_code);
}
eprintln!();
eprintln!(
" Code expires in {} seconds. Polling…",
prompt.expires_in.as_secs()
);
eprintln!();
})
.await?;
} else {
println!("Opening browser for authentication...");
client.login().await?;
}
println!("Authenticated successfully!");
Ok(())
}
pub async fn logout(context_override: Option<&str>, endpoint_override: Option<&str>) -> Result<()> {
let config = CliConfig::load()?;
let config = config.resolve(context_override, endpoint_override)?;
let endpoint = config.endpoint.as_str();
if config.auth != AuthMode::Oidc {
println!(
"Context uses auth={}. Browser logout is only needed for auth=oidc.",
config.auth
);
return Ok(());
}
let service_config = ServiceConfig::discover(endpoint).await?;
let client = AuthClient::new(service_config)?;
client.logout_async().await?;
println!("Logged out (token revoked at IdP).");
Ok(())
}