Migrate to jwt-simple

This commit is contained in:
Zhaofeng Li 2023-01-08 00:57:22 -07:00
parent 1c2173caac
commit 6c4d04da74
9 changed files with 380 additions and 89 deletions

352
Cargo.lock generated
View file

@ -218,7 +218,6 @@ dependencies = [
"humantime", "humantime",
"humantime-serde", "humantime-serde",
"itoa", "itoa",
"jsonwebtoken",
"maybe-owned", "maybe-owned",
"rand", "rand",
"regex", "regex",
@ -248,7 +247,7 @@ dependencies = [
"base64 0.20.0", "base64 0.20.0",
"chrono", "chrono",
"displaydoc", "displaydoc",
"jsonwebtoken", "jwt-simple",
"lazy_static", "lazy_static",
"regex", "regex",
"serde", "serde",
@ -680,6 +679,12 @@ dependencies = [
"syn", "syn",
] ]
[[package]]
name = "base16ct"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "349a06037c7bf932dd7e7d1f653678b2038b9ad46a74102f1fc7bd7872678cce"
[[package]] [[package]]
name = "base64" name = "base64"
version = "0.13.1" version = "0.13.1"
@ -701,6 +706,12 @@ dependencies = [
"simd-abstraction", "simd-abstraction",
] ]
[[package]]
name = "base64ct"
version = "1.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b645a089122eccb6111b4f81cbc1a49f5900ac4666bb93ac027feaecf15607bf"
[[package]] [[package]]
name = "bindgen" name = "bindgen"
version = "0.63.0" version = "0.63.0"
@ -723,6 +734,12 @@ dependencies = [
"which", "which",
] ]
[[package]]
name = "binstring"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7e0d60973d9320722cb1206f412740e162a33b8547ea8d6be75d7cff237c7a85"
[[package]] [[package]]
name = "bitflags" name = "bitflags"
version = "1.3.2" version = "1.3.2"
@ -989,6 +1006,18 @@ dependencies = [
"os_str_bytes", "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]] [[package]]
name = "codespan-reporting" name = "codespan-reporting"
version = "0.11.1" version = "0.11.1"
@ -1048,6 +1077,12 @@ dependencies = [
"tracing-subscriber", "tracing-subscriber",
] ]
[[package]]
name = "const-oid"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cec318a675afcb6a1ea1d4340e2d377e56e47c266f28043ceccbf4412ddfdd3b"
[[package]] [[package]]
name = "const_format" name = "const_format"
version = "0.2.30" version = "0.2.30"
@ -1155,6 +1190,18 @@ dependencies = [
"cfg-if", "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]] [[package]]
name = "crypto-common" name = "crypto-common"
version = "0.1.6" version = "0.1.6"
@ -1250,6 +1297,17 @@ dependencies = [
"syn", "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]] [[package]]
name = "derivative" name = "derivative"
version = "2.2.0" version = "2.2.0"
@ -1279,6 +1337,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f" checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f"
dependencies = [ dependencies = [
"block-buffer", "block-buffer",
"const-oid",
"crypto-common", "crypto-common",
"subtle", "subtle",
] ]
@ -1320,6 +1379,18 @@ version = "0.15.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "03d8c417d7a8cb362e0c37e5d815f5eb7c37f79ff93707329d5a194e42e54ca0" 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]] [[package]]
name = "ed25519-compact" name = "ed25519-compact"
version = "2.0.4" version = "2.0.4"
@ -1336,6 +1407,28 @@ version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" 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]] [[package]]
name = "encode_unicode" name = "encode_unicode"
version = "0.3.6" version = "0.3.6"
@ -1399,6 +1492,16 @@ dependencies = [
"instant", "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]] [[package]]
name = "flate2" name = "flate2"
version = "1.0.25" version = "1.0.25"
@ -1563,6 +1666,17 @@ version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" 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]] [[package]]
name = "h2" name = "h2"
version = "0.3.15" version = "0.3.15"
@ -1682,6 +1796,30 @@ dependencies = [
"digest", "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]] [[package]]
name = "http" name = "http"
version = "0.2.8" version = "0.2.8"
@ -1924,17 +2062,41 @@ dependencies = [
] ]
[[package]] [[package]]
name = "jsonwebtoken" name = "jwt-simple"
version = "8.2.0" version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09f4f04699947111ec1733e71778d763555737579e44b85844cae8e1940a1828" checksum = "529a00f2d42d7dc349c994e65917c81bf53225831a65361f6c0454124c550f63"
dependencies = [ dependencies = [
"base64 0.13.1", "anyhow",
"pem", "binstring",
"ring", "coarsetime",
"ct-codecs",
"ed25519-compact",
"hmac-sha1-compact",
"hmac-sha256",
"hmac-sha512",
"k256",
"p256",
"p384",
"rand",
"rsa",
"serde", "serde",
"serde_json", "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]] [[package]]
@ -1942,6 +2104,9 @@ name = "lazy_static"
version = "1.4.0" version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
dependencies = [
"spin 0.5.2",
]
[[package]] [[package]]
name = "lazycell" name = "lazycell"
@ -1965,6 +2130,12 @@ dependencies = [
"winapi", "winapi",
] ]
[[package]]
name = "libm"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "348108ab3fba42ec82ff6e9564fc4ca0247bdccdc68dd8af9764bbc79c3c8ffb"
[[package]] [[package]]
name = "libsqlite3-sys" name = "libsqlite3-sys"
version = "0.24.2" version = "0.24.2"
@ -2126,6 +2297,23 @@ dependencies = [
"num-traits", "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]] [[package]]
name = "num-integer" name = "num-integer"
version = "0.1.45" version = "0.1.45"
@ -2136,6 +2324,17 @@ dependencies = [
"num-traits", "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]] [[package]]
name = "num-traits" name = "num-traits"
version = "0.2.15" version = "0.2.15"
@ -2143,6 +2342,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd"
dependencies = [ dependencies = [
"autocfg", "autocfg",
"libm",
] ]
[[package]] [[package]]
@ -2163,9 +2363,9 @@ checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3"
[[package]] [[package]]
name = "once_cell" name = "once_cell"
version = "1.16.0" version = "1.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860" checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66"
[[package]] [[package]]
name = "openssl-probe" name = "openssl-probe"
@ -2214,6 +2414,28 @@ version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" 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]] [[package]]
name = "parking_lot" name = "parking_lot"
version = "0.11.2" version = "0.11.2"
@ -2252,12 +2474,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099"
[[package]] [[package]]
name = "pem" name = "pem-rfc7468"
version = "1.1.0" version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "03c64931a1a212348ec4f3b4362585eca7159d0d09cbdf4a7f74f02173596fd4" checksum = "24d159833a9105500e0398934e205e0773f0b27529557134ecfc51c27646adac"
dependencies = [ dependencies = [
"base64 0.13.1", "base64ct",
] ]
[[package]] [[package]]
@ -2298,6 +2520,28 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" 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]] [[package]]
name = "pkg-config" name = "pkg-config"
version = "0.3.26" version = "0.3.26"
@ -2554,6 +2798,17 @@ dependencies = [
"winreg", "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]] [[package]]
name = "ring" name = "ring"
version = "0.16.20" version = "0.16.20"
@ -2594,6 +2849,27 @@ dependencies = [
"syn", "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]] [[package]]
name = "rust_decimal" name = "rust_decimal"
version = "1.27.0" version = "1.27.0"
@ -2884,6 +3160,20 @@ version = "4.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b" 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]] [[package]]
name = "security-framework" name = "security-framework"
version = "2.7.0" version = "2.7.0"
@ -3062,6 +3352,16 @@ dependencies = [
"libc", "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]] [[package]]
name = "simd-abstraction" name = "simd-abstraction"
version = "0.7.1" version = "0.7.1"
@ -3071,18 +3371,6 @@ dependencies = [
"outref", "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]] [[package]]
name = "slab" name = "slab"
version = "0.4.7" version = "0.4.7"
@ -3123,6 +3411,16 @@ dependencies = [
"lock_api", "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]] [[package]]
name = "sqlformat" name = "sqlformat"
version = "0.2.0" version = "0.2.0"

View file

@ -41,7 +41,6 @@ hex = "0.4.3"
humantime = "2.1.0" humantime = "2.1.0"
humantime-serde = "1.1.1" humantime-serde = "1.1.1"
itoa = "1.0.5" itoa = "1.0.5"
jsonwebtoken = "8.2.0"
maybe-owned = "0.3.4" maybe-owned = "0.3.4"
rand = "0.8.5" rand = "0.8.5"
regex = "1.7.0" regex = "1.7.0"

View file

@ -30,7 +30,7 @@ impl AuthState {
/// ///
/// Currently it's the `sub` claim of the JWT. /// Currently it's the `sub` claim of the JWT.
pub fn username(&self) -> Option<&str> { 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. /// Finds and performs authorization for a cache.
@ -101,7 +101,7 @@ pub async fn apply_auth<B>(req: Request<B>, next: Next<B>) -> Response {
.and_then(parse_authorization_header) .and_then(parse_authorization_header)
.and_then(|jwt| { .and_then(|jwt| {
let state = req.extensions().get::<State>().unwrap(); let state = req.extensions().get::<State>().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 { if let Err(e) = &res_token {
tracing::debug!("Ignoring bad JWT token: {}", e); tracing::debug!("Ignoring bad JWT token: {}", e);
} }

View file

@ -115,7 +115,7 @@ pub async fn run(config: Config, opts: Opts) -> Result<()> {
if sub.dump_claims { if sub.dump_claims {
println!("{}", serde_json::to_string(token.opaque_claims())?); println!("{}", serde_json::to_string(token.opaque_claims())?);
} else { } else {
let encoded_token = token.encode(&config.token_hs256_secret.encoding)?; let encoded_token = token.encode(&config.token_hs256_secret)?;
println!("{}", encoded_token); println!("{}", encoded_token);
} }

View file

@ -11,7 +11,7 @@ use derivative::Derivative;
use serde::{de, Deserialize}; use serde::{de, Deserialize};
use xdg::BaseDirectories; 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::narinfo::Compression as NixCompression;
use crate::storage::{LocalStorageConfig, S3StorageConfig}; 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. /// Environment variable storing the Base64-encoded HS256 JWT secret.
const ENV_TOKEN_HS256_SECRET_BASE64: &str = "ATTIC_SERVER_TOKEN_HS256_SECRET_BASE64"; 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. /// Configuration for the Attic Server.
#[derive(Clone, Derivative, Deserialize)] #[derive(Clone, Derivative, Deserialize)]
#[derivative(Debug)] #[derivative(Debug)]
@ -102,10 +96,10 @@ pub struct Config {
/// ///
/// Set this to the base64 encoding of a randomly generated secret. /// Set this to the base64 encoding of a randomly generated secret.
#[serde(rename = "token-hs256-secret-base64")] #[serde(rename = "token-hs256-secret-base64")]
#[serde(deserialize_with = "deserialize_base64_jwt_secret")] #[serde(deserialize_with = "deserialize_token_hs256_secret_base64")]
#[serde(default = "JwtKeys::load_from_env")] #[serde(default = "load_token_hs256_secret_from_env")]
#[derivative(Debug = "ignore")] #[derivative(Debug = "ignore")]
pub token_hs256_secret: JwtKeys, pub token_hs256_secret: HS256Key,
} }
/// Database connection configuration. /// Database connection configuration.
@ -189,18 +183,11 @@ pub struct GarbageCollectionConfig {
pub default_retention_period: Duration, pub default_retention_period: Duration,
} }
impl JwtKeys { fn load_token_hs256_secret_from_env() -> HS256Key {
fn load_from_env() -> Self { let s = env::var(ENV_TOKEN_HS256_SECRET_BASE64)
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.");
.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) decode_token_hs256_secret_base64(&s).expect("Failed to load as decoding key")
.expect("Failed to load as decoding key");
let encoding = JwtEncodingKey::from_base64_secret(&s)
.expect("Failed to load as decoding key");
Self { decoding, encoding }
}
} }
impl CompressionConfig { impl CompressionConfig {
@ -247,17 +234,16 @@ impl Default for GarbageCollectionConfig {
} }
} }
fn deserialize_base64_jwt_secret<'de, D>(deserializer: D) -> Result<JwtKeys, D::Error> fn deserialize_token_hs256_secret_base64<'de, D>(deserializer: D) -> Result<HS256Key, D::Error>
where where
D: de::Deserializer<'de>, D: de::Deserializer<'de>,
{ {
use de::Error; use de::Error;
let s = String::deserialize(deserializer)?; let s = String::deserialize(deserializer)?;
let decoding = JwtDecodingKey::from_base64_secret(&s).map_err(Error::custom)?; let key = decode_token_hs256_secret_base64(&s).map_err(Error::custom)?;
let encoding = JwtEncodingKey::from_base64_secret(&s).map_err(Error::custom)?;
Ok(JwtKeys { decoding, encoding }) Ok(key)
} }
fn default_listen_address() -> SocketAddr { fn default_listen_address() -> SocketAddr {

View file

@ -17,7 +17,7 @@ use rand::distributions::Alphanumeric;
use rand::Rng; use rand::Rng;
use tokio::fs::{self, OpenOptions}; use tokio::fs::{self, OpenOptions};
use crate::access::{JwtEncodingKey, Token}; use crate::access::{decode_token_hs256_secret_base64, Token};
use crate::config; use crate::config;
use attic::cache::CacheNamePattern; use attic::cache::CacheNamePattern;
@ -75,8 +75,8 @@ pub async fn run_oobe() -> Result<()> {
perm.configure_cache_retention = true; perm.configure_cache_retention = true;
perm.destroy_cache = true; perm.destroy_cache = true;
let encoding_key = JwtEncodingKey::from_base64_secret(&hs256_secret_base64)?; let key = decode_token_hs256_secret_base64(&hs256_secret_base64).unwrap();
token.encode(&encoding_key)? token.encode(&key)?
}; };
eprintln!(); eprintln!();

View file

@ -11,7 +11,7 @@ attic = { path = "../attic", default-features = false }
base64 = "0.20.0" base64 = "0.20.0"
chrono = "0.4.23" chrono = "0.4.23"
displaydoc = "0.2.3" displaydoc = "0.2.3"
jsonwebtoken = "8.2.0" jwt-simple = "0.11.2"
lazy_static = "1.4.0" lazy_static = "1.4.0"
regex = "1.7.0" regex = "1.7.0"
serde = "1.0.151" serde = "1.0.151"

View file

@ -73,9 +73,10 @@ use std::error::Error as StdError;
use chrono::{DateTime, Utc}; use chrono::{DateTime, Utc};
use displaydoc::Display; use displaydoc::Display;
pub use jsonwebtoken::{ pub use jwt_simple::{
Algorithm as JwtAlgorithm, DecodingKey as JwtDecodingKey, EncodingKey as JwtEncodingKey, algorithms::{HS256Key, MACLike},
Header as JwtHeader, Validation as JwtValidation, claims::{Claims, JWTClaims},
prelude::UnixTimeStamp,
}; };
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use serde_with::{serde_as, BoolFromInt}; use serde_with::{serde_as, BoolFromInt};
@ -111,17 +112,11 @@ macro_rules! require_permission_function {
/// A validated JSON Web Token. /// A validated JSON Web Token.
#[derive(Debug)] #[derive(Debug)]
pub struct Token(jsonwebtoken::TokenData<TokenClaims>); pub struct Token(JWTClaims<TokenClaims>);
/// Claims of a JSON Web Token. /// Claims of a JSON Web Token.
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
struct TokenClaims { struct TokenClaims {
/// Subject.
sub: String,
/// Expiration timestamp.
exp: usize,
/// Attic namespace. /// Attic namespace.
#[serde(rename = "https://jwt.attic.rs/v1")] #[serde(rename = "https://jwt.attic.rs/v1")]
attic_ns: AtticAccess, attic_ns: AtticAccess,
@ -208,14 +203,16 @@ pub enum Error {
PermissionDenied, PermissionDenied,
/// JWT error: {0} /// JWT error: {0}
TokenError(jsonwebtoken::errors::Error), TokenError(jwt_simple::Error),
/// Base64 decode error: {0}
Base64Error(base64::DecodeError),
} }
impl Token { impl Token {
/// Verifies and decodes a token. /// Verifies and decodes a token.
pub fn from_jwt(token: &str, key: &JwtDecodingKey) -> Result<Self> { pub fn from_jwt(token: &str, key: &HS256Key) -> Result<Self> {
let validation = JwtValidation::default(); key.verify_token(token, None)
jsonwebtoken::decode::<TokenClaims>(token, key, &validation)
.map_err(|e| Error::TokenError(e)) .map_err(|e| Error::TokenError(e))
.map(Token) .map(Token)
} }
@ -223,31 +220,38 @@ impl Token {
/// Creates a new token with an expiration timestamp. /// Creates a new token with an expiration timestamp.
pub fn new(sub: String, exp: &DateTime<Utc>) -> Self { pub fn new(sub: String, exp: &DateTime<Utc>) -> Self {
let claims = TokenClaims { let claims = TokenClaims {
sub,
exp: exp.timestamp() as usize,
attic_ns: Default::default(), attic_ns: Default::default(),
}; };
Self(jsonwebtoken::TokenData { Self(JWTClaims {
header: JwtHeader::new(JwtAlgorithm::HS256), issued_at: None,
claims, 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. /// Encodes the token.
pub fn encode(&self, key: &JwtEncodingKey) -> Result<String> { pub fn encode(&self, key: &HS256Key) -> Result<String> {
jsonwebtoken::encode(&self.0.header, &self.0.claims, key) key.authenticate(self.0.clone())
.map_err(|e| Error::TokenError(e)) .map_err(|e| Error::TokenError(e))
} }
/// Returns the subject of the token. /// Returns the subject of the token.
pub fn sub(&self) -> &str { pub fn sub(&self) -> Option<&str> {
self.0.claims.sub.as_str() self.0.subject.as_deref()
} }
/// Returns the claims as a serializable value. /// Returns the claims as a serializable value.
pub fn opaque_claims(&self) -> &impl Serialize { pub fn opaque_claims(&self) -> &impl Serialize {
&self.0.claims &self.0
} }
/// Returns a mutable reference to a permission entry. /// Returns a mutable reference to a permission entry.
@ -283,11 +287,11 @@ impl Token {
} }
fn attic_access(&self) -> &AtticAccess { fn attic_access(&self) -> &AtticAccess {
&self.0.claims.attic_ns &self.0.custom.attic_ns
} }
fn attic_access_mut(&mut self) -> &mut AtticAccess { 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 {} impl StdError for Error {}
pub fn decode_token_hs256_secret_base64(s: &str) -> Result<HS256Key> {
let secret = base64::decode(s).map_err(Error::Base64Error)?;
Ok(HS256Key::from_bytes(&secret))
}
// bruh // bruh
fn is_false(b: &bool) -> bool { fn is_false(b: &bool) -> bool {
!b !b

View file

@ -13,8 +13,7 @@ fn test_basic() {
// "very secure secret" // "very secure secret"
let base64_secret = "dmVyeSBzZWN1cmUgc2VjcmV0"; let base64_secret = "dmVyeSBzZWN1cmUgc2VjcmV0";
let dec_key = let dec_key = decode_token_hs256_secret_base64(base64_secret).unwrap();
JwtDecodingKey::from_base64_secret(base64_secret).expect("Could not import decoding key");
/* /*
{ {