3 unstable releases
0.2.1 | Nov 14, 2019 |
---|---|
0.2.0 |
|
0.1.2 | Aug 6, 2019 |
0.1.1 | Aug 6, 2019 |
0.1.0 |
|
#3 in #web-service
28 downloads per month
34KB
508 lines
Alexa Rust Webservice Verifier
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.
Features
Both sync and async clients are provided by default. These are behind feature
flags sync
or async
, respectively.
sync
providesRequestVerifier
clientasync
providesRequestVerifierAsync
client
Using
Example 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
Dependencies
~12–17MB
~406K SLoC