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}