I'd like to connect a chatbot made in python and deployed on aws lambda to a facebook page.
this is my code to verifly connection to facebook
def webhook(event, context):
# #debug
print("event:" )
print(event)
# print("context")
# print(context)
#handle webhook challenge
if keys_exist(event, ["queryStringParameters"]):
print("Veriflying stuff")
v_token = str(find_item(event, 'hub.verify_token'))
print("token :")
print (v_token)
challenge = int(find_item(event, 'hub.challenge'))
print ("challenge")
print(challenge)
if (os.environ['verify_token'] == v_token):
print ("returning stuff")
return (challenge)
But facebook says The URL couldn't be validated. Callback verification failed with the following errors: HTTP Status Code = 502; HTTP Message = Bad Gateway
I have created the urls with serverless. It works well when i do a get request from the browser.
I have given the same url in the facebook Webhook page. And made sure the validation and Verify Token are correct.
I have tried a few things I saw online. But i dont understand a few of them like this one
Facebook Messenger API "URL COULD NOT BE VALIDATED"
I dont understand if I nned a cert file for this?
AND "The URL could not be validated", facebook api error says to give path to a php. Which I dont even use?
I have found the problem.
Facebook also now required the status code of the request.
if keys_exist(event, ["queryStringParameters","hub.verify_token","hub.challenge"]):
print("subscribe to webhook invoked")
v_token = str(find_item(event, 'hub.verify_token'))
challenge = find_item(event, 'hub.challenge')
if ("strongtoken" == v_token):
response = {
"statusCode": 200,
"body": str(challenge)
}
print(challenge)
return response
Related
I am new to python and coding in general and I have been tasked with creating a Google Chat Bot that will send an alert in a Google Chat Room when our hardware monitoring service detects an issue. The general premise of the project is that the monitoring service takes my webhook URL and uses it to give me the JSON and I have to get that to the Google Chat in a readable and timely fashion.
This is what I have so far :
from flask import Flask, request, abort, Response
from json import dumps
from httplib2 import Http
app = Flask(__name__)
def main(botmsg):
url = #placeholder for Google Chat Webhook URL#
bot_message = {
'text' : botmsg}
message_headers = {'Content-Type': 'application/json; charset=UTF-8'}
http_obj = Http()
Response = http_obj.request(
uri=url,
method='post',
headers=message_headers,
body=dumps(bot_message),
)
print(Response)
#app.route('/', methods=['POST'])
def respond():
if request.method == 'POST':
print(request.json)
return Response(status=200)
else: abort(400)
if __name__ == '__main__':
app.run()
At first I had this exact file running locally. I would spin up my flask server but I could never get the main() to ping the Google Chat when I triggered it with a local webhook. Alone, the main function is working but I couldn't call the function in response to receiving the webhook. Now I am struggling with the same issue with this code in a Google Function pinging it using Github.
I get this error in my function logs when I ping it with the webhook:
"TypeError: Object of type Request is not JSON serializable"
I have been scraping the internet for weeks on how to do this to no avail so if anyone could give me some pointers it would be greatly appreciated!
I hope everyone is fine. I am trying to implement google sso on my fastapi app. after entering the user credentials is entered and it gets redirected while redirecting i am getting this error
google_sso = GoogleSSO("client-id", "client-secret", "http://127.0.0.1:8000/google/callback/")
#app1.get("/google/login")
async def google_login():
"""Generate login url and redirect"""
return await google_sso.get_login_redirect()
#app1.get("/google/callback")
async def google_callback(request: Request):
"""Process login response from Google and return user info"""
user = await google_sso.verify_and_process(request)
print("Hellooooooooooooooo")
print(user, "11111111111111")
return {
"id": user.id,
"picture": user.picture,
"display_name": user.display_name,
"email": user.email,
"provider": user.provider,
}
I have shared the URL configuration in google dashboard in below screenshot
enter image description here
the error i have mentioned below
oauthlib.oauth2.rfc6749.errors.CustomOAuth2Error: (redirect_uri_mismatch) Bad Request
The problem could lay in the process_login() function which is getting called in the verify_and_process() function in your /callback api.
Let's take a look inside the process_login() function (https://tomasvotava.github.io/fastapi-sso/sso/base.html#fastapi_sso.sso.base.SSOBase.verify_and_process):
async def process_login(self, code: str, request: Request) -> Optional[OpenID]:
"""This method should be called from callback endpoint to verify the user and request user info endpoint.
This is low level, you should use {verify_and_process} instead.
"""
url = request.url
current_url = str(url).replace("http://", "https://")
current_path = f"https://{url.netloc}{url.path}"
I guess the (redirect_uri_mismatch) error is because you are using a HTTP redirect_url in your GoogleSSO() call:
google_sso = GoogleSSO("client-id", "client-secret", "http://127.0.0.1:8000/google/callback/")
Inside the process_login() function the HTTP of the redirect url inside the url of your request is replaced with HTTPS:
url = request.url
current_url = str(url).replace("http://", "https://")
After that replacement you have a mismatch with your redirect url, because
https://127.0.0.1:8000/google/callback/
is not
http://127.0.0.1:8000/google/callback/
They are two different urls.
Solution could be that you secure your server with HTTPS via self signed certificates.
(That one is very simple: https://dev.to/rajshirolkar/fastapi-over-https-for-development-on-windows-2p7d)
Btw. did you register you app in the google cloud (https://developers.google.com/identity/sign-in/web/sign-in)? Because you are using "client-id" and "client-secret" as parameters.
try it use 127.0.0.1:8000/google/callback #remove /
or
fix url #app1.get("/google/callback/") #add /
This is because the port number is changing in the redirect URI, everytime you run the application.
So everytime you run it it becomes:
http://localhost:65280/
http://localhost:65230/
http://localhost:63280/
And so forth. I dont have a solution for you yet. Working on it myself right now.
I am using python-social-auth for authentication with social networks.
I have installed and configured everything. In the last step, I added these two action links:
Login with Facebook
Login with Instagram
Facebook login is working fine but instagram is giving me the following error:
{"code": 400, "error_type": "OAuthException", "error_message": "Redirect URI does not match registered redirect URI"}
in my settings.py I have these:
SOCIAL_AUTH_INSTAGRAM_KEY = 'my_key'
SOCIAL_AUTH_INSTAGRAM_SECRET = 'my_secret'
and
INSTAGRAM_REDIRECT_URI = 'http://localhost:8000/shops/edit'
the most interesting part is that if I try to do this without python-social-aut, i.e. using these configurations:
INSTAGRAM_CLIENT_ID = get_env_setting('INSTAGRAM_CLIENT_ID')
INSTAGRAM_CLIENT_SECRET = get_env_setting('INSTAGRAM_CLIENT_SECRET')
INSTAGRAM_REDIRECT_URI = get_env_setting('INSTAGRAM_REDIRECT_URI')
It is just working fine.
I am thinking it has something to do with that python-social-auth app.
How can I fix it?
Try to set SOCIAL_AUTH_INSTAGRAM_REDIRECT_URL for example
SOCIAL_AUTH_INSTAGRAM_REDIRECT_URL = 'http://localhost:8000/complete/instagram'
and check redirect uri in you instagram client settings.
I'm consistently getting an "Invalid response from Facebook" error when authenticating over Facebook with Oauthlib when building off of the sample code here.
I've outlined the sections of relevant code below.
Setup:
Setting up the Oauth request object.
Not pictured: Navigational routes and Flask app initialization.
from flask_oauthlib.client import OAuth, OAuthException
oauth = OAuth()
facebook = oauth.remote_app('facebook',
base_url='https://graph.facebook.com/',
request_token_url=None,
access_token_url='/oauth/access_token',
authorize_url='https://www.facebook.com/dialog/oauth',
consumer_key=config.get("app_id"),
consumer_secret=config.get("app_secret"),
request_token_params={'scope': 'public_profile,email'}
)
#facebook.tokengetter
def get_facebook_token():
if current_user.is_authenticated():
return current_user.get_facebook_token()
else:
return None
Login handler:
Sending users here in order to begin the process, with the url for the facebook callback appended to the root URL.
#app.route('/facebook/login')
def facebook_login():
return facebook.authorize(callback="http://example.com%s" % url_for('facebook_callback'))
Facebook callback, source of the issue:
From here I can garner that a code (presumably the token) is returned but Oauthlib fails to parse it correctly.
#app.route('/facebook/callback')
def facebook_callback(response):
response = facebook.authorized_response()
if response is None:
flash("You denied the request to sign in.", "error")
return redirect(url_for('index'))
if isinstance(response, OAuthException):
flash("Access denied: %s" % response.message, "error")
return redirect(url_for('index'))
# Request fails here, returns the redirect above.
From dumping the request args I can see fairly clearly that after being directed to Facebook and successfully connecting, there is a very long token being returned to the callback along the lines of '?code=1234567890-abcdefghijklmnop', however actually trying to authenticate with this fails with "Invalid response from Facebook".
Here is a sample request dump:
ImmutableMultiDict([('code', 'AQAPedwWavTb_cBx6NVy-qy3AL5YPr780oG5tA1LfITpVwkk-kr_4I0lG6B-vlhcYEubhuKhEM46bPs-1WpWUpJzcWfhkQ64lIkdLm9uSHSqeBHBM_6zw7SDpvVmGK-JKWBpAqRJuBKenl9zslQizthox96104iiul0uYQY67cmZgPXZi9uL-mcgZ5dRj387eKJIjNninBXxwCGgFkg5kLVHYt7t0ktUH58stYlxn2f98AXuSlrIvWsA5NeHsVbM8XY0XQrDrNbCvjDmEwHQGkZ3uZRbyaecN7MAi0bM0TrZzpuQ8j3M34DnQp_v9n4ktM4')])
Having used similar code based off of the Twitter sample that works, I'm thinking this could be a possible library bug due to Facebook API changes, but I would appreciate any pointers!
For anyone who stumbles upon this from Google in the future, I solved this in a solution that can be read here.
Hey there, I solved this issue in a very hacky way which I would not
recommend for production environments, but I eventually found the
issue a few days after my last message.
When you ask Facebook for an access token, it does NOT give you an
access token in the way you might expect. What I assumed to be a
failure on Facebook's side was instead a (perhaps intentional)
formatting error.
What you might expect:
http://example.com/callback?access_token=00000000000
or
http://example.com/callback with the access token passed as a POST
argument in the headers.
What actually happens is that Facebook responds like this:
http://example.com/callback?#access_token=0000000000
Because of this, it is -impossible- for any server side language
to parse it, as the access token will now only be visible to the
browser itself. It is not passed to the backend whatsoever.
Capturing the request:
#app.route('/facebook/translate', methods=['GET'])
def facebook_translate():
# Facebook responds with the access token as ?#access_token,
# rather than ?access_token, which is only accessible to the browser.
# This part is where things get really, really dumb.
return ''' <script type="text/javascript">
var token = window.location.href.split("access_token=")[1];
window.location = "/facebook/callback?access_token=" + token;
</script> '''
Proceeding as usual:
#app.route('/facebook/callback', methods=['GET', 'POST'])
def facebook_callback():
access_token = request.args.get("access_token")
if access_token == "undefined":
flash("You denied the request to sign in.", "error")
return redirect(url_for('index'))
graph = facebooksdk.GraphAPI(access_token)
profile = graph.get_object("me")
I'm use facebook-sdk-0.4.0
I trying run from my server
access_token = get_app_access_token(settings.FACEBOOK_APP_ID, settings.FACEBOOK_API_SECRET)
graph = GraphAPI(access_token)
response = graph.put_wall_post(profile_id='274460312618957', message=message, attachment={'link':link, })
But have error
(#200) The user hasn't authorized the application to perform this
action
I have admin-rules of this page (274460312618957)
I have admin-rules of this APP settings.FACEBOOK_APP_ID
Way error (#200) ??
You need publish_stream permission for your app in order to create posts as detailed here. As to why you get a response code 200, they are detailed here