Python Connexion: Automatically validate Accept header - python

I'm using the Connexion framework for my Python Flask project. In the API spec (using the yaml file format) I defined "consumes" and "produces" field like this:
produces:
- application/json
consumes:
- application/json
The Connexion documentanation says that Connexion automatically validates the request based on the API specification, so I thought that it would automatically verify that incoming "Accept" (or "Content-Type") headers would match "application/json" using the above data as example.
However, this doesn't seem to be the case. If I omit the Accept header and Content-Type header, or add them with random values, there are no warnings or errors or anything.
Have other Connexion users gotten Connexion to validate media types data? Or do you handle this explicitly in your code?
EDIT: Seems like this bug report addresses this issue.

I'm using the versions:
connexion == 1.5.3 swagger
spec-validator == 2.4.0
When I execute an operation in this scenario where I wait for "application/json" and send a different Content I get a 415 with the body:
{
"detail": "Invalid Content-type (application/javascript), expected JSON data",
"status": 415,
"title": "Unsupported Media Type",
"type": "about:blank"
}
In this case i sent a request with the Content "application/javascript"

Related

Incorrect value in api/rest-auth/facebook/

I have an issue related to access_token which I've received from a React Native app. The React Native app uses the expo-facebook library and when the pop-up of authentication disappears the token is created and sent to the backend API. The token is created by logInWithReadPermissionsAsync method.
const { type, token, expirationDate, permissions, declinedPermissions, graphDomain } =
await Facebook.logInWithReadPermissionsAsync({
permissions: ["public_profile", "email"],
});
I see that the server received this token on http://localhost:8000/api/rest-auth/facebook/ endpoint and sends it to the Facebook endpoint verify. The problem occurs on the response from Facebook. I expect that it should be valid by Facebook, but it seems that something went wrong.
HTTP 400 Bad Request
Allow: POST, OPTIONS
Content-Type: application/json
Vary: Accept
{
"non_field_errors": [
"Incorrect value."
],
"code": 400,
"message": "Bad Request"
}
An access token that I generate in Graph API Explorer is shorter (when I use it, it works in the backend app) than the token which is generated in the React Native expo app. Why are these two tokens different? And why doesn't it work as I am expecting?
I discovered where the issue was. I knew that the issue is was in the token, a good direction was a response from Facebook.
{"error":{"message":"Invalid appsecret_proof provided in the API argument","type":"GraphMethodException","code":100}}.
After that, I realized that probably something is wrong with React Native Expo. Expo-facebook doesn't react when you even pass the app id, it used the wrong APP ID which was defined in the expo environment(APP_ID=1696089354000816). App-id was set in settings and also in the
await Facebook.initializeAsync({
appId: '<APP_ID>',
});".
So the main issue was that I relied on an access_token that didn't belong to my app.

GitHub : API name/identity inside webhook payload?

I'm writing a Github API client and a webhook.
Is there any way to distinguish if an event (i.e assignment, issue open, etc etc) is trigered by API or by user directly (i.e via git's web ui) ?
I read what payload github will send on it's webhook call, but could not find one.
sincerely
-bino-
I'm not sure what it looks on the server side, but at least when using the UI, the POST payload seems to be form-data, and with API it is JSON-formatted.
From my tests with UI:
...
Content-Disposition: form-data; name="issue[user_assignee_ids][]"
28
------
and from GitHub API documentation:
{
"assignees": [
"hubot",
"other_user"
]
}
This also means that the requests content-type header is different: for form data it is content-type: multipart/form-data; ... and for JSON it should be content-type: application/json.

Sending JWT Get Request containing username/password using python

I have access to an API that I'm trying to start leveraging to automate some tasks and I jumped right into it but was stymied by JWT, which I have never used. I'm also coming off a couple years not using python, so I'm a little rusty. Please bear with me.
Here is a direct quote from the API documentation:
The authentication mode for an organization is with a JSON Web Token. Users
must pass a JSON Web Token (JWT) in the header of each API request made.
To obtain the JWT, send the user’s API key (UUID) and password in a JSON Web
Token GET Request. The authorization method of “Bearer” and a
space is then prefixed to the encoded token string returned. The token will
be tied to the user account that generated the JWT.
I've tried with requests but I'm get 405 errors, I've also installed and imported pyjwt but it's confusing to me. This is essentially what I'm trying to send via python:
POST https://<our endpoint>/v1/token/get HTTP/1.1
Content-Type: application/json
{
"username": "<myUsername>",
"password": "<myPassword>"
I've verified that the target API is working, as there is a small set of functionality that works without JWT and was easily accessed via requests
Advice is welcome, as are any tutorials. I've tried to read several JWT tutorials but I'm having a hard time translating it to python.
Thanks!
Question: To obtain the JWT, send the user’s API key (UUID) and password in a JSON Web Token GET Request
Solution using python_jwt.
Assumptions:
Encoding Method = HS256
claims Fieldname 'consumerId'
claims Fieldname 'httpMethod'
Your JWT in the url looks like:
'http://httpbin.org/get?eyJ0eXAiOiAiSldUIiwgImFsZyI6ICJIUzI1NiJ9... (omitted for brevity)
response.json() contains the requested JWT you have to use afterwards.
Note: Your have to use https://<base url>/v1/token/get
import python_jwt as jwt
# Create claims dictionary for generation of JwToken
claims = {
'consumerId': 'My App ID',
'httpMethod': 'GET'
}
import datetime
# create JWToken
jwtoken = jwt.generate_jwt(claims, 'My secret', 'HS256', datetime.timedelta(minutes=5))
response = requests.get('http://httpbin.org/get', jwtoken)
print(response.json())
Tested with Python:3.4.2 - requests:2.11.1

django-rest-framework accept JSON data?

I have created RESTFul APIs using django-rest-framework. The user endpoint is: /api/v1/users
I want to create a new user, so I send the user data in JSON format:
{
"username": "Test1",
"email": "test1#gmail.com",
"first_name": "Test1",
"last_name": "Test2",
"password":"12121212"
}
I am using Google Chrome extension Postman to test the API. But, after sending the request, the user data is not saving. The response contains this error:
{
"detail": "Unsupported media type \"text/plain;charset=UTF-8\" in request."
}
This is what the request details look like in Postman:
You have missed adding the Content-Type header in the headers section. Just set the Content-Type header to application/json and it should work.
See the below image:
Also, you might also need to include a CSRF token in the header in case you get an error {"detail": "CSRF Failed: CSRF token missing or incorrect."} while making a POST request using Postman. In that case, add an X-CSRFToken header also with value as the CSRF token value.
I'm posting this answer in case someone is facing a problem like mine.
I'm working on a Front-End app using Angular 2 with an API made with Django Rest Framework and I used to send requests with the following headers:
'Content-Type': 'application/json'
And it was working fine until I tried it on Fire Fox and I couldn't load the needed data and I solved it with adding the following headers
'Content-Type': 'application/json',
'Accept': 'application/json'
Here's an explanation, Content-Type tells the server what is the content type of data is while Accept tells it what content type the client side will accpet.
Here's a nice clear answer about this issue:
https://webmasters.stackexchange.com/questions/31212/difference-between-the-accept-and-content-type-http-headers
You need to do two step to done this issue:
Add Content-Type header with application/json value
Add Authorization header with Token {YOUR_CUSTOM_TOKEN} value to pass CSRFToken
Note: if you want to authenticate with session, you don't need to do second step, but if you want use this API for mobile, you have to pass Authorization header to server
I hope it helps
You need to define content type by setting the appropriate headers. In case of Postman you need to set the following values under url field:
Header: "Content-Type"
Value: application/json
I had to add the following to get this to work (I'm using node-fetch btw from the client side to do a POST):
supportHeaderParams: true,
headers: { "Content-Type": "application/json; charset=UTF-8" },
Couple of things to do if you want to accept JSON Data using Django Rest Framework.
Make sure application/json headers are sent:
'Content-Type: application/json'
JSON Parser is selected in settings.py
REST_FRAMEWORK = {
'DEFAULT_PARSER_CLASSES': [
'rest_framework.parsers.JSONParser',
],
}

Errors loading JSON with Flask and Angular

I've solved my issue, but I'd like to know what was going wrong so I can address it in the future. I'm having issues decoding incoming JSON for use in my Flask application.
The code that sends it in Angular:
$http.post("/login", JSON.stringify($scope.loginForm))
.success(function(data, status, headers, config) {
console.log(data);
})
.error(function(data, status, headers, config) {
console.log("Submitting form failed!");
});
Important to note that the request type is set to application/json earlier up, with
$http.defaults.headers.post["Content-Type"] = "application/json";
The code that receives it within Flask:
data = request.get_json()
email_address = data.get("email_address")
password = data.get("password")
Attempting to load it this way returns an error 400, but any other way leads to some very strange issues. For example:
return json.dumps(request.get_json())
Will log {"password": "password", "email_address": "email#email.com"} in the console, but attempting to do this:
data = request.get_json()
email_address = data.get("email_address")
password = data.get("password")
With no difference whatsoever between this and the first block of code except that I'm not forcing it, I receive the exception "ValueError: need more than 1 value to unpack". Which implies that there aren't two values to unpack.
HOWEVER, they both work individually. If I do the above request and omit either of the data.get() lines above, the other will work.
What about my setup causes my JSON object to disintegrate the first time it's accessed?
I got around this by using request.json instead of request.get_json() but as request.json is being deprecated it's fairly important I know how to solve this in the future. Any pointers would be appreciated!
You can omit JSON.stringify and pass object directly to $http.post() method because angular will serialize it to JSON automatically it formData is object. So I assume that JSON.stringify will force angular to send is as x-www-form-urlencoded instead of application/json media type.
See default transformations section: angular $http service documentation

Categories

Resources