feat(iam): tambahkan CSPRNG (OsRng) untuk token state/PKCE

This commit is contained in:
asepharyana
2026-07-17 09:08:41 +07:00
parent 4dc4f80fa3
commit 5ede65f454
4 changed files with 43 additions and 0 deletions
Generated
+2
View File
@@ -4772,7 +4772,9 @@ dependencies = [
"anyhow",
"base64",
"chrono",
"hex",
"libc",
"rand_core 0.6.4",
"reqwest",
"serde",
"serde_json",
+2
View File
@@ -18,3 +18,5 @@ tracing.workspace = true
url.workspace = true
base64.workspace = true
sha2.workspace = true
hex.workspace = true
rand_core = { version = "0.6", features = ["getrandom"] }
@@ -1,2 +1,3 @@
pub mod http;
pub mod persistence;
pub mod rng;
@@ -0,0 +1,38 @@
//! Cryptographically secure random-token generation for OAuth CSRF state
//! tokens and PKCE verifiers.
use rand_core::{OsRng, RngCore};
/// Generate `n_bytes` of CSPRNG output, hex-encoded.
///
/// Why: the previous implementation derived "randomness" from
/// `SystemTime::now()` XORed with a monotonic counter — predictable given
/// a bounded guess at request time, which undermines both CSRF `state`
/// and PKCE verifier unpredictability. `OsRng` draws from the OS entropy
/// source (`getrandom`/`/dev/urandom` equivalent) and is the same
/// primitive already used correctly for password-salt generation in
/// `zesdex-libs::password::hash_password`.
///
/// Return: a lowercase hex string of length `2 * n_bytes`.
pub fn secure_token_hex(n_bytes: usize) -> String {
let mut buf = vec![0u8; n_bytes];
OsRng.fill_bytes(&mut buf);
hex::encode(buf)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn secure_token_hex_produces_correct_length() {
assert_eq!(secure_token_hex(16).len(), 32);
assert_eq!(secure_token_hex(32).len(), 64);
}
#[test]
fn secure_token_hex_is_not_constant() {
let a = secure_token_hex(16);
let b = secure_token_hex(16);
assert_ne!(a, b, "two consecutive calls must not produce the same token");
}
}