Using python's requests post call with verify=True - python-3.x

I am using python's request to make a post call like below -
response = requests.post(ENDPOINT, data=json.dumps(data), \
headers=headers, proxies=getProxy(), verify=True)
What does this 'verify=True' actually verify internally with respect to the certificate? what all information it verifies - whether it includes common name as part of verification?
Is there any other ways in python this verification can be done?
thanks for your replies

Related

How to configure or set cookie as json before making a post request in locust load test tool for FastHTTPUser

Locust is having option to use HTTPUser and FastHTTPUser
HTTPUSer internally using python requests which accepts cookies as an argument with json content
e.g. self.client.get(url, header=myheader, cookies=mycookies) here I can configure mycookies as json. Same is not working if I change the code to FastHTTPUser instead of HTTPUser. Need details how to configure hardcoded cookies as key value before making the request in FastHTTPUser approach.
I don't see why you have received downvotes for your question. I found it valid and I think you should create an issue in the locust github page:
https://github.com/locustio/locust/issues/
I think you could solve it like this:
from requests.cookies import cookiejar_from_dict
#task
def task_cookie(self):
cookiejar_from_dict(mycookies, self.client.cookiejar)
self.client.get(url, header=myheader)
I will try to make a PR to make this automatic

How to accept a Github repository invitation through API?

I was looking at the Github API and it allows you to fetch all repository invites through an API endpoint (see https://developer.github.com/v3/repos/invitations/#list-invitations-for-a-repository). This works fine like this:
from requests.auth import HTTPBasicAuth
import requests
login = 'xxx'
password = 'yyy'
url = 'https://api.github.com/user/repository_invitations'
repository_invites = requests.get(
url, auth=HTTPBasicAuth(login, password)).json()
print('response: ' + str(repository_invites))
I can then get out each request its url like this:
for repository_invite in repository_invites:
print('url: ' + repository_invite.get('url'))
Which gives something back like:
url: https://api.github.com/user/repository_invitations/123456789
Github also mentions that you can accept an invite at https://developer.github.com/v3/repos/invitations/#accept-a-repository-invitation which mentions
PATCH /user/repository_invitations/:invitation_id
What I don't get is how I can tell Github how to accept it though. This endpoint seems to be used for both deleting and accepting an invitation. Github talks about PATCH at https://developer.github.com/v3/#http-verbs which mentions you can use either a POST or send a PATCH request, however not how. So the question is, how do I know what I should send in the PATCH call? I tried this for example:
result = requests.patch(repository_invite.get('url'), json.dumps({'accept': True}))
print('result: ' + str(result.json()))
Which gives back:
result: {'message': 'Invalid request.\n\n"accept" is not a permitted key.', 'documentation_url': 'https://developer.github.com/v3'}
In order to call the API endpoint you will need to have authentication with your Github user and you need to send a Patch call (which can take data/headers if you would need them). Here's a working sample:
for repository_invite in repository_invites:
repository_id = repository_invite.get('id')
accept_invite = requests.patch('https://api.github.com/user/repository_invitations/'+ str(repository_id),
data={}, headers={},
auth=HTTPBasicAuth(github_username, github_password))
Without the authentication the Patch call will give back a 404 response code because it is only accessible behind a login for obvious safety purpose. If you call the endpoint user/repository_invitations/ followed by the ID Github will automatically accept the invitation.

PRIVACY Card API Authorization

I have recently been working with API's but I am stuck on one thing and it's been holding me back for a few days.
I am trying to work with Privacy's API and I do not understand the Authentication/Authorization process. When I enter the url in a browser I get the error "message": "Please provide API key in Authorization header", even when I use the correct format of Authorization. I also get an error when I make a request in Python. The format I'm using for the url is https://api.privacy.com/v1/card "Authorization: api-key:".
If someone could explain how to work this or simply give an example of how I would make a request through Python3. The API information is in the link below.
Thank you in advance.
https://developer.privacy.com/docs
This is the code I am using in Python. After I run this I receive a 401 status code.
import requests
headers={'Authorization': 'api-key:200e6036-6894-xxxx-xxxx-xxxx'}
url = 'https://api.privacy.com/v1/card'
r = requests.get(url)
print("Status code:", r.status_code)
You need to add the authentication header to the get call. It isn't enough to include it in a header variable. You need to provide those headers to requests
import requests
response = requests.get('https://api.privacy.com/v1/card', headers={'Authorization': 'api-key 65a9566c-XXXXXXXXXXXX'})
print(response.json())

JWT Token auth using python requests for DockerHub

I found out that editing a full_description of a DockerHub repository can be done via a JavaScript API, and figured this would be a fun excuse to learn the requests package for python. The JavaScript API definitely works, e.g. using this simple docker image.
The JS API basically does
Send a POST request to https://hub.docker.com/v2/users/login with the username and password. The server responds with a token.
Send a PATCH request to the specific https://hub.docker.com/v2/repositories/{user or org}/{repo}, making sure the header has Authorization: JWT {token}, and in this case with content body of {"full_description":"...value..."}.
What is troubling is that the PATCH request on the python side gets a 200 response back from the server (if you intentionally set a bad auth token, you get denied as expected). But it's response actually contains the current information (not the patched info).
The only "discoveries" I've made:
If you add the debug logging stuff, there's a 301. But this is the same URL for the javascript side, so it doesn't matter?
send: b'{"full_description": "TEST"}'
reply: 'HTTP/1.1 301 MOVED PERMANENTLY\r\n'
The token received by doing a POST in requests is the same as if I GET to auth.docker.io as decribed in Getting a Bearer Token section here. Notably, I didn't specify a password (just did curl -X GET ...). This is not true. They are different, I don't know how I thought they were the same.
This second one makes me feel like I'm missing a step. Like I need to decode the token or something? I don't know what else to make of this, especially the 200 response from the PATCH despite no changes.
The code:
import json
from textwrap import indent
import requests
if __name__ == "__main__":
username = "<< SET THIS VALUE >>"
password = "<< SET THIS VALUE >>"
repo = "<< SET THIS VALUE >>"
base_url = "https://hub.docker.com/v2"
login_url = f"{base_url}/users/login"
repo_url = f"{base_url}/repositories/{username}/{repo}"
# NOTE: if I use a `with requests.Session()`, then I'll get
# CSRF Failed: CSRF token missing or incorrect
# Because I think that csrftoken is only valid for login page (?)
# Get login token and create authorization header
print("==> Logging into DockerHub")
tok_req = requests.post(login_url, json={"username": username, "password": password})
token = tok_req.json()["token"]
headers = {"Authorization": f"JWT {token}"}
print(f"==> Sending PATCH request to {repo_url}")
payload = {"full_description": "TEST"}
patch_req = requests.patch(repo_url, headers=headers, json=payload)
print(f" Response (status code: {patch_req.status_code}):")
print(indent(json.dumps(patch_req.json(), indent=2), " "))
Additional information related to your CSRF problem when using requests.Session():
It seems that Docker Hub is not recognizing csrftoken named header/cookie (default name of the coming cookie), when making requests in this case.
Instead, when using header X-CSRFToken on the following requests, CSRF is identified as valid.
Maybe reason is cookie-to-header token pattern.
Once updating session header with cookie of login response
s.headers.update({"X-CSRFToken": s.cookies.get("csrftoken")})
There is no need to set JWT token manually anymore for further requests - token works as cookie already.
Sorry, no enough privileges to just comment, but I think this is relevant enough.
As it turns out the JWT {token} auth was valid the entire time. Apparently, you need a / at the end of the URL. Without it, nothing happens. LOL!
# ----------------------------------------------------V
repo_url = f"{base_url}/repositories/{username}/{repo}/"
As expected, the PATCH then responds with the updated description, not the old description. WOOOOT!
Important note: this is working for me as of January 15th 2020, but in my quest I came across this dockerhub issue that seems to indicate that if you have 2FA enabled on your account, you can no longer edit the description using a PATCH request. I don't have 2FA on my account, so I can (apparently). It's unclear what the future of that will be.
Related note: the JWT token has remained the same the entire time, so for any web novices like myself, don't share those ;)

Unicode-objects must be encoded before hashing when requesting data using Flask-OAuth

I'm integrating Google's login with a Flask site using Flask-OAuth.
Everything is working fine. I can authorise the login and get a token back etc without any difficulties. But when I use Flask-OAuth's get method to request the logged in user's email address I get an error saying:
TypeError: Unicode-objects must be encoded before hashing
I'm using Python3 and this has the smell of a Python version issue but I can't figure out what I'd need to change.
The code I'm using is this:
def get_additional_data(self):
access_token = session.get('oauth_token')
headers = {'Authorization': 'OAuth ' + access_token[0]}
return self.service.get(
'https://www.googleapis.com/oauth2/v1/userinfo', None,
headers=headers)
I'm not sure what I can encode in that request. Even if I don't pass the headers I get the same error (rather than an invalid request or something like that).
I've run 2to3 on oauth2/__init__.py and the tweaks is suggests are very minor and shouldn't prevent the code from running in Python 3. Also, everything else OAuth2 related is working.
The bad news is that the solution to this problem is switching to Flask-OAuthlib.
The good news is it required very few changes from Flask-OAuth to get it working.

Resources