Can i use localhost as a URL Callback in a messenger webhook - facebook

Good evening, just saw that Facebook released his messenger bot toolkit and i immediately jumped right into it to learn more about it and maybe try to do my own.
My problem is that i don't have a https website running and it requires a https valid url. I tried to use my local web-server that has a certificate but it doesn't work.
My question is if this is possible to be done using a localhost url at all.
Thank you in advance

Actually this is possible with localhost. Use ngrok. It allows you to open localhost to the public web, over http or https. This should only be used for testing however.

If you want to test webhooks on your local environment, I would try ultrahook.com, you can get an API Key for free and the tool creates a tunnel from a public URL to your computer. This is from their FAQs page:
You download and run the UltraHook client on your computer. It
connects to UltraHook servers in the cloud and creates a tunnel from a
public endpoint on our servers to your computer. Any HTTP POST
requests sent to the public end point will be sent through the tunnel
an delivered to a private endpoint accessible from your computer.
I have used it to test webhooks from different providers (like payment gateways). In your computer, you can run something like:
ultrahook <subdomain> http://localhost:8000/webhook/
and then configure the webhook URL in your external service to something like <subdomain>.ultrahook.com

My question is if this is possible to be done using a localhost url at all.
No, of course it isn’t – because what such a “callback” actually means, is that Facebook makes a request to your server – and that is hardly possible with localhost.
A valid SSL certificate for your website is easy to get for free these days, via LetsEncrypt. And even if that is not available on your server, there’s still StartSSL, that provide basic certificates for free. All you need is a server you can install them on, or upload them to, or whatever mechanism your hoster provides for it. (And if they don’t provide any, then it might be time to switch.)

Related

OAuth access_denied on login from all providers after server IP change

We recently changed the IP-address on a server hosting one of our services based on .NET Web API 2.
The service is using OAuth2, providing external logins via Facebook/Google.
We're still using the same server and the same host name for our services, only the IP-address has changed. Now I'm getting back my login URL with "&error=access_denied" whenever I try to login using Facebook/Google.
I have checked every setting in both Facebook's and Google's developer consoles but nothing seems to apply. If I remove the OAuth redirect URI, I get an error that the URL is blocked, so the settings seems to take effect.
What have I missed?
Funny how asking a question makes you think even more outside of the box. The culprit was that wrong DNS-server was set on the web host.
I'll see myself out...

How to test Messenger Bots offline? Local webhooks

I'm starting with Messenger Platform API. I want to make simple Messenger Chatbot. Here is tutorial I follow.
As you see, to start I need to set up webhook (step 2). So basically: web server that provides some REST API and posts some data back. The problem is: facebook requires me to provide some real, existing app URL that works currently in internet. So, do I need to upload my code to server each time I change something? Can I somehow test it locally (on my localhost)? How can I test behavior of my bot?
There's a few services you can use to expose your webserver running on localhost to the public. Two options are localtunnel and ngrok.
An example (from localtunnel's quickstart) of how you might do this, given that your webserver is running at http://localhost:8000/ would look like this:
Install localtunnel from npm:
npm install -g localtunnel
Request a tunnel to your local server:
lt --port 8000
This will generate a link, of the form https://foo.localtunnel.me you can use to access your localhost from the web. One nice feature is that you automatically get https so Facebook won't give you a 'SSL certificate problem' error. Localtunnel or ngrok are also nice for sharing work running locally with others.
Note that the localtunnel url is only valid as long as the connection lives, so you will have to update the url Facebook has if the connection ends.
I created a library that tries to solve this exact problem! With fb-local-chat-bot you can easily test your bot offline. The library also makes testing much more simple. If you're interested, definitely check it out
https://github.com/spchuang/fb-local-chat-bot
Demo:
you may use ngrok to test the messenger bot in localhost. You may download it at:
https://ngrok.com/download
on executing ngrok, it will generate secure link that can be used as a end point in webhook.
You can also check the detailed status of each request and response of ngrok through
http://localhost:4040/inspect/http
Later, once you are done, you may deploy your code to secure server.
You can find more info as to how to build a basic chat bot on the link below:
How to build a basic chat bot on facebook messenger
You can deploy your backend services on heroku free of cost. It provide public DNS with RSA.
If you can't use ngrok for some reason (like routing webhook to multiples dev machines). please try this emulator i have created for developing / debugging webhooks locally. this provides emulation of send api and a messenger ui
I have created an emulator for send api and messenger which i use for debugging web hooks locally
https://github.com/SonOfSardaar/facebook-send-api-emulator
I also came across this (i have not tried this one yet but looks good)
https://learn.microsoft.com/en-us/bot-framework/debug-bots-emulator

HTTPS for local IP address

I have a gadget[*] that connects to the user's WiFi network and responds to commands over a simple REST interface. The user uses a web app to control this gadget. The web app is currently served over http and the app's javascript does AJAX calls to the gadget's local IP address to control it. This scheme works well and I have no issues with it.
[*] By "gadget" I mean an actual, physical IoT device that the user buys and installs within their home, and configures to connect to their home WiFi network
Now, I want to serve this web app over https. I have no issue setting up https on the hosting side. The problem is, now the browser blocks access to the gadget (since the gadget's REST API is over http and not https).
The obvious solution is to have the gadget serve it's REST API over https. But how? It has a local IP address and no one will issue a certificate for it. (Even if they did, I'd have to buy a boatload of certificates for each possible local IP address.) I could round-trip via the cloud (by adding additional logic on my server side to accept commands from the web app and forward it to the gadget over another connection), but this will increase latencies.
Is there a way around this problem? One possibility that I have in mind is to:
Get a wildcard certificate (say, *.mydomain.com)
Run my own DNS that maps sub-domains to a local IP address following a pattern (For example, 192-168-1-123.mydomain.com would map to 192.168.1.123)
Use the wild-card certificate in all the gadgets
My web app could then make AJAX calls to https://192-168-1-123.mydomain.com instead of http://192.168.1.123 and latencies would remain unaffected aside from the initial DNS lookup
Would this work? It's an expensive experiment to try out (wildcard certificates cost ~$200) and running a DNS server seems like a lot of work. Plus I find myself under-qualified to think through the security implications.
Perhaps there's already a service out there that solves this problem?
While this is a pretty old question, it is still nothing that you find out-of-the-box solutions for today.
Just as #Jaffa-the-cake posted in a comment, you can lean on how Plex did it, which Filippo Valsorda explained in his blog:
https://blog.filippo.io/how-plex-is-doing-https-for-all-its-users/
This is very similar to what you proposed yourself. You don't even need a wildcard certificate, but you can generate certificates on-the-fly using Let's Encrypt. (You can still use wildcard certificates, if you want, which Let's Encrypt supports now, too.)
Just yesterday I did a manual proof-of-concept for that workflow, that can be automated with the following steps:
Write a Web Service that can create DNS entries for individual devices dynamically and generate matching certificates via Let's Encrypt - this is pretty easy using certbot and e.g. Google Cloud DNS. I guess Azure, AWS and others have similar offerings, too. When you use certbot's DNS plugins, you don't even need to have an actual web server running on port 80/443.
On you local device, contact that Web Service to generate a unique DNS entry (e.g. ..yourdns.com) and certificate for that domain
Use that certificate in your local HTTPS server
Browse to that domain instead of your local IP
Now you will have a HTTPS connection to your local server, using a local IP, but a publicly resolved DNS entry.
The downside is that this does not work offline from arbitrary clients. And you need to think of a good security concept to create trust between the client that requests a DNS and certificate, and your web service that will generate those.
BTW, do you mind sharing what kind of gadget it is that you are building?
If all you want is to access the device APIs through the web browser, A Simple solution would be to proxy all the requests to the device through your web server.this was even self signed certs for the devices wont be a problem. Only problem though is that the server would have to be on the same network as your devices.
If you are not on the same network, you can write a simple browser plugin (chrome) to send the api request to IoT device. but then the dependency on the app/plugin will be clumsy.

Can't Authenticate with Local .NET back-end

I've followed the guide:
Getting Started with Authentication with Mobile Services .NET for Windows Store
I'm able to run the service locally as long as I don't need to authenticate the user. I can also authenticate the user if I publish the service to Azure. But I want to be able to test and authenticate the user locally. How can this be done?
I'm using Live ID and I have the correct ClientID and ClientSecret set in the Web.config. When I attempt to call LoginAsync from the client the call fails with The request could not be completed. (Method Not Allowed)
** Update 2014-03-20 **
Based on the comments of Carlos and Henrik, I've updated my local service to look exactly like my server instance. I followed Scot Hanselmans excellent guide and now I have my service running locally on port 80 and port 443 with a completely valid SSL certificate. It's even running on the exact same https://xxxx.azure-mabile.net hostname.
With these changes, there is now no configuration difference whatsoever between running the app against my local machine or running it against Azure. I can go to https://xxxx.azure-mabile.net in the browser, get redirected to Live login, sign in, and get redirected back to the service successfully. In the browser it all works. However it still doesn't work in the app.
I attached the debugger, set CLR errors to "break when thrown" and I managed to trap the exception in the service. Here's what I see in the immediate window:
The Response property is not helpful. It does not provide any additional information about the problem.
The only thing that stands out to me is that the app is trying to do a POST to /login/microsoftaccount while the browser would normally be doing a GET at this address (then getting redirected).
** Update #2 2014-03-20 **
After following Henriks guide for remote debugging I was able to load symbols and get a tiny bit more information:
"An existing connection was forcibly closed by the remote host"
The error code is 10054 (WSAECONNRESET) Connection reset by peer.
It appears the Live Authentication server may be forcibly terminating the connection, but only when I'm authenticating with the app. Again, authentication within the browser is fine. This, combined with the fact that /login/microsoftaccount is a POST from the app seems to suggest there is a problem with the authentication token I'm getting back from LiveClient.LoginAsync. I'll do some more digging...
At the moment, it is set up so that you don't need authentication when running locally and access the service from localhost. In this case, anonymous access is let through (this is of course disabled while running in the cloud).
We don't really have a way for your to authenticate locally as redirect URIs won't work (they can't point to localhost as there is not way that Facebook, say, can resolve "localhost").
One option is that we somehow can mock the authentication locally and give you a token without connecting with the various identity providers. I am not sure exactly what that would look like but it is something we can consider.
Henrik
Did you perhaps set Mobile client app: Yes in your Live Connect project? I think that setting is meant to be used with the Live Connect SDK (client) flow, not the browser-based (server) flow. The client flow isn't supported yet with a .NET backend.
You also want to make sure you are using LoginAsync(MobileServiceAuthenticationProvider.MicrosoftAccount) on the client to trigger the server flow.

How to test Facebook Real-time updates

In order to publish real-time updates to my app, Facebook needs needs to perform a post request to my server.
Problem is, my server is my home computer and not publicly addressable from the internet. Bringing a server live to implement this sounds like it could be a pain... can't attach debugger, fiddler etc....
So what's the best way to test the Http Endpoint? Integration tests that simulate the Facebook server? Fiddling with firewalls/NAT to try and get Facebook talking to my home computer?
Any ideas?
You can use ngrok - https://ngrok.com/ - free (pay-what-you-can) service that does exactly what you need. Localtunnel service is down and the developers also recommend ngrok.
In the past, I've used LocalTunnel to do this. It's a nice wrapper around an SSH tunnel and it effectively assigns you a subdomain at localtunnel.com pointing to a port on your localhost.
So basically, when you run it it will spit back an externally accessible sub domain name like xyz.localtunnel.com who's port 80 will point a port you specify on your local box.
You can find it at: http://progrium.com/localtunnel/
It's really great for testing various pubsubhubbub subscription feeds (like Facebook's).
OK! I think NAT should be the best bet and I don't see a reason for it not to work. You should try it out.
It was actually pretty easy - Logged into my home router, set up port forwarding on port 80 to the local IP of my computer, put an exception in windows firewall for port 80. and then navigate to my public IP address in the browser.
Implement the receiver samples at: https://github.com/facebook/real-time/tree/master/samples
The only answer is to get a webserver that is publicly accessible for real-time updates to be able to call back to.
There's lots of free webhosts that allow server-side scripting. And there's lots of paid for webhosts out there too. Stackoverflow is really not the place to get leads on where/when/why/howmuch for web hosting.
No you can't use ngrok only to simulate facebook realtime update since you must make a call to facebook servers with your ngrok adress to validate it (tell me if you find out how to do this :p ).
I use an openshift server to receive facebook realtime and then post evry json data received from facebook to my ngrok adress. So the process is
set up an openshift server to receive facebook notifications
Facebook sends notifications to your openshift
your openshift sends datas (as received) to your ngrok adress
And if you must receive facebook notifications on a local website (like www.website.dev/fb-notifications/) then create a script in your localhost folder which receives openshift posts (let's call it tunelscript.php). the process will be
set up an openshift server to receive facebook notifications
Facebook sends notifications to your openshift
your openshift sends datas (as received) to your tunel script via your ngrok adress (perso.ngrok.com/tunelscript.php)
Relay datas from your tunelscript to your local website (tunelscript.php => www.website.dev/fb-notifications/)
That's Tuneling B-)