Compare commits

...

1 Commits

Author SHA1 Message Date
Edward Shen ab53a6ac24
Add support for v32 2021-07-09 14:32:43 -04:00
3 changed files with 34 additions and 0 deletions

1
Cargo.lock generated
View File

@ -1172,6 +1172,7 @@ dependencies = [
"parking_lot",
"prometheus",
"reqwest",
"ring",
"rustls",
"serde",
"serde_json",

View File

@ -32,6 +32,7 @@ lru = "0.6"
parking_lot = "0.11"
prometheus = { version = "0.12", features = [ "process" ] }
reqwest = { version = "0.11", default_features = false, features = [ "json", "stream", "rustls-tls" ] }
ring = "*"
rustls = "0.19"
serde = "1"
serde_json = "1"

View File

@ -17,6 +17,7 @@ use log::{debug, error, info, trace, warn};
use once_cell::sync::Lazy;
use prometheus::{Encoder, TextEncoder};
use reqwest::{Client, StatusCode};
use ring::signature::ECDSA_P256_SHA256_ASN1;
use serde::Deserialize;
use sodiumoxide::crypto::box_::{open_precomputed, Nonce, PrecomputedKey, NONCEBYTES};
use thiserror::Error;
@ -170,6 +171,8 @@ enum TokenValidationError {
TokenExpired,
#[error("Invalid chapter hash.")]
InvalidChapterHash,
#[error("Invalid v32 format")]
InvalidV32Format,
}
impl Responder for TokenValidationError {
@ -217,6 +220,35 @@ fn validate_token(
Ok(())
}
fn validate_token_v32(pub_key: &[u8], token: String) -> Result<(), TokenValidationError> {
#[derive(Deserialize)]
struct Token<'a> {
expires: DateTime<Utc>,
client_id: &'a str,
}
let (token_base64, sig_base64) = token
.split_once('~')
.ok_or_else(|| TokenValidationError::InvalidV32Format)?;
let token = base64::decode_config(token_base64, BASE64_CONFIG)?;
let sig = base64::decode_config(sig_base64, BASE64_CONFIG)?;
ring::signature::UnparsedPublicKey::new(&ECDSA_P256_SHA256_ASN1, pub_key)
.verify(&token, &sig)
.map_err(|_| TokenValidationError::DecryptionFailure)?;
// At this point, token has a valid signature, now to check token fields
let token: Token =
serde_json::from_slice(&token).map_err(|_| TokenValidationError::InvalidToken)?;
if token.expires < Utc::now() {
return Err(TokenValidationError::TokenExpired);
}
Ok(())
}
#[inline]
fn push_headers(builder: &mut HttpResponseBuilder) -> &mut HttpResponseBuilder {
builder