firebase-auth icon indicating copy to clipboard operation
firebase-auth copied to clipboard

When cloned `FirebaseAuth` is dropped, public keys will no longer be updated.

Open techno-tanoC opened this issue 7 months ago • 0 comments

Hi, thank you for the wonderful crate!

I have a question regarding the implementation of FirebaseAuth. Since FirebaseAuth implements Clone, it can be cloned. Additionally, it also implements Drop, which stops the updates of public keys when the instance is dropped. Therefore, it appears that dropping a cloned FirebaseAuth also stops keys updates.

This behavior can potentially lead to unintentional stopping of key updates due to cloning. I encountered this issue while using the Extension in axum. (I am aware of the axum feature, but in my case, a Firebase auth token is passed via a different header. I was able to resolve this issue by wrapping FirebaseAuth with Arc.)

Could you please clarify whether it is expected for FirebaseAuth to implement Clone? Is there a way to ensure that dropping a naive cloned FirebaseAuth does not stop keys updates?

Repro

Patched Drop for FirebaseAuth

impl Drop for FirebaseAuth {
    fn drop(&mut self) {
        debug!("Abort the handler");
        // Stop the update thread when the updater is destructed
        let handler = self.handler.lock().unwrap();
        handler.abort();
    }
}
use std::time::Duration;

use anyhow::Result;
use firebase_auth::{FirebaseAuth, FirebaseUser};
use tracing_subscriber::{fmt, layer::SubscriberExt as _, util::SubscriberInitExt as _, EnvFilter};

#[tokio::main]
async fn main() -> Result<()> {
    tracing_subscriber::registry()
        .with(fmt::layer())
        .with(EnvFilter::from_default_env())
        .init();

    let auth: FirebaseAuth = FirebaseAuth::new("sample_project_id").await;

    tokio::time::sleep(Duration::from_secs(3)).await;

    // Clone and drop
    let cloned = auth.clone();
    drop(cloned);

    // A long time have passed...
    tokio::time::sleep(Duration::from_secs(10_000_000)).await;

    // Fail?
    let _ = auth.verify::<FirebaseUser>("token");

    Ok(())
}
$ RUST_LOG=info,firebase_auth=debug cargo run
   Compiling fba v0.1.0 (/workspace)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 2.38s
     Running `target/debug/fba`
2024-07-11T06:08:00.231661Z DEBUG firebase_auth::firebase_auth: Updated JWK keys. Next refresh will be in 22344s
2024-07-11T06:08:03.141457Z DEBUG firebase_auth::firebase_auth: Abort the handler

Version

rust 1.79.0 firebase-auth 0.4.3

techno-tanoC avatar Jul 11 '24 06:07 techno-tanoC