jakubsuchy / amazon-alexa-php

Amazon Alexa PHP Library
36 stars 14 forks source link

Returning 500 internal server error from Amazon. #2

Closed briward closed 2 years ago

briward commented 7 years ago

Hi,

I've just started using the package, thanks very much for providing it! However, I wonder if you have experienced the same issue as me. I have followed the code examples but I keep getting a 500 error when testing via the Amazon developer hub.

Error: There was an error calling the remote endpoint, which returned HTTP 500 : Internal Server Error

If I test locally I get the following messages logged:

[2017-01-17 13:03:10] logger.CRITICAL: Request timestamp was too old. Possible replay attack. [] [] [2017-01-17 13:03:30] logger.CRITICAL: Protocol isn't secure. Request isn't from Alexa. [] []

So that makes me think I have everything setup correctly, as it shouldn't work locally.

Best wishes, Bri

danstreeter commented 7 years ago

Hey Bri,

I'm not the original creator, nor anything to do with this package, however I have merged quite a few developments from various people into my own fork here https://github.com/danstreeter/amazon-alexa-php

I've certainly not had that error using the merged copy...

You can see what has been merged here: https://github.com/jakubsuchy/amazon-alexa-php/network

All the best

Dan

briward commented 7 years ago

Hey Dan,

Ah I see, I think i've somehow become lost in forks here. I've now pulled your fork down and sadly the error persists. Does the "Service Simulator" (on Amazon developer interface) work for you when using the package?

Best wishes, Bri

danstreeter commented 7 years ago

Hmm, thats odd - I've got 'my' package working in three different skills at the moment without any problems, I doubt that amazon are having any service issues (given they are AWS! haha)...

Do you get any other information with regards to the error? Anything more in the error logs?

With regards to the replay attack: change the timestamp of your test message to something in the future (I have mine set to 2117 as there seems to be no upper bound checking).

briward commented 7 years ago

ha, yeah seems pretty strange. It could be something totally simple (hopefully!)

Sadly the main issue I have is the lack of errors in my logs, I've managed to get around the other two issues locally by changing timestamp and commenting out a few things.

I'll keep plowing through and see if I can get any more log messages.

Thanks

danstreeter commented 7 years ago

What are you incorporating the package into?

briward commented 7 years ago

I've got the package running inside a SlimPHP app, on an nginx, Ubuntu (DO) server. Nothing particularly fancy really.

briward commented 7 years ago

I've now managed to get the following:

Type: InvalidArgumentException Message: Request signature could not be verified File: akubsuchy/amazon-alexa-php/src/Request/Certificate.php Line: 90

So it looks like it may be having some problems with the openssl_verify check perhaps?

I'm using Let's Encrypt for SSL.

danstreeter commented 7 years ago

Are you sending the required header with the certificate path?

briward commented 7 years ago

Quite possibly not, I don't suppose you have any examples there?

danstreeter commented 7 years ago

The documentation for it is here: https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/developing-an-alexa-skill-as-a-web-service

However my payload is as follows:

Headers: signaturecertchainurl == https://s3.amazonaws.com/echo.api/echo-api-cert-4.pem signature == (base64string)

JSON Payload: { "session": { "sessionId": "SessionId.4f9bb0a5-7afe-4b2b-af5a-dbefff8183c3", "application": { "applicationId": "(application ID)" }, "attributes": {}, "user": { "userId": "amzn1.ask.account.xxxxxxx..." }, "new": true }, "request": { "type": "IntentRequest", "requestId": "EdwRequestId.1163cdd2-bcce-4d60-acaf-f3d3484c3fd1", "locale": "en-GB", "timestamp": "2016-12-27T23:59:42Z", "intent": { "name": "AskToCount", "slots": { "CountTo": { "name": "CountTo", "value": "10" } } } }, "version": "1.0" }

briward commented 7 years ago

Ah, i'm actually just using the built-in "Service Simulator" so i'm hoping that is sending the correct headers when it makes a request to my server.

danstreeter commented 7 years ago

It should be doing so yes, if your referring to the one under the Alexa Skills Kit > Test > Service Simulator.

I've never had inbound certificate issues with that one, only when I use a static payload from Postman do I need to 'return true;' from the Certificate class to ignore the invalid digest.

Can you use the following http://docs.slimframework.com/request/headers/ to get all the headers to check? (Presuming of course that this is the SlimPHP that your using)

I doubt it is that though to be honest, and would point toward the built in PHP open_ssl methods - I've had problems in the past when implementing them against a Java SOAP client request and the digest's just 'not matching' despite running through the correct routines...

My point to start would be to start throwing out some debug in the Certificate.php:: validateRequestSignature() method to ensure its getting the right content at all the right places. (Bear in mind however that some of this will be binary data)

briward commented 7 years ago

Looks like the openssl_pkey_get_public() function is returning nothing. This may be the problem.

$this->certificateContent and $this->requestSignature both appear to be returning correct values though.

danstreeter commented 7 years ago

Sounds about right as that will be then used to digest the message and provide a matching signature. Without that - it'll stump itself =(

briward commented 7 years ago

Perhaps my certificate is not X.509 (i'm not particularly knowledgeable in this area yet sadly) and therefor can't export the key from it.

danstreeter commented 7 years ago

You shouldnt have to be providing one as the consumer of inbound requests from ASK, they send you theirs and you validate it.

(I cant find my link to an easy to read version) but in summary: They get the data they want to send and create a digest by 'mashing' it using their PRIVATE key. They then send you the message incusive of this digest (now called signature) as part of the message, public on the line. They also send you a resource to get their public key (given in the header). You then take the public key and 'mash' the same data and you should end up with the same digest.

This prooves that the message has not changed in transit as no one but THEY can create it - anyone can confirm that they created it.

This is different to your SSL certificate, which although is of similar format, used for a different purpose. That has nothing to do with the communication between you, digest calculation, signature validation or anything to do with the messaging at all. The SSL certificate gives you encryption 'during transmission' whilst on the line.

SSL for HTTPS protects you against man in the middle & sniffing SSL for webservice messaging protects you against message replay (coupled with timestamp data which is part of the digest) and the messaging being changed 'in transit' should the HTTPS failed (unlikely)

Anyway... back to your issue... what version of PHP and openssl are you using on the server?

briward commented 7 years ago

Ah, thanks I appreciate the explanation. I have PHP 7.0.13 and OpenSSL 1.0.2g installed on my server.

danstreeter commented 7 years ago

I'm on PHP 5.6 and OpenSSL 1.0.2j in one of my development enviroments that works fine... I dont see any major changes between OpenSSL 1.0.2g > j (none that I can make any sense of anyway) https://www.openssl.org/news/openssl-1.0.2-notes.html.

And i've not tried it on PHP7 as yet so cant comment on that. =(

briward commented 7 years ago

Just to let you know I eventually solved my problem. Turns out I was actually re-encoding the JSON request and passing that in to verify, but by doing that I was changing the request and therefor invalidating it. Doh!

Simple ones are always the hardest 👍

danstreeter commented 7 years ago

Agh - yeh... that'll do it! =) Glad you got it sorted though.

I had a similar thing in the past with the ordering of things happening, turns out (obviously now) that you cant add things to a message once the digest has been calculated! Doh!