Python, Https Get with Basic Authentication

Python, HTTPS GET with basic authentication

In Python 3 the following will work. I am using the lower level http.client from the standard library. Also check out section 2 of rfc2617 for details of basic authorization. This code won't check the certificate is valid, but will set up a https connection. See the http.client docs on how to do that.

from http.client import HTTPSConnection
from base64 import b64encode

# Authorization token: we need to base 64 encode it
# and then decode it to acsii as python 3 stores it as a byte string
def basic_auth(username, password):
token = b64encode(f"{username}:{password}".encode('utf-8')).decode("ascii")
return f'Basic {token}'

username = "user_name"
password = "password"

#This sets up the https connection
c = HTTPSConnection("www.google.com")
#then connect
headers = { 'Authorization' : basic_auth(username, password) }
c.request('GET', '/', headers=headers)
#get the response back
res = c.getresponse()
# at this point you could check the status etc
# this gets the page text
data = res.read()

How do I use basic HTTP authentication with the python Requests library?

You need to use a session object and send the authentication each request. The session will also track cookies for you:

session = requests.Session()
session.auth = (user, password)

auth = session.post('http://' + hostname)
response = session.get('http://' + hostname + '/rest/applications')

use headers and basic authentication in python requests

In general: yes, it seems alright.

But some notes/fixes/hints:

  1. BasicAuth can be used as just tuple, so auth=(username, password) is enough - docs say that BasicAuth is common that it they made it a shorthand

  2. When you do any request, you should save its result to know whether it was successful or nor and diagnose it. Usually r = requests.post(...) is enough. You can then either manually check r.status_code (and examine r.content) or do r.raise_for_status() to just get an error for 4xx and 5xx codes.

    r.raise_for_status() will raise an error only based on the code itself and what it seems. But sometimes r.content might provide info on what actually broke - e.g. "400 bad request", while response might have in its content what field is missing).

  3. As for json headers and data=data... another shorthand. data= requires you to pass data in a form that you want it to be sent directly. But requests lib knows that a lot of times we want to send json data, so they implemented a json= arguments - which takes care of converting your dict/list structure to json for you and sets the content-type header as well!

So in your case:

data = {"example": "data"}
r = requests.post(URL, # save the result to examine later
auth=(username, password), # you can pass this without constructor
json=data) # no need to json.dumps or add the header manually!

How to confirm user/pass for http authorization?

Here is a working example of what you need.

tl;dr: as pointed out in comments, with sockets you are working at the transport level. The HTTP Basic Auth lies at a higher level in the TCP/IP (or OSI) stack. If you do not want to embrace the HTTP protocol (do you?), you need to process requests and headers manually, mimicking the HTTP protocol. Indeed, python requests manages full-fledged HTTP requests.

I slightly modified your code to parse http headers and to manage a HTTP-like auth. There you go (comments and explanation in the code):

import socket, base64
from http.server import BaseHTTPRequestHandler
from io import BytesIO

serverSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
serverPort = 8080
serverSocket.bind(("127.0.0.1", serverPort))
serverSocket.listen(1)

# Auth section
user = 'user'
password = 'pass'
# The token you want the client to provide (string)
server_token = base64.b64encode(bytes(f'{user}:{password}','utf-8')).decode('utf-8')

# Use this simple class to parse you HTTP headers
# Read more here: https://stackoverflow.com/a/5955949/4820341
class HTTPRequest(BaseHTTPRequestHandler):
def __init__(self, request_text):
self.rfile = BytesIO(request_text)
self.raw_requestline = self.rfile.readline()
self.error_code = self.error_message = None
self.parse_request()

def send_error(self, code, message):
self.error_code = code
self.error_message = message

while True:
print('Ready to serve...')

connectionSocket, addr = serverSocket.accept()

data = connectionSocket.recv(1024)

# Those are your data coming from the client
print(data.decode('utf-8'))

# parse your headers
http_headers = HTTPRequest(data)

try:

# get the incoming auth token
client_token = http_headers.headers['Authorization'].strip('Basic ')

if server_token != client_token:
connectionSocket.sendall(bytes("HTTP/1.1 401 Unauthorized\n\n" + 'Wrong credetials', 'utf-8'))
else:
# process the request and do your stuff here
connectionSocket.sendall(bytes("HTTP/1.1 200 OK\n\n" + 'Ok, all is fine here', 'utf-8'))

except AttributeError:
connectionSocket.sendall(bytes("HTTP/1.1 401 Unauthorized\n\n" + 'No credentials provided', 'utf-8'))

finally:
connectionSocket.close()

Here is how a requests.get with auth looks like server side:

Ready to serve...
GET / HTTP/1.1
Host: 127.0.0.1:8080
User-Agent: python-requests/2.26.0
Accept-Encoding: gzip, deflate
Accept: */*
Connection: keep-alive
Authorization: Basic dXNlcjpwYXNz

And now, let's see it in action:

>>> r = requests.get('http://127.0.0.1:8080',auth = HTTPBasicAuth('user', 'pass'))
>>> r.status_code
200
>>> r.text
'Ok, all is fine here'
>>>
>>>
>>> r = requests.get('http://127.0.0.1:8080',auth = HTTPBasicAuth('user', 'wrongpass'))
>>> r.status_code
401
>>> r.text
'wrong credentials'
>>>
>>>
>>> r = requests.get('http://127.0.0.1:8080')
>>> r.status_code
401
>>> r.text
'No credentials provided'

Python requests library: HTTP basic authentication for each request

Use Session(). Documentation states:

The Session object allows you to persist certain parameters across
requests.

import requests

s = requests.Session()
s.auth = (username, password)
s.verify = ssl_ca_file

s.get(base_url)


Related Topics



Leave a reply



Submit