Skip to main content

ez_token/services/authentication/
authenticator.rs

1use crate::cli::output::{print_success, print_warning};
2use arboard::Clipboard;
3use miette::Result;
4
5/// Defines the interface for an OAuth2 authentication flow.
6///
7/// Implementors are responsible for performing the full token exchange
8/// and returning a raw access token string on success.
9///
10/// # Implementors
11///
12/// - [`super::pkce::AuthorizationCodeFlow`] — Interactive browser login via PKCE.
13/// - [`super::client_credentials::ClientCredentialsFlow`] — Machine-to-machine via client secret.
14#[allow(async_fn_in_trait)]
15pub trait Authenticator {
16    /// Performs the authentication flow and returns a raw access token.
17    ///
18    /// # Errors
19    ///
20    /// Returns an error if the token exchange fails for any reason,
21    /// such as invalid credentials, network issues, or a rejected authorization.
22    async fn get_token(&self) -> Result<String>;
23}
24
25/// Executes an authentication flow and handles the resulting token.
26///
27/// Calls [`Authenticator::get_token`] on the provided flow, then attempts
28/// to copy the token to the system clipboard. If clipboard access is
29/// unavailable or fails, the token is printed to standard output as a fallback.
30///
31/// # Arguments
32///
33/// * `flow` - Any type implementing the [`Authenticator`] trait.
34///
35/// # Errors
36///
37/// Returns an error if the underlying authentication flow fails.
38/// Clipboard errors are handled gracefully and do not cause the function to fail.
39pub async fn execute_flow<A: Authenticator>(flow: &A) -> Result<()> {
40    let token = flow.get_token().await?;
41
42    match Clipboard::new() {
43        Ok(mut cb) => {
44            if let Err(e) = cb.set_text(token.clone()) {
45                print_warning(&format!("Failed to copy to clipboard: {}", e));
46                println!("Token: {}", token);
47            } else {
48                print_success("Token copied to clipboard!");
49            }
50        }
51        Err(_) => {
52            print_warning("Could not access clipboard.");
53            println!("Token: {}", token);
54        }
55    }
56
57    Ok(())
58}