feat: add refresh token rotation flow
This commit is contained in:
@@ -6,6 +6,7 @@ use jsonwebtoken::{
|
||||
};
|
||||
use rand_core::OsRng;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use sha2::{Digest, Sha256};
|
||||
use time::{Duration, OffsetDateTime};
|
||||
use uuid::Uuid;
|
||||
|
||||
@@ -403,6 +404,12 @@ pub fn create_refresh_session_token() -> String {
|
||||
Uuid::new_v4().simple().to_string()
|
||||
}
|
||||
|
||||
pub fn hash_refresh_session_token(token: &str) -> String {
|
||||
let mut hasher = Sha256::new();
|
||||
hasher.update(token.as_bytes());
|
||||
format!("{:x}", hasher.finalize())
|
||||
}
|
||||
|
||||
pub fn build_refresh_session_set_cookie(token: &str, config: &RefreshCookieConfig) -> String {
|
||||
let mut parts = vec![
|
||||
format!(
|
||||
@@ -426,6 +433,22 @@ pub fn build_refresh_session_set_cookie(token: &str, config: &RefreshCookieConfi
|
||||
parts.join("; ")
|
||||
}
|
||||
|
||||
pub fn build_refresh_session_clear_cookie(config: &RefreshCookieConfig) -> String {
|
||||
let mut parts = vec![
|
||||
format!("{}=", config.cookie_name()),
|
||||
format!("Path={}", config.cookie_path()),
|
||||
"HttpOnly".to_string(),
|
||||
format!("SameSite={}", config.cookie_same_site().as_str()),
|
||||
"Max-Age=0".to_string(),
|
||||
];
|
||||
|
||||
if config.cookie_secure() {
|
||||
parts.push("Secure".to_string());
|
||||
}
|
||||
|
||||
parts.join("; ")
|
||||
}
|
||||
|
||||
impl fmt::Display for JwtError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
@@ -651,4 +674,25 @@ mod tests {
|
||||
assert!(cookie.contains("SameSite=Lax"));
|
||||
assert!(cookie.contains("Max-Age=2592000"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn hash_refresh_session_token_matches_sha256_hex() {
|
||||
let hash = hash_refresh_session_token("refresh-token-01");
|
||||
|
||||
assert_eq!(
|
||||
hash,
|
||||
"0b6901f0dcee3f50df4115ecb29214f7740f8173919f94cc1f5eb92ff2481ce8"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn build_refresh_session_clear_cookie_respects_config() {
|
||||
let cookie = build_refresh_session_clear_cookie(&build_refresh_cookie_config());
|
||||
|
||||
assert!(cookie.contains("genarrative_refresh_session="));
|
||||
assert!(cookie.contains("Path=/api/auth"));
|
||||
assert!(cookie.contains("HttpOnly"));
|
||||
assert!(cookie.contains("SameSite=Lax"));
|
||||
assert!(cookie.contains("Max-Age=0"));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user