mreinstein / alexa-verifier

✓ Verify HTTP requests sent to an Alexa skill are sent from Amazon
MIT License
76 stars 23 forks source link

verifier always throws error: "invalid signature" #40

Closed yozef closed 6 years ago

yozef commented 6 years ago

I have an Alexa Skill on the Amazon Dashboard to test, the functionality is hosted on a nodeJS server (with https).

While trying to submit the skill to Amazon, I've received an email that the headers were not validating.

So I was happy to find alexa-verifier and added it to my node app, like so:

var cert_url = req.headers['signaturecertchainurl'];
var signature = req.headers['signature'];
var requestRawBody = JSON.stringify(req.body);
if(cert_url && signature) {
        console.log('-> Cert & Signature exist');
        verifier(cert_url, signature, requestRawBody, function(error) {
                console.log('-> Verifier - Error? ' + JSON.stringify(error));
                if(!error) {
                    alexaskill(req, resp, next);
                } else {
                    resp.response.status(500);
                    resp.send({"Error": "Error verifying source of request to AlexaAppHandler - " + error});
                    next();
                }
            });
        } else {
            resp.response.status(500);
            resp.send({"error": "Proper headers not found"});
            next();
}

When testing from the Test tab of Alexa's Developer Console, I am always getting at console.log('-> Verifier - Error? ' + JSON.stringify(error)); in the code, this error: -> Verifier - Error? "invalid signature"

I should note, that I do see in the traceout the: cert_url, signature & requestRawBody, and I pass them into the Verifier.

mreinstein commented 6 years ago

@yozef are you using express?

yozef commented 6 years ago

@mreinstein thanks for your quick reply. No I'm using just nodejs.

yozef commented 6 years ago

I should also note, that in SSL Certificate tab in Alexa console, the My development endpoint is a sub-domain of a domain that has a wildcard certificate from a certificate authority selection. I assume this is fine?

mreinstein commented 6 years ago

this line is likely your problem:

var requestRawBody = JSON.stringify(req.body);

Why is req.body an object? Isn't it already a string? How is req.body being populated? You might try just changing that line to:

var requestRawBody = req.body;
mreinstein commented 6 years ago

You can't modify the raw request body at all, because the signature is signed against it. Changing even the whitespace in the body will break it.

Wherever you are setting req.body, this is what the logic should look like:

https://github.com/alexa-js/alexa-verifier-middleware/blob/master/index.js#L21-L24

yozef commented 6 years ago

Fixed it... the issue was: 1- Testing should be from Device (not web console, otherwise it will always return "invalid signature" 2- Failed Verification must return resp.response.status(400); & for successful verification resp.response.status(200);

Thanks @mreinstein