Rust Alexa Webservice Verifier

Verify that requests were sent by Alexa, in Rust

About

```rust

pub struct RequestVerifier {
    cert_cache: HashMap<String, Vec<u8>>,
}

impl Default for RequestVerifier {
    fn default() -> Self {
        RequestVerifier {
            cert_cache: HashMap::new(),
        }
    }
}

impl RequestVerifier {
    pub fn new() -> Self {
        RequestVerifier::default()
    }

    pub fn verify(
        &mut self,
        signature_cert_chain_url: &str,
        signature: &str,
        body: &[u8],
        timestamp: &str,
        timestamp_tolerance_millis: Option<u64>,
    ) -> Result<(), Error> { 
        ...
    }
}

```

Example using Rouille server and alexa_sdk

```rust use crate::skill::processrequest; // Entry point to custom skill use alexaverifier::RequestVerifier; use log::{debug, error, info}; use rouille::{router, Request, Response}; use std::{ io::Read, sync::{Mutex, MutexGuard}, };

fn note_routes(request: &Request, verifier: &mut MutexGuard) -> Response { router!(request, (POST) (/) => { info!("Request received...");

        // Get request body data
        let mut body = request.data().unwrap();
        let mut body_bytes: Vec<u8> = vec![];
        body.read_to_end(&mut body_bytes).unwrap();

        // Get needed headers, default to blank (will cause verification to fail)
        let signature_cert_chain_url = request.header("SignatureCertChainUrl").unwrap_or("");
        let signature = request.header("Signature").unwrap_or("");

        // Deserialize using alexa_sdk::Request
        let _request = serde_json::from_slice::<alexa_sdk::Request>(&body_bytes); 
        if let Err(e) = _request {
            error!("Could not deserialize request");
            error!("{:?}", e);
            let response = Response::empty_400();
            info!("Sending back response...");
            debug!("{:?}", response);
            return response;
        }
        let request = _request.unwrap();
        debug!("{:?}", request);

        // alexa-verifier used here, return 400 if verification fails
        if verifier
            .verify(
                signature_cert_chain_url,
                signature,
                &body_bytes,
                request.body.timestamp.as_str(),
                None
            ).is_err() {
                error!("Could not validate request came from Alexa");
                let response = Response::empty_400();
                info!("Sending back response...");
                debug!("{:?}", response);
                return response;
            };
        debug!("Request is validated...");

        // Entry point to skill, returning alexa_sdk::Response
        let response = Response::json(&process_request(request));
        info!("Sending back response...");
        debug!("{:?}", response);
        response
},
    _ => Response::empty_404()
)

}

pub fn run() -> std::io::Result<()> { info!("Starting server on 0.0.0.0:8086"); let verifier = Mutex::from(RequestVerifier::new());

rouille::start_server("0.0.0.0:8086", move |request| {
    let mut verifier = verifier.lock().unwrap();
    note_routes(&request, &mut verifier)
});

} ```