Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 35 additions & 19 deletions src/storjwt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,33 +4,49 @@ use jwt::{Header, SignWithKey, Token, VerifyWithKey};
use sha2::Sha256;
use std::collections::BTreeMap;
use toml::value::Table;
fn verify_with_key_str(
token_str: &str,
key_str: &str,
) -> Result<BTreeMap<String, String>, jwt::Error> {
let key: Hmac<Sha256> = Hmac::new_from_slice(key_str.as_bytes())?;
let token: Token<Header, BTreeMap<String, String>, _> = token_str.verify_with_key(&key)?;
let claims = token.claims();
if claims.get("email").is_none() {
debug_log!("email not found");
return Err(jwt::Error::InvalidSignature);
}
Ok(claims.clone())
}

pub fn verify_jwt_token(token_str: &str) -> Result<BTreeMap<String, String>, jwt::Error> {
// config.toml, jwt_secret parameter
let toml_cfg = get_config_content();
let parsed_toml = toml_cfg.parse::<Table>().unwrap();
let key_str = parsed_toml["jwt_secret"].as_str().unwrap();
Comment on lines 22 to 24
Copy link

Copilot AI Apr 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

jwt_secret is still accessed via parsed_toml["jwt_secret"].as_str().unwrap(), which will panic before the new unified_secret fallback is attempted. If the intent is to support configs that only define unified_secret (or temporarily omit jwt_secret), switch this to an optional lookup (e.g., get("jwt_secret").and_then(|v| v.as_str())) and only attempt verification when present, otherwise fall through to unified_secret.

Copilot uses AI. Check for mistakes.
let key: Hmac<Sha256> = Hmac::new_from_slice(key_str.as_bytes())?;
let verify_result = token_str.verify_with_key(&key);
let token: Token<Header, BTreeMap<String, String>, _> = match verify_result {
Ok(token) => token,
Err(e) => {
eprintln!("JWT verification error: {:?}", e);
return Err(e);

match verify_with_key_str(token_str, key_str) {
Ok(claims) => {
debug_log!("email: {}", claims["email"]);
return Ok(claims);
}
};
//let header = token.header();
let claims = token.claims();
let email = claims.get("email");
match email {
Some(email) => {
debug_log!("email: {}", email);
Err(e) => {
debug_log!("JWT verification with jwt_secret failed: {:?}", e);
}
None => {
debug_log!("email not found");
return Err(jwt::Error::InvalidSignature);
}

if let Some(unified) = parsed_toml.get("unified_secret").and_then(|v| v.as_str()) {
match verify_with_key_str(token_str, unified) {
Ok(claims) => {
debug_log!("email (unified_secret): {}", claims["email"]);
return Ok(claims);
Comment on lines +36 to +40
Copy link

Copilot AI Apr 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New unified_secret verification path isn’t covered by existing tests (e2e tests currently only configure/sign with jwt_secret). Add a test that signs a token with unified_secret (and optionally ensures fallback works when jwt_secret is wrong/missing) to prevent regressions.

Copilot uses AI. Check for mistakes.
}
Err(e) => {
eprintln!("JWT verification with unified_secret also failed: {:?}", e);
return Err(e);
}
}
}
Ok(claims.clone())

Err(jwt::Error::InvalidSignature)
Comment on lines +48 to +49
Copy link

Copilot AI Apr 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When jwt_secret verification fails and unified_secret is not configured, the function returns a generic jwt::Error::InvalidSignature here, discarding the original verification error from the first attempt. Consider carrying the first error through (e.g., store it and return it when no fallback key exists) so failures are diagnosed accurately.

Copilot uses AI. Check for mistakes.
}

pub fn generate_jwt_secret() {
Expand Down