firebase_verifyid/
lib.rs

1mod jwk_cache;
2pub mod middleware;
3mod settings;
4mod token_verifier;
5
6pub use jwk_cache::JwkCache;
7pub use settings::Settings;
8pub use token_verifier::TokenVerifier;
9
10pub use jwt_simple::claims;
11
12pub const KTY: &str = "RSA";
13pub const ALG: &str = "RS256";
14pub const TOKEN_SIG_TYPE: &str = "JWT";
15
16#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
17pub struct FirebaseClaims {
18    pub email_verified: bool,
19    pub email: Option<String>,
20    pub phone_number: Option<String>,
21    pub user_id: String,
22    pub auth_time: u64,
23    pub firebase: serde_json::Value,
24}
25
26#[derive(Debug, thiserror::Error)]
27pub enum Error {
28    #[error("jwt token or pubkey error {0}")]
29    JwtError(#[from] jwt_simple::Error),
30    #[error("unauthorized bearer token {0}")]
31    UnknownBearer(String),
32    #[error("failed to fetch jwks {0}")]
33    JwkRefresh(#[from] reqwest::Error),
34    #[error("no compatible keys in set {0}")]
35    JwkSetEmpty(String),
36    #[error("token kid does not match known key {0}")]
37    UnknownJwk(String),
38    #[error("error reading jwk pem from file {0}")]
39    PemReadFile(#[from] std::io::Error),
40}
41
42pub(crate) const GOOGLE_PUBKEY_URI: &str =
43    "https://www.googleapis.com/service_accounts/v1/jwk/securetoken@system.gserviceaccount.com";
44
45#[cfg(test)]
46mod test {
47    use jwt_simple::reexports::ct_codecs::{Base64UrlSafeNoPadding, Decoder};
48
49    use super::*;
50
51    #[test]
52    fn decode_claims() {
53        let token = "eyJhbGciOiJSUzI1NiIsImtpZCI6IjEyMzQ1Njc4OTAifQ.eyJpc3MiOiJodHRwczovL2lkZW50aXR5dG9vbGtpdC5nb29nbGUuY29tL2ZpcmViYXNlLXByb2plY3QtaWQiLCJhdWQiOiJmaXJlYmFzZS1wcm9qZWN0LWlkIiwiaWF0IjoxNzEwMTMyMDAwLCJleHAiOjE3MTAxMzU2MDAsInVzZXJfaWQiOiJ1c2VyX2lkX2V4YW1wbGUiLCJzdWIiOiJ1c2VyX2lkX2V4YW1wbGUiLCJlbWFpbCI6InRlc3RAZXhhbXBsZS5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiaXNzX2F1dGgiOiJjdXN0b21Ub2tlbkF1dGgiLCJhdXRoX3RpbWUiOjE3MTAxMzIwMDAsImZpcmViYXNlIjp7InNpZ25faW5wcm92ZWQiOnRydWUsImxvZ2luX3Byb3ZpZGVyIjoiY29udGFjdHNwYWNlIiwidXNlcl9zdGF0dXMiOiJhY3RpdmUifX0.SGVsbG9UaGVyZVNob3VsZGJFUmVhbFNpZ25hdHVyZUJ1dEl0cydNb2NrZWQ";
54        let claims_component = token.split(".").collect::<Vec<_>>()[1];
55        let decoded_token: FirebaseClaims = serde_json::from_slice(
56            &Base64UrlSafeNoPadding::decode_to_vec(claims_component, None).expect("valid token"),
57        )
58        .expect("valid decode struct");
59        println!("{decoded_token:?}");
60    }
61}