Crates.io | alexa-verifier |
lib.rs | alexa-verifier |
version | 0.2.1 |
source | src |
created_at | 2019-08-06 00:11:56.317402 |
updated_at | 2019-11-14 23:23:48.958131 |
description | Verify that requests were sent by Alexa for custom webservice skills, in Rust |
homepage | |
repository | https://github.com/tarkah/alexa-rust-webservice-verifier |
max_upload_size | |
id | 154426 |
size | 34,449 |
Verify that incoming requests are from Alexa for custom, webservice skills.
Confirmed working with the Alexa certification functional test.
Built using the Developer Documentation and Python Alexa SDK as reference.
Both sync and async clients are provided by default. These are behind feature
flags sync
or async
, respectively.
sync
provides RequestVerifier
clientasync
provides RequestVerifierAsync
clientExample using Rouille server and alexa_sdk for request deserialization
use crate::skill::process_request; // Entry point to custom skill
use alexa_verifier::RequestVerifier; // Struct provided by this crate
use log::{debug, error, info};
use rouille::{router, Request, Response};
use std::io::Read;
fn note_routes(request: &Request, verifier: &RequestVerifier) -> 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 custom 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 = RequestVerifier::new();
rouille::start_server("0.0.0.0:8086", move |request| {
note_routes(&request, &verifier)
});
}
License: MIT