ez-token 0.1.0

CLI tool for generating OAuth2 access tokens via PKCE and Client Credentials for Microsoft Entra ID and Auth0
Documentation
use crate::cli::output::{print_success, print_warning};
use arboard::Clipboard;
use miette::Result;

/// Defines the interface for an OAuth2 authentication flow.
///
/// Implementors are responsible for performing the full token exchange
/// and returning a raw access token string on success.
///
/// # Implementors
///
/// - [`super::pkce::AuthorizationCodeFlow`] — Interactive browser login via PKCE.
/// - [`super::client_credentials::ClientCredentialsFlow`] — Machine-to-machine via client secret.
#[allow(async_fn_in_trait)]
pub trait Authenticator {
    /// Performs the authentication flow and returns a raw access token.
    ///
    /// # Errors
    ///
    /// Returns an error if the token exchange fails for any reason,
    /// such as invalid credentials, network issues, or a rejected authorization.
    async fn get_token(&self) -> Result<String>;
}

/// Executes an authentication flow and handles the resulting token.
///
/// Calls [`Authenticator::get_token`] on the provided flow, then attempts
/// to copy the token to the system clipboard. If clipboard access is
/// unavailable or fails, the token is printed to standard output as a fallback.
///
/// # Arguments
///
/// * `flow` - Any type implementing the [`Authenticator`] trait.
///
/// # Errors
///
/// Returns an error if the underlying authentication flow fails.
/// Clipboard errors are handled gracefully and do not cause the function to fail.
pub async fn execute_flow<A: Authenticator>(flow: &A) -> Result<()> {
    let token = flow.get_token().await?;

    match Clipboard::new() {
        Ok(mut cb) => {
            if let Err(e) = cb.set_text(token.clone()) {
                print_warning(&format!("Failed to copy to clipboard: {}", e));
                println!("Token: {}", token);
            } else {
                print_success("Token copied to clipboard!");
            }
        }
        Err(_) => {
            print_warning("Could not access clipboard.");
            println!("Token: {}", token);
        }
    }

    Ok(())
}