diff --git a/Cargo.lock b/Cargo.lock index 4df3937..80649de 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -218,7 +218,6 @@ dependencies = [ "humantime", "humantime-serde", "itoa", - "jsonwebtoken", "maybe-owned", "rand", "regex", @@ -248,7 +247,7 @@ dependencies = [ "base64 0.20.0", "chrono", "displaydoc", - "jsonwebtoken", + "jwt-simple", "lazy_static", "regex", "serde", @@ -680,6 +679,12 @@ dependencies = [ "syn", ] +[[package]] +name = "base16ct" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349a06037c7bf932dd7e7d1f653678b2038b9ad46a74102f1fc7bd7872678cce" + [[package]] name = "base64" version = "0.13.1" @@ -701,6 +706,12 @@ dependencies = [ "simd-abstraction", ] +[[package]] +name = "base64ct" +version = "1.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b645a089122eccb6111b4f81cbc1a49f5900ac4666bb93ac027feaecf15607bf" + [[package]] name = "bindgen" version = "0.63.0" @@ -723,6 +734,12 @@ dependencies = [ "which", ] +[[package]] +name = "binstring" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e0d60973d9320722cb1206f412740e162a33b8547ea8d6be75d7cff237c7a85" + [[package]] name = "bitflags" version = "1.3.2" @@ -989,6 +1006,18 @@ dependencies = [ "os_str_bytes", ] +[[package]] +name = "coarsetime" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "454038500439e141804c655b4cd1bc6a70bcb95cd2bc9463af5661b6956f0e46" +dependencies = [ + "libc", + "once_cell", + "wasi 0.11.0+wasi-snapshot-preview1", + "wasm-bindgen", +] + [[package]] name = "codespan-reporting" version = "0.11.1" @@ -1048,6 +1077,12 @@ dependencies = [ "tracing-subscriber", ] +[[package]] +name = "const-oid" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cec318a675afcb6a1ea1d4340e2d377e56e47c266f28043ceccbf4412ddfdd3b" + [[package]] name = "const_format" version = "0.2.30" @@ -1155,6 +1190,18 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "crypto-bigint" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef2b4b23cddf68b89b8f8069890e8c270d54e2d5fe1b143820234805e4cb17ef" +dependencies = [ + "generic-array", + "rand_core", + "subtle", + "zeroize", +] + [[package]] name = "crypto-common" version = "0.1.6" @@ -1250,6 +1297,17 @@ dependencies = [ "syn", ] +[[package]] +name = "der" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1a467a65c5e759bce6e65eaf91cc29f466cdc57cb65777bd646872a8a1fd4de" +dependencies = [ + "const-oid", + "pem-rfc7468", + "zeroize", +] + [[package]] name = "derivative" version = "2.2.0" @@ -1279,6 +1337,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f" dependencies = [ "block-buffer", + "const-oid", "crypto-common", "subtle", ] @@ -1320,6 +1379,18 @@ version = "0.15.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "03d8c417d7a8cb362e0c37e5d815f5eb7c37f79ff93707329d5a194e42e54ca0" +[[package]] +name = "ecdsa" +version = "0.14.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413301934810f597c1d19ca71c8710e99a3f1ba28a0d2ebc01551a2daeea3c5c" +dependencies = [ + "der", + "elliptic-curve", + "rfc6979", + "signature", +] + [[package]] name = "ed25519-compact" version = "2.0.4" @@ -1336,6 +1407,28 @@ version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" +[[package]] +name = "elliptic-curve" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7bb888ab5300a19b8e5bceef25ac745ad065f3c9f7efc6de1b91958110891d3" +dependencies = [ + "base16ct", + "crypto-bigint", + "der", + "digest", + "ff", + "generic-array", + "group", + "hkdf", + "pem-rfc7468", + "pkcs8", + "rand_core", + "sec1", + "subtle", + "zeroize", +] + [[package]] name = "encode_unicode" version = "0.3.6" @@ -1399,6 +1492,16 @@ dependencies = [ "instant", ] +[[package]] +name = "ff" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d013fc25338cc558c5c2cfbad646908fb23591e2404481826742b651c9af7160" +dependencies = [ + "rand_core", + "subtle", +] + [[package]] name = "flate2" version = "1.0.25" @@ -1563,6 +1666,17 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" +[[package]] +name = "group" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5dfbfb3a6cfbd390d5c9564ab283a0349b9b9fcd46a706c1eb10e0db70bfbac7" +dependencies = [ + "ff", + "rand_core", + "subtle", +] + [[package]] name = "h2" version = "0.3.15" @@ -1682,6 +1796,30 @@ dependencies = [ "digest", ] +[[package]] +name = "hmac-sha1-compact" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05e2440a0078e20c3b68ca01234cea4219f23e64b0c0bdb1200c5550d54239bb" + +[[package]] +name = "hmac-sha256" +version = "1.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc736091aacb31ddaa4cd5f6988b3c21e99913ac846b41f32538c5fae5d71bfe" +dependencies = [ + "digest", +] + +[[package]] +name = "hmac-sha512" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "520c9c3f6040661669bc5c91e551b605a520c8e0a63a766a91a65adef734d151" +dependencies = [ + "digest", +] + [[package]] name = "http" version = "0.2.8" @@ -1924,17 +2062,41 @@ dependencies = [ ] [[package]] -name = "jsonwebtoken" -version = "8.2.0" +name = "jwt-simple" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09f4f04699947111ec1733e71778d763555737579e44b85844cae8e1940a1828" +checksum = "529a00f2d42d7dc349c994e65917c81bf53225831a65361f6c0454124c550f63" dependencies = [ - "base64 0.13.1", - "pem", - "ring", + "anyhow", + "binstring", + "coarsetime", + "ct-codecs", + "ed25519-compact", + "hmac-sha1-compact", + "hmac-sha256", + "hmac-sha512", + "k256", + "p256", + "p384", + "rand", + "rsa", "serde", "serde_json", - "simple_asn1", + "spki", + "thiserror", + "zeroize", +] + +[[package]] +name = "k256" +version = "0.11.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72c1e0b51e7ec0a97369623508396067a486bd0cbed95a2659a4b863d28cfc8b" +dependencies = [ + "cfg-if", + "ecdsa", + "elliptic-curve", + "sha2", ] [[package]] @@ -1942,6 +2104,9 @@ name = "lazy_static" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +dependencies = [ + "spin 0.5.2", +] [[package]] name = "lazycell" @@ -1965,6 +2130,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "libm" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "348108ab3fba42ec82ff6e9564fc4ca0247bdccdc68dd8af9764bbc79c3c8ffb" + [[package]] name = "libsqlite3-sys" version = "0.24.2" @@ -2126,6 +2297,23 @@ dependencies = [ "num-traits", ] +[[package]] +name = "num-bigint-dig" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2399c9463abc5f909349d8aa9ba080e0b88b3ce2885389b60b993f39b1a56905" +dependencies = [ + "byteorder", + "lazy_static", + "libm", + "num-integer", + "num-iter", + "num-traits", + "rand", + "smallvec", + "zeroize", +] + [[package]] name = "num-integer" version = "0.1.45" @@ -2136,6 +2324,17 @@ dependencies = [ "num-traits", ] +[[package]] +name = "num-iter" +version = "0.1.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + [[package]] name = "num-traits" version = "0.2.15" @@ -2143,6 +2342,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" dependencies = [ "autocfg", + "libm", ] [[package]] @@ -2163,9 +2363,9 @@ checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" [[package]] name = "once_cell" -version = "1.16.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860" +checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66" [[package]] name = "openssl-probe" @@ -2214,6 +2414,28 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" +[[package]] +name = "p256" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51f44edd08f51e2ade572f141051021c5af22677e42b7dd28a88155151c33594" +dependencies = [ + "ecdsa", + "elliptic-curve", + "sha2", +] + +[[package]] +name = "p384" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfc8c5bf642dde52bb9e87c0ecd8ca5a76faac2eeed98dedb7c717997e1080aa" +dependencies = [ + "ecdsa", + "elliptic-curve", + "sha2", +] + [[package]] name = "parking_lot" version = "0.11.2" @@ -2252,12 +2474,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" [[package]] -name = "pem" -version = "1.1.0" +name = "pem-rfc7468" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03c64931a1a212348ec4f3b4362585eca7159d0d09cbdf4a7f74f02173596fd4" +checksum = "24d159833a9105500e0398934e205e0773f0b27529557134ecfc51c27646adac" dependencies = [ - "base64 0.13.1", + "base64ct", ] [[package]] @@ -2298,6 +2520,28 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "pkcs1" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eff33bdbdfc54cc98a2eca766ebdec3e1b8fb7387523d5c9c9a2891da856f719" +dependencies = [ + "der", + "pkcs8", + "spki", + "zeroize", +] + +[[package]] +name = "pkcs8" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9eca2c590a5f85da82668fa685c09ce2888b9430e83299debf1f34b65fd4a4ba" +dependencies = [ + "der", + "spki", +] + [[package]] name = "pkg-config" version = "0.3.26" @@ -2554,6 +2798,17 @@ dependencies = [ "winreg", ] +[[package]] +name = "rfc6979" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7743f17af12fa0b03b803ba12cd6a8d9483a587e89c69445e3909655c0b9fabb" +dependencies = [ + "crypto-bigint", + "hmac", + "zeroize", +] + [[package]] name = "ring" version = "0.16.20" @@ -2594,6 +2849,27 @@ dependencies = [ "syn", ] +[[package]] +name = "rsa" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "094052d5470cbcef561cb848a7209968c9f12dfa6d668f4bca048ac5de51099c" +dependencies = [ + "byteorder", + "digest", + "num-bigint-dig", + "num-integer", + "num-iter", + "num-traits", + "pkcs1", + "pkcs8", + "rand_core", + "signature", + "smallvec", + "subtle", + "zeroize", +] + [[package]] name = "rust_decimal" version = "1.27.0" @@ -2884,6 +3160,20 @@ version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b" +[[package]] +name = "sec1" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3be24c1842290c45df0a7bf069e0c268a747ad05a192f2fd7dcfdbc1cba40928" +dependencies = [ + "base16ct", + "der", + "generic-array", + "pkcs8", + "subtle", + "zeroize", +] + [[package]] name = "security-framework" version = "2.7.0" @@ -3062,6 +3352,16 @@ dependencies = [ "libc", ] +[[package]] +name = "signature" +version = "1.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c" +dependencies = [ + "digest", + "rand_core", +] + [[package]] name = "simd-abstraction" version = "0.7.1" @@ -3071,18 +3371,6 @@ dependencies = [ "outref", ] -[[package]] -name = "simple_asn1" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adc4e5204eb1910f40f9cfa375f6f05b68c3abac4b6fd879c8ff5e7ae8a0a085" -dependencies = [ - "num-bigint", - "num-traits", - "thiserror", - "time 0.3.17", -] - [[package]] name = "slab" version = "0.4.7" @@ -3123,6 +3411,16 @@ dependencies = [ "lock_api", ] +[[package]] +name = "spki" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67cf02bbac7a337dc36e4f5a693db6c21e7863f45070f7064577eb4367a3212b" +dependencies = [ + "base64ct", + "der", +] + [[package]] name = "sqlformat" version = "0.2.0" diff --git a/server/Cargo.toml b/server/Cargo.toml index 4c66df8..873cc39 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -41,7 +41,6 @@ hex = "0.4.3" humantime = "2.1.0" humantime-serde = "1.1.1" itoa = "1.0.5" -jsonwebtoken = "8.2.0" maybe-owned = "0.3.4" rand = "0.8.5" regex = "1.7.0" diff --git a/server/src/access/http.rs b/server/src/access/http.rs index 391f6f9..0138def 100644 --- a/server/src/access/http.rs +++ b/server/src/access/http.rs @@ -30,7 +30,7 @@ impl AuthState { /// /// Currently it's the `sub` claim of the JWT. pub fn username(&self) -> Option<&str> { - self.token.get().map(|token| token.sub()) + self.token.get().and_then(|token| token.sub()) } /// Finds and performs authorization for a cache. @@ -101,7 +101,7 @@ pub async fn apply_auth(req: Request, next: Next) -> Response { .and_then(parse_authorization_header) .and_then(|jwt| { let state = req.extensions().get::().unwrap(); - let res_token = Token::from_jwt(&jwt, &state.config.token_hs256_secret.decoding); + let res_token = Token::from_jwt(&jwt, &state.config.token_hs256_secret); if let Err(e) = &res_token { tracing::debug!("Ignoring bad JWT token: {}", e); } diff --git a/server/src/adm/command/make_token.rs b/server/src/adm/command/make_token.rs index 3e00386..3542d99 100644 --- a/server/src/adm/command/make_token.rs +++ b/server/src/adm/command/make_token.rs @@ -115,7 +115,7 @@ pub async fn run(config: Config, opts: Opts) -> Result<()> { if sub.dump_claims { println!("{}", serde_json::to_string(token.opaque_claims())?); } else { - let encoded_token = token.encode(&config.token_hs256_secret.encoding)?; + let encoded_token = token.encode(&config.token_hs256_secret)?; println!("{}", encoded_token); } diff --git a/server/src/config.rs b/server/src/config.rs index e393ad7..aeefd78 100644 --- a/server/src/config.rs +++ b/server/src/config.rs @@ -11,7 +11,7 @@ use derivative::Derivative; use serde::{de, Deserialize}; use xdg::BaseDirectories; -use crate::access::{JwtDecodingKey, JwtEncodingKey}; +use crate::access::{decode_token_hs256_secret_base64, HS256Key}; use crate::narinfo::Compression as NixCompression; use crate::storage::{LocalStorageConfig, S3StorageConfig}; @@ -28,12 +28,6 @@ const ENV_CONFIG_BASE64: &str = "ATTIC_SERVER_CONFIG_BASE64"; /// Environment variable storing the Base64-encoded HS256 JWT secret. const ENV_TOKEN_HS256_SECRET_BASE64: &str = "ATTIC_SERVER_TOKEN_HS256_SECRET_BASE64"; -#[derive(Clone)] -pub struct JwtKeys { - pub decoding: JwtDecodingKey, - pub encoding: JwtEncodingKey, -} - /// Configuration for the Attic Server. #[derive(Clone, Derivative, Deserialize)] #[derivative(Debug)] @@ -102,10 +96,10 @@ pub struct Config { /// /// Set this to the base64 encoding of a randomly generated secret. #[serde(rename = "token-hs256-secret-base64")] - #[serde(deserialize_with = "deserialize_base64_jwt_secret")] - #[serde(default = "JwtKeys::load_from_env")] + #[serde(deserialize_with = "deserialize_token_hs256_secret_base64")] + #[serde(default = "load_token_hs256_secret_from_env")] #[derivative(Debug = "ignore")] - pub token_hs256_secret: JwtKeys, + pub token_hs256_secret: HS256Key, } /// Database connection configuration. @@ -189,18 +183,11 @@ pub struct GarbageCollectionConfig { pub default_retention_period: Duration, } -impl JwtKeys { - fn load_from_env() -> Self { - let s = env::var(ENV_TOKEN_HS256_SECRET_BASE64) - .expect("The HS256 secret must be specified in either token_hs256_secret or the ATTIC_SERVER_TOKEN_HS256_SECRET_BASE64 environment."); +fn load_token_hs256_secret_from_env() -> HS256Key { + let s = env::var(ENV_TOKEN_HS256_SECRET_BASE64) + .expect("The HS256 secret must be specified in either token_hs256_secret or the ATTIC_SERVER_TOKEN_HS256_SECRET_BASE64 environment."); - let decoding = JwtDecodingKey::from_base64_secret(&s) - .expect("Failed to load as decoding key"); - let encoding = JwtEncodingKey::from_base64_secret(&s) - .expect("Failed to load as decoding key"); - - Self { decoding, encoding } - } + decode_token_hs256_secret_base64(&s).expect("Failed to load as decoding key") } impl CompressionConfig { @@ -247,17 +234,16 @@ impl Default for GarbageCollectionConfig { } } -fn deserialize_base64_jwt_secret<'de, D>(deserializer: D) -> Result +fn deserialize_token_hs256_secret_base64<'de, D>(deserializer: D) -> Result where D: de::Deserializer<'de>, { use de::Error; let s = String::deserialize(deserializer)?; - let decoding = JwtDecodingKey::from_base64_secret(&s).map_err(Error::custom)?; - let encoding = JwtEncodingKey::from_base64_secret(&s).map_err(Error::custom)?; + let key = decode_token_hs256_secret_base64(&s).map_err(Error::custom)?; - Ok(JwtKeys { decoding, encoding }) + Ok(key) } fn default_listen_address() -> SocketAddr { diff --git a/server/src/oobe.rs b/server/src/oobe.rs index 878a20e..e606d1e 100644 --- a/server/src/oobe.rs +++ b/server/src/oobe.rs @@ -17,7 +17,7 @@ use rand::distributions::Alphanumeric; use rand::Rng; use tokio::fs::{self, OpenOptions}; -use crate::access::{JwtEncodingKey, Token}; +use crate::access::{decode_token_hs256_secret_base64, Token}; use crate::config; use attic::cache::CacheNamePattern; @@ -75,8 +75,8 @@ pub async fn run_oobe() -> Result<()> { perm.configure_cache_retention = true; perm.destroy_cache = true; - let encoding_key = JwtEncodingKey::from_base64_secret(&hs256_secret_base64)?; - token.encode(&encoding_key)? + let key = decode_token_hs256_secret_base64(&hs256_secret_base64).unwrap(); + token.encode(&key)? }; eprintln!(); diff --git a/token/Cargo.toml b/token/Cargo.toml index 5aa284e..bd8f85b 100644 --- a/token/Cargo.toml +++ b/token/Cargo.toml @@ -11,7 +11,7 @@ attic = { path = "../attic", default-features = false } base64 = "0.20.0" chrono = "0.4.23" displaydoc = "0.2.3" -jsonwebtoken = "8.2.0" +jwt-simple = "0.11.2" lazy_static = "1.4.0" regex = "1.7.0" serde = "1.0.151" diff --git a/token/src/lib.rs b/token/src/lib.rs index 117a763..f25c784 100644 --- a/token/src/lib.rs +++ b/token/src/lib.rs @@ -73,9 +73,10 @@ use std::error::Error as StdError; use chrono::{DateTime, Utc}; use displaydoc::Display; -pub use jsonwebtoken::{ - Algorithm as JwtAlgorithm, DecodingKey as JwtDecodingKey, EncodingKey as JwtEncodingKey, - Header as JwtHeader, Validation as JwtValidation, +pub use jwt_simple::{ + algorithms::{HS256Key, MACLike}, + claims::{Claims, JWTClaims}, + prelude::UnixTimeStamp, }; use serde::{Deserialize, Serialize}; use serde_with::{serde_as, BoolFromInt}; @@ -111,17 +112,11 @@ macro_rules! require_permission_function { /// A validated JSON Web Token. #[derive(Debug)] -pub struct Token(jsonwebtoken::TokenData); +pub struct Token(JWTClaims); /// Claims of a JSON Web Token. -#[derive(Debug, Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] struct TokenClaims { - /// Subject. - sub: String, - - /// Expiration timestamp. - exp: usize, - /// Attic namespace. #[serde(rename = "https://jwt.attic.rs/v1")] attic_ns: AtticAccess, @@ -208,14 +203,16 @@ pub enum Error { PermissionDenied, /// JWT error: {0} - TokenError(jsonwebtoken::errors::Error), + TokenError(jwt_simple::Error), + + /// Base64 decode error: {0} + Base64Error(base64::DecodeError), } impl Token { /// Verifies and decodes a token. - pub fn from_jwt(token: &str, key: &JwtDecodingKey) -> Result { - let validation = JwtValidation::default(); - jsonwebtoken::decode::(token, key, &validation) + pub fn from_jwt(token: &str, key: &HS256Key) -> Result { + key.verify_token(token, None) .map_err(|e| Error::TokenError(e)) .map(Token) } @@ -223,31 +220,38 @@ impl Token { /// Creates a new token with an expiration timestamp. pub fn new(sub: String, exp: &DateTime) -> Self { let claims = TokenClaims { - sub, - exp: exp.timestamp() as usize, attic_ns: Default::default(), }; - Self(jsonwebtoken::TokenData { - header: JwtHeader::new(JwtAlgorithm::HS256), - claims, + Self(JWTClaims { + issued_at: None, + expires_at: Some(UnixTimeStamp::from_secs( + exp.timestamp().try_into().unwrap(), + )), + invalid_before: None, + issuer: None, + subject: Some(sub), + audiences: None, + jwt_id: None, + nonce: None, + custom: claims, }) } /// Encodes the token. - pub fn encode(&self, key: &JwtEncodingKey) -> Result { - jsonwebtoken::encode(&self.0.header, &self.0.claims, key) + pub fn encode(&self, key: &HS256Key) -> Result { + key.authenticate(self.0.clone()) .map_err(|e| Error::TokenError(e)) } /// Returns the subject of the token. - pub fn sub(&self) -> &str { - self.0.claims.sub.as_str() + pub fn sub(&self) -> Option<&str> { + self.0.subject.as_deref() } /// Returns the claims as a serializable value. pub fn opaque_claims(&self) -> &impl Serialize { - &self.0.claims + &self.0 } /// Returns a mutable reference to a permission entry. @@ -283,11 +287,11 @@ impl Token { } fn attic_access(&self) -> &AtticAccess { - &self.0.claims.attic_ns + &self.0.custom.attic_ns } fn attic_access_mut(&mut self) -> &mut AtticAccess { - &mut self.0.claims.attic_ns + &mut self.0.custom.attic_ns } } @@ -356,6 +360,11 @@ impl Default for CachePermission { impl StdError for Error {} +pub fn decode_token_hs256_secret_base64(s: &str) -> Result { + let secret = base64::decode(s).map_err(Error::Base64Error)?; + Ok(HS256Key::from_bytes(&secret)) +} + // bruh fn is_false(b: &bool) -> bool { !b diff --git a/token/src/tests.rs b/token/src/tests.rs index fc4b9c5..9a73210 100644 --- a/token/src/tests.rs +++ b/token/src/tests.rs @@ -13,8 +13,7 @@ fn test_basic() { // "very secure secret" let base64_secret = "dmVyeSBzZWN1cmUgc2VjcmV0"; - let dec_key = - JwtDecodingKey::from_base64_secret(base64_secret).expect("Could not import decoding key"); + let dec_key = decode_token_hs256_secret_base64(base64_secret).unwrap(); /* {