Why is a redirect used on oath? - python

See the example here. Why is a redirect used simply to connect to a service? Why bother with mocking a service and all that stuff? Is there some valid reason for all of this or is this just because someone made an assumption about how authentications would be used (i.e. author and user are different)? Is there a good way of avoiding this within the REPL?
https://github.com/SaxoBank/openapi-samples-python/blob/master/authentication/oauth/code-flow/bare-bones-code-flow-app.py

I don't fully understand your issue, but regarding the SAXO API and the oauth token, you always to need to define the RedirectUrls for generating the token. That's why the 5 keys listed in the provided are indeed mandatory :
params = {
"grant_type": "refresh_token",
"refresh_token": token_data["refresh_token"],
"redirect_uri": app_config["RedirectUrls"][0],
"client_id": app_config["AppKey"],
"client_secret": app_config["AppSecret"]
}
FYI, you can find the full doc of the Redirect URI here below :
https://www.oauth.com/oauth2-servers/redirect-uris/

Related

Trying to use python to authenticate to WebSite

I'm attempting to authenticate to a website to automate some device configuration.
There is no official API so I'm using "WebSpy" in my browser to watch what URLs are targeted and the payloads being sent.
I'm unable to get initial authentication working with a python post request.
The target url is https://xxxxxx.xxx/authenticate.
The payload I see when logging in from a web browser is.
{ "client_id": xxxxxx,
"username": <plainText username>,
"password": <plainText password>,
"realm": "xxxxx",
"credential_type": "http://auth0.com/oauth/grant-type/password-realm"}
If I replicate all this in a python requests.POST I get back
{ "error": "invalid request",
"error_description": "Unknown client."}
I should mention the "client_id" I'm sending in my python post is just copied from what I see coming from the browser.
I imagine that client ID should be dynamically generated somehow but I don't see where it's coming from.
I should also mention I see some reference to a \callback URL happening after login within the web browser so I'm guessing that is how/when the auth token is being offered.
Can anyone point me in the right direction on all this?
Thank you in advance.

Python 3.6 Post Request Domain API

This is a bit of a newbie Q.
I'm using Python 3.6
I am trying to use the domain realestate api to write a scraper that collects data of houses/apartments for sale in my area, but i am having trouble getting the post request to work. I have registered and retrieved my client_id and secret_id for the authentication. The post request returns a status_code of 400
response = requests.post('https://auth.domain.com.au/v1/connect/token',
data = {'client_id':client_id,
"client_secret":client_secret,
"grant_type":"client_credentials",
"scope":"api_agencies_read api_listings_read",
"Content-Type":"application/json"})
token=response.json()
access_token=token["access_token"]
search_parameters = {
"listingType": "Sale",
"locations": [
{
"state": "NSW",
"suburb": "Balgowlah",
"postcode": 2093,
"includeSurroundingSuburbs": True
}
]
}
url = "https://api.domain.com.au/v1/listings/residential/_search"
auth = {"Authorization":"Bearer "+access_token}
request = requests.post(url, data=search_parameters, headers=auth)
details=request.json()
I know my authentication is correct, because i can use the Live API on the website to test the same request (i had to select the client, secret id and the project to allow direct access), and i get a valid access token from the code above.
access_token:
{'access_token': 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX',
'expires_in': 43200,
'token_type': 'Bearer'}
request.json():
{'errors': {'parameters': ['Undefined error.']},
'message': 'The request is invalid.'}
I've been able to implement the notebook from this post. So i can be sure my client and secret ids are connected to the domain project.
#furas had the solution:
look at the example closer :)
The example uses "Content-Type":"text/json" but you use "application/json" instead of "text/json"

Dialogflow Unify Responses cross multiple platforms

Is there any way I can unify the responses in dialgflow across multiple platforms?
I'm building a chatbot where users can interact with using:
Facebook Messenger
Custom API Endpoints
In the dialogflow console, I can specify the response on facebook that is different than the default response
Default Response
Facebook Response
But i do want buttons to appear on both responses. Is there any way to do that?
I do understand that Facebook requires the response to be in a specific format in order to interpret the buttons... and I'm free to set any custom payload in the default response that can be interpreted by the client ( App, website ), but did anyone manage to combine both responses?
If not, what's a good way to set the custom payload? any examples might help.
Note: Webhook calls are enabled for all intents
You can send custom payloads in the JSON format provided in the platforms documentation, it will be rendered on a specific platform accordingly. Below is the format which you need to follow to send custom payload.
{
"facebook": {
},
"kik": {
},
"line": {
},
"skype": {
},
"slack": {
},
"telegram": {
}
"viber": {
}
}
You can also send a custom payload to self-developed integrations. It won’t be processed by Dialogflow, so you'll need to handle it in your own business logic.
Hope it helps.

HTTP Triggering Cloud Function with Cloud Scheduler

I have a problem with a job in the Cloud Scheduler for my cloud function. I created the job with next parameters:
Target: HTTP
URL: my trigger url for cloud function
HTTP method: POST
Body:
{
"expertsender": {
"apiKey": "ExprtSender API key",
"apiAddress": "ExpertSender APIv2 address",
"date": "YYYY-MM-DD",
"entities": [
{
"entity": "Messages"
},
{
"entity": "Activities",
"types":[
"Subscriptions"
]
}
]
},
"bq": {
"project_id": "YOUR GCP PROJECT",
"dataset_id": "YOUR DATASET NAME",
"location": "US"
}
}
The real values has been changed in this body.
When I run this job I got an error. The reason is caused by processing body from POST request.
However, when I take this body and use it as Triggering event in Testing I don't get any errors. So I think, that problem in body representation for my job but I havn't any idea how fix it. I'll be very happy for any idea.
Disclaimer:
I have tried to solve the same issue using NodeJS and I'm able to get a solution
I understand that this is an old question. But I felt like its worth to answer this question as I have spent almost 2 hours figuring out the answer for this issue.
Scenario - 1: Trigger the Cloud Function via Cloud Scheduler
Function fails to read the message in request body.
Scenario - 2: Trigger the Cloud Function via Test tab in Cloud Function interface
Function call always executes fine with no errors.
What did I find?
When the GCF routine is executed via Cloud Scheduler, it sends the header content-type as application/octet-stream. This makes express js unable to parse the data in request body when Cloud scheduler POSTs the data.
But when the exact same request body is used to test the function via the Cloud Function interface, everything works fine because the Testing feature on the interface sends the header content-type as application/json and express js is able to read the request body and parses the data as a JSON object.
Solution
I had to manually parse the request body as JSON (explicitly using if condition based on the content-type header) to get hold of data in the request body.
/**
* Responds to any HTTP request.
*
* #param {!express:Request} req HTTP request context.
* #param {!express:Response} res HTTP response context.
*/
exports.helloWorld = (req, res) => {
let message = req.query.message || req.body.message || 'Hello World!';
console.log('Headers from request: ' + JSON.stringify(req.headers));
let parsedBody;
if(req.header('content-type') === 'application/json') {
console.log('request header content-type is application/json and auto parsing the req body as json');
parsedBody = req.body;
} else {
console.log('request header content-type is NOT application/json and MANUALLY parsing the req body as json');
parsedBody = JSON.parse(req.body);
}
console.log('Message from parsed json body is:' + parsedBody.message);
res.status(200).send(message);
};
It is truly a feature issue which Google has to address and hopefully Google fixes it soon.
Cloud Scheduler - Content Type header issue
Another way to solve the problem is this:
request.get_json(force=True)
It forces the parser to treat the payload as json, ingoring the Mimetype.
Reference to the flask documentation is here
I think this is a bit more concise then the other solutions proposed.
Thank you #Dinesh for pointing towards the request headers as a solution! For all those who still wander and are lost, the code in python 3.7.4:
import json
raw_request_data = request.data
# Luckily it's at least UTF-8 encoded...
string_request_data = raw_request_data.decode("utf-8")
request_json: dict = json.loads(string_request_data)
Totally agree, this is sub-par from a usability perspective. Having the testing utility pass a JSON and the cloud scheduler posting an "application/octet-stream" is incredibly irresponsibly designed.
You should, however, create a request handler, if you want to invoke the function in a different way:
def request_handler(request):
# This works if the request comes in from
# requests.post("cloud-function-etc", json={"key":"value"})
# or if the Cloud Function test was used
request_json = request.get_json()
if request_json:
return request_json
# That's the hard way, i.e. Google Cloud Scheduler sending its JSON payload as octet-stream
if not request_json and request.headers.get("Content-Type") == "application/octet-stream":
raw_request_data = request.data
string_request_data = raw_request_data.decode("utf-8")
request_json: dict = json.loads(string_request_data)
if request_json:
return request_json
# Error code is obviously up to you
else:
return "500"
One of the workarounds that you can use is to provide a header "Content-Type" set to "application/json". You can see a setup here.

Authentication Error with Paypal Sandbox and Google App Engine

I'm having trouble getting the Paypal Adaptive Payments API to work with GAE - I'm specifically going to be using Implicit Payments.
The error returned is that my api credentials are incorrect, but from what i've read I should be suspicious of the header format as well.
Here's the snippet of code - I'm using the urlfetch module in GAE:
headers = {
"X-PAYPAL-USERID" : "xxxx_123456789_biz_api1.xxxx.com",
"X-PAYPAL-SECURITY-PASSWORD" : "1234567890",
"X-PAYPAL-SECURITY-SIGNATURE" : "Ahg-XXXXXXXXXXXXXXXXXXXXXX",
"X-PAYPAL-REQUEST-DATA-FORMAT" : "JSON",
"X-PAYPAL-RESPONSE-DATA-FORMAT" : "JSON",
"X-PAYPAL-APPLICATION-ID" : "APP-80W284485P519543T"
}
request_body = {
"actionType" : "PAY",
"senderEmail" : "xxxx_123456789_biz_api1#xxxx.com",
"receiverList.receiver(0).email" : "xxxx_123456789_per#xxxx.com",
"receiverList.receiver(0).amount" : 100.00,
"currencyCode" : "USD",
"cancelUrl" : "some_url.com",
"returnUrl" : "some_url.com",
"requestEnvelope.errorLanguage" : "en_US"
}
url = "https://svcs.sandbox.paypal.com/AdaptivePayments/Pay"
result = urlfetch.fetch(url=url,payload=request_body,headers=headers)
I've Xed out some values, but everything I'm using is coming from the sandbox "API Credentials" section.
Is there a problem with the header format? Am I using the wrong set of credentials? Can I even use the sandbox to test Implicit Payments?
Any help is much appreciated.
Thanks!
For any of those having similar problems, follow the excellent tutorial located here:
Awesome Paypal Adaptive Payments Tutorial
The headers do tend to cause authentication errors if not formed correctly. I was pretty far off :)
go to your headers, and make a change like this
the key
'X-PAYPAL-USERID'
should become
'X-PAYPAL-SECURITY-USERID'.
You forgot to set the POST method inside the urlfetch.fetch call; without it, the payload data is ignored.
result = urlfetch.fetch(url=url,
payload=request_body,
method=urlfetch.POST,
headers=headers)
The urllib2.Request used in the Tutorial instead switches automatically from GET to POST when the request data is set.
req = urllib2.Request(self.request_url,paypal_request_data,header_data)

Categories