MCPcopy Create free account
hub / github.com/NodeDB-Lab/nodedb / validate

Method validate

nodedb/src/control/security/jwt.rs:122–224  ·  view source on GitHub ↗

Validate a JWT token string and extract the authenticated identity. Performs: 1. Base64 decode header + payload + signature 2. HMAC-SHA256 signature verification (if configured) 3. Expiration check (`exp` claim) 4. Issuer/audience validation (if configured) 5. Map claims → `AuthenticatedIdentity`

(&self, token: &str)

Source from the content-addressed store, hash-verified

120 /// 4. Issuer/audience validation (if configured)
121 /// 5. Map claims → `AuthenticatedIdentity`
122 pub fn validate(&self, token: &str) -> Result<AuthenticatedIdentity, JwtError> {
123 let parts: Vec<&str> = token.split('.').collect();
124 if parts.len() != 3 {
125 return Err(JwtError::MalformedToken);
126 }
127
128 // Decode header to determine algorithm.
129 let header_bytes = base64_url_decode(parts[0]).ok_or(JwtError::DecodingError)?;
130 let header: JwtHeader =
131 sonic_rs::from_slice(&header_bytes).map_err(|_| JwtError::InvalidClaims)?;
132
133 // Decode payload (middle part). We verify signature separately.
134 let payload_bytes = base64_url_decode(parts[1]).ok_or(JwtError::DecodingError)?;
135 let claims: JwtClaims =
136 sonic_rs::from_slice(&payload_bytes).map_err(|_| JwtError::InvalidClaims)?;
137
138 // Verify signature based on algorithm declared in header.
139 let signing_input = format!("{}.{}", parts[0], parts[1]);
140 let signature_bytes = base64_url_decode(parts[2]).ok_or(JwtError::DecodingError)?;
141
142 match header.alg.as_str() {
143 "HS256" => {
144 if self.config.hmac_secret.is_empty() {
145 return Err(JwtError::UnsupportedAlgorithm);
146 }
147 if !verify_hmac_sha256(
148 &self.config.hmac_secret,
149 signing_input.as_bytes(),
150 &signature_bytes,
151 ) {
152 return Err(JwtError::InvalidSignature);
153 }
154 }
155 "RS256" => {
156 if self.config.rsa_public_key_der.is_empty() {
157 return Err(JwtError::UnsupportedAlgorithm);
158 }
159 if !verify_rsa_sha256(
160 &self.config.rsa_public_key_der,
161 signing_input.as_bytes(),
162 &signature_bytes,
163 ) {
164 return Err(JwtError::InvalidSignature);
165 }
166 }
167 _ => return Err(JwtError::UnsupportedAlgorithm),
168 }
169
170 // Check expiration.
171 let now = SystemTime::now()
172 .duration_since(UNIX_EPOCH)
173 .unwrap_or_default()
174 .as_secs();
175
176 if claims.exp > 0 && now > claims.exp + self.config.clock_skew_seconds {
177 return Err(JwtError::Expired);
178 }
179 if claims.nbf > 0 && now + self.config.clock_skew_seconds < claims.nbf {

Callers 9

malformed_token_rejectedFunction · 0.45
rs256_roundtripFunction · 0.45
set_permission_treeFunction · 0.45
create_sequenceFunction · 0.45
try_validate_jwtFunction · 0.45
validate_upgrade_tokenFunction · 0.45
handle_handshakeMethod · 0.45
handle_token_refreshMethod · 0.45

Calls 12

base64_url_decodeFunction · 0.85
verify_hmac_sha256Function · 0.85
nowFunction · 0.85
collectMethod · 0.80
duration_sinceMethod · 0.80
verify_rsa_sha256Function · 0.70
lenMethod · 0.45
as_strMethod · 0.45
is_emptyMethod · 0.45
as_bytesMethod · 0.45
iterMethod · 0.45
cloneMethod · 0.45

Tested by 2

malformed_token_rejectedFunction · 0.36
rs256_roundtripFunction · 0.36