1use std::fmt::{Debug, Formatter};
73use std::ops::{Deref, DerefMut};
74use serde::{Serialize, Deserialize, Serializer, Deserializer};
75use serde::de::{DeserializeOwned, Visitor};
76
77#[cfg(feature="hmac")]
78use hmac::Mac;
79
80const DOT: u8 = '.' as u8;
81static TYPE: &'static str = "JWT";
82
83#[derive(Serialize, Deserialize)]
85pub struct TokenHeader {
86 #[serde(skip_serializing_if="Option::is_none")]
87 #[serde(rename="type")]
88 pub _type: Option<String>,
89
90 #[serde(rename="alg")]
91 pub algorithm: TokenAlgorithm,
92}
93
94
95#[derive(Serialize, Deserialize, Clone, Debug)]
96pub enum TokenAlgorithm {
98 #[cfg(feature="HS256")]
99 HS256,
100 #[cfg(feature="HS512")]
101 HS512,
102 #[serde(other)]
103 Other
104}
105
106pub struct Token<T> {
110 pub header: TokenHeader,
111 pub payload: T
112}
113
114#[derive(Clone)]
115pub struct SignedToken {
122 algorithm: TokenAlgorithm,
123 body: Vec<u8>,
124 signature: Vec<u8>
125}
126
127#[derive(Debug)]
128pub enum TokenError {
130 UnsupportedAlgorithm,
132 InvalidKey,
134 InvalidHeader,
136 InvalidPayload(serde_json::Error),
138
139 InvalidToken,
141 InvalidSignature
143}
144
145fn b64_encode<S: AsRef<[u8]>>(input: S) -> Vec<u8> {
146 let mut buffer = Vec::new();
147 buffer.resize(input.as_ref().len() * 4 / 3 + 4, 0);
148 let decode = base64::encode_config_slice(
149 input.as_ref(),
150 base64::Config::new(base64::CharacterSet::UrlSafe, false),
151 &mut buffer
152 );
153 buffer.truncate(decode);
154 buffer
155}
156
157
158fn b64_decode<S: AsRef<[u8]>>(input: S) -> Result<Vec<u8>, TokenError> {
159 let input = input.as_ref();
160 let mut buffer = vec![0; (input.len() + 3) / 4 * 3];
161 let decode = base64::decode_config_slice(
162 input,
163 base64::Config::new(base64::CharacterSet::UrlSafe, false),
164 &mut buffer
165 );
166
167 match decode {
168 Err(_) => Err(TokenError::InvalidToken),
169 Ok(size) => {
170 buffer.truncate(size);
171 Ok(buffer)
172 }
173 }
174}
175
176impl TokenAlgorithm {
177 fn name(&self) -> &'static str {
178 match &self {
179 #[cfg(feature="HS256")]
180 TokenAlgorithm::HS256 => "HS256",
181 #[cfg(feature="HS512")]
182 TokenAlgorithm::HS512 => "HS512",
183
184 TokenAlgorithm::Other => "Unsupported",
185 }
186 }
187
188 pub fn sign<P: AsRef<[u8]>>(&self, payload: P, key: &[u8]) -> Result<Vec<u8>, TokenError> {
190 match &self {
191 #[cfg(feature="HS256")]
192 TokenAlgorithm::HS256 => {
193 let mut hash = match hmac::Hmac::<sha2::Sha256>::new_from_slice(&key) {
194 Ok(x) => x,
195 Err(_) => return Err(TokenError::InvalidKey)
196 };
197 hash.update(payload.as_ref());
198 return Ok(hash.finalize().into_bytes().as_slice().to_vec())
199 }
200 #[cfg(feature="HS512")]
201 TokenAlgorithm::HS512 => {
202 let mut hash = match hmac::Hmac::<sha2::Sha256>::new_from_slice(&key) {
203 Ok(x) => x,
204 Err(_) => return Err(TokenError::InvalidKey)
205 };
206 hash.update(payload.as_ref());
207 return Ok(hash.finalize().into_bytes().as_slice().to_vec())
208 }
209
210 TokenAlgorithm::Other => Err(TokenError::UnsupportedAlgorithm)
211 }
212 }
213
214 pub fn verify<P: AsRef<[u8]>>(&self, payload: P, sig: &[u8], key: &[u8]) -> Result<bool, TokenError> {
216 match &self {
217 #[cfg(feature="HS256")]
218 TokenAlgorithm::HS256 => {
219 let mut hash = match hmac::Hmac::<sha2::Sha256>::new_from_slice(&key) {
220 Ok(x) => x,
221 Err(_) => return Err(TokenError::InvalidKey)
222 };
223 hash.update(payload.as_ref());
224 Ok(hash.verify_slice(sig).is_ok())
225 }
226
227 #[cfg(feature="HS512")]
228 TokenAlgorithm::HS512 => {
229 let mut hash = match hmac::Hmac::<sha2::Sha512>::new_from_slice(&key) {
230 Ok(x) => x,
231 Err(_) => return Err(TokenError::InvalidKey)
232 };
233 hash.update(payload.as_ref());
234 Ok(hash.verify_slice(sig).is_ok())
235 }
236
237 TokenAlgorithm::Other => Err(TokenError::UnsupportedAlgorithm),
238 }
239 }
240}
241
242impl TokenHeader {
243 pub fn new(algorithm: TokenAlgorithm, include_type: bool) -> Self {
248 Self {
249 algorithm,
250 _type: if include_type { Some(TYPE.to_string()) } else { None }
251 }
252 }
253
254 fn serialize(&self) -> Result<Vec<u8>, TokenError> {
255 match serde_json::to_vec(&self) {
256 Ok(x) => Ok(x),
257 Err(_) => Err(TokenError::InvalidHeader)
258 }
259 }
260
261 fn deserialize(input: &[u8]) -> Result<TokenHeader, TokenError> {
262 match serde_json::from_slice(input) {
263 Ok(x) => Ok(x),
264 Err(_) => Err(TokenError::InvalidHeader)
265 }
266 }
267}
268
269impl<T> Token<T> {
270 pub fn create(algorithm: TokenAlgorithm, payload: T) -> Self {
278 Self {
279 header: TokenHeader::new(algorithm, false),
280 payload
281 }
282 }
283
284 pub fn new(header: TokenHeader, payload: T) -> Self {
295 Self {
296 header,
297 payload
298 }
299 }
300}
301
302impl<T: Serialize> Token<T> {
303 fn serialize(x: &T) -> Result<Vec<u8>, TokenError> {
304 match serde_json::to_vec(x) {
305 Ok(x) => Ok(x),
306 Err(e) => Err(TokenError::InvalidPayload(e))
307 }
308 }
309
310 fn build(&self) -> Result<Vec<u8>, TokenError> {
311 let mut buffer = b64_encode(&self.header.serialize()?);
312 buffer.push(DOT);
313 buffer.append(&mut b64_encode(Self::serialize(&self.payload)?));
314 Ok(buffer)
315 }
316
317 pub fn sign(&self, key: &[u8]) -> Result<SignedToken, TokenError> {
319 let buffer = self.build()?;
320 let sign = self.header.algorithm.sign(&buffer, &key)?;
321
322 Ok(SignedToken {
323 algorithm: self.header.algorithm.clone(),
324 body: buffer ,
325 signature: sign
326 })
327 }
328}
329
330impl<T: DeserializeOwned> Token<T> {
331 fn deserialize(x: &[u8]) -> Result<T, TokenError> {
332 match serde_json::from_slice(x) {
333 Ok(x) => Ok(x),
334 Err(e) => Err(TokenError::InvalidPayload(e))
335 }
336 }
337
338 pub fn verify<S: AsRef<[u8]>>(input: S, key: &[u8]) -> Result<Self, TokenError>{
340 let token = SignedToken::decode(input)?;
341 if !token.verify(key)? {
342 return Err(TokenError::InvalidSignature)
343 }
344 token.parse()
345 }
346}
347
348
349impl SignedToken {
350 pub fn bytes(&self) -> Vec<u8> {
352 let mut body = self.body.clone();
353 body.push(DOT);
354 body.append(&mut b64_encode(&self.signature));
355 body
356 }
357
358 pub fn into_bytes(self) -> Vec<u8> {
360 let mut body = self.body;
361 body.push(DOT);
362 body.append(&mut b64_encode(&self.signature));
363 body
364 }
365
366 pub fn string(&self) -> String {
368 String::from_utf8_lossy(&self.bytes()).to_string()
369 }
370
371
372 pub fn decode<S: AsRef<[u8]>>(input: S) -> Result<Self, TokenError> {
374 let mut parts = input.as_ref().split(|x| x == &DOT).collect::<Vec<&[u8]>>();
375
376 if parts.len() != 3 { return Err(TokenError::InvalidToken) }
377 let sig = b64_decode(&parts[2])?;
378 let header = TokenHeader::deserialize(&b64_decode(&parts[0])?)?;
379
380 let mut buffer = Vec::new();
381 buffer.extend_from_slice(&mut parts[0]);
382 buffer.push(DOT);
383 buffer.extend_from_slice(&mut parts[1]);
384
385 Ok(SignedToken {
386 algorithm: header.algorithm.clone(),
387 body: buffer,
388 signature: sig
389 })
390 }
391
392 pub fn parse<T: DeserializeOwned>(&self) -> Result<Token<T>, TokenError> {
394 let parts = self.body.split(|x| x == &DOT).collect::<Vec<&[u8]>>();
395
396 let header = TokenHeader::deserialize(&b64_decode(&parts[0])?)?;
397 let body = Token::<T>::deserialize(&b64_decode(&parts[1])?)?;
398
399 Ok(Token {
400 header,
401 payload: body
402 })
403 }
404
405 pub fn verify(&self, key: &[u8]) -> Result<bool, TokenError> {
407 self.algorithm.verify(&self.body, &self.signature, key)
408 }
409
410 pub fn parse_verify<T: DeserializeOwned>(&self, key: &[u8]) -> Result<Token<T>, TokenError> {
412 if !self.verify(key)? {
413 return Err(TokenError::InvalidSignature)
414 }
415 self.parse()
416 }
417}
418
419impl<T: Debug> Debug for Token<T> {
420 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
421 f.write_str("Token(")?;
422 f.write_str(self.header.algorithm.name())?;
423 f.write_str(", ")?;
424 self.payload.fmt(f)?;
425 f.write_str(" )")?;
426 Ok(())
427 }
428}
429
430impl Debug for SignedToken {
431 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
432 f.write_str("SignedToken(")?;
433 f.write_str(self.algorithm.name())?;
434 f.write_str(", ")?;
435 for byte in &self.signature {
436 f.write_str(&format!("{:x?}", byte))?;
437 }
438 f.write_str(" )")?;
439 Ok(())
440 }
441}
442
443impl<T> Deref for Token<T> {
444 type Target = T;
445
446 fn deref(&self) -> &Self::Target {
447 &self.payload
448 }
449}
450
451impl<T> DerefMut for Token<T> {
452 fn deref_mut(&mut self) -> &mut Self::Target {
453 &mut self.payload
454 }
455}
456
457impl Serialize for SignedToken {
458 fn serialize<S: Serializer>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error> {
459 serializer.serialize_str(&self.string())
460 }
461}
462
463impl<'de> Deserialize<'de> for SignedToken {
464 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer<'de> {
465 deserializer.deserialize_str(SignedTokenVisitor)
466 }
467}
468
469struct SignedTokenVisitor;
470
471impl<'de> Visitor<'de> for SignedTokenVisitor {
472 type Value = SignedToken;
473
474 fn expecting(&self, formatter: &mut Formatter) -> std::fmt::Result {
475 formatter.write_str("a valid token string")
476 }
477
478 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E> where E: serde::de::Error {
479 match SignedToken::decode(v) {
480 Ok(token) => Ok(token),
481 Err(error) => Err(serde::de::Error::custom(match error {
482 TokenError::InvalidPayload(e) => return Err(E::custom(e.to_string())),
483
484 TokenError::UnsupportedAlgorithm => "unsupported algorithm",
485 TokenError::InvalidKey => "invalid key",
486 TokenError::InvalidHeader => "invalid header",
487 TokenError::InvalidToken => "invalid token",
488 TokenError::InvalidSignature => "invalid signature",
489 }))
490 }
491 }
492}
493
494#[cfg(feature="HS256")]
495impl Default for TokenAlgorithm {
496 fn default() -> Self {
497 TokenAlgorithm::HS256
498 }
499}
500
501#[cfg(feature="http")]
502impl Into<http::StatusCode> for TokenError {
503 fn into(self) -> http::StatusCode {
504 match self {
505 TokenError::UnsupportedAlgorithm => http::StatusCode::BAD_REQUEST,
506 TokenError::InvalidKey => http::StatusCode::BAD_REQUEST,
507 TokenError::InvalidHeader => http::StatusCode::BAD_REQUEST,
508 TokenError::InvalidPayload(_) => http::StatusCode::BAD_REQUEST,
509 TokenError::InvalidToken => http::StatusCode::BAD_REQUEST,
510 TokenError::InvalidSignature => http::StatusCode::UNAUTHORIZED,
511 }
512 }
513}