headless_lms_models/library/oauth/
tokens.rs

1use hmac::{Hmac, Mac};
2use rand::distr::SampleString;
3use rand::rng;
4use sha2::Sha256;
5
6use crate::library::oauth::Digest;
7
8const ACCESS_TOKEN_LENGTH: usize = 64;
9
10/// Generate a cryptographically strong opaque token suitable for access/refresh/auth codes.
11pub fn generate_access_token() -> String {
12    rand::distr::Alphanumeric.sample_string(&mut rng(), ACCESS_TOKEN_LENGTH)
13}
14
15/// Produce a `Digest` (HMAC-SHA-256) from an access/refresh token plaintext using a secret key.
16///
17/// This function uses HMAC-SHA-256 instead of plain SHA-256 to provide better security
18/// by requiring knowledge of the secret key to compute valid digests.
19///
20/// # Arguments
21/// * `token_plaintext` - The token string to hash
22/// * `key` - The secret key (pepper) to use for HMAC
23pub fn token_digest_sha256(token_plaintext: &str, key: &str) -> Digest {
24    let mut mac =
25        Hmac::<Sha256>::new_from_slice(key.as_bytes()).expect("HMAC can take key of any size");
26    mac.update(token_plaintext.as_bytes());
27    let result = mac.finalize();
28    let code_bytes = result.into_bytes();
29    let mut arr = [0u8; Digest::LEN];
30    arr.copy_from_slice(&code_bytes);
31    Digest::new(arr)
32}