use async_trait::async_trait;
use dpop_verifier::{DpopError, DpopVerifier, ReplayContext, ReplayStore};
use std::collections::HashSet;
use std::io::{self, Read};
struct MemoryStore(HashSet<[u8; 32]>);
#[async_trait]
impl ReplayStore for MemoryStore {
async fn insert_once(
&mut self,
jti_hash: [u8; 32],
_ctx: ReplayContext<'_>,
) -> Result<bool, DpopError> {
Ok(self.0.insert(jti_hash))
}
}
#[tokio::main(flavor = "current_thread")]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut dpop = String::new();
io::stdin().read_to_string(&mut dpop)?;
let dpop = dpop.trim();
let expected_htu = std::env::var("HTU").unwrap_or_else(|_| "http://localhost/resource".into());
let expected_htm = std::env::var("HTM").unwrap_or_else(|_| "GET".into());
let access_token =
std::env::var("ACCESS_TOKEN").expect("set ACCESS_TOKEN env var for RS verification");
let mut store = MemoryStore(HashSet::new());
let mut verifier = DpopVerifier::new()
.with_max_age_seconds(300)
.with_future_skew_seconds(5);
if let Ok(client_id) = std::env::var("CLIENT_ID") {
verifier = verifier.with_client_binding(client_id);
}
let verified = verifier
.verify(
&mut store,
dpop,
&expected_htu,
&expected_htm,
Some(&access_token), )
.await?;
eprintln!("Verified RS call:");
eprintln!(" jkt = {}", verified.jkt);
eprintln!(" jti = {}", verified.jti);
eprintln!(" iat = {}", verified.iat);
Ok(())
}