Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python Requests - authentication after redirect

I have a quick question regarding HTTP Basic Authentication after a redirect.

I am trying to login to a website which, for operational reasons, immediately redirects me to a central login site using an HTTP 302 response. In my testing, it appears that the Requests module does not send my credentials to the central login site after the redirect. As seen in the code snippet below, I am forced to extract the redirect URL from the response object and attempt the login again.

My question is simply this:
is there a way to force Requests to re-send login credentials after a redirect off-host?

For portability reasons, I would prefer not to use a .netrc file. Also, the provider of the website has made url_login static but has made no such claim about url_redirect.

Thanks for your time!

CODE SNIPPET

import requests

url_login = '<url_login>'
myauth = ('<username>', '<password')

login1 = requests.request('get', url_login, auth=myauth)
# this login fails; response object contains the login form information

url_redirect = login1.url
login2 = requests.request('get', url_redirect, auth=myauth)
# this login succeeds; response object contains a welcome message

UPDATE

Here is a more specific version of the general code above.

  • The first request() returns an HTTP 200 response and has the form information in its text field.
  • The second request() returns an HTTP 401 response with 'HTTP Basic: Access denied.' in its text field.

(Of course, the login succeeds when provided with valid credentials.)

Again, I am wondering whether I can achieve my desired login with only one call to requests.request().

import requests

url_login = 'http://cddis-basin.gsfc.nasa.gov/CDDIS_FileUpload/login' 
myauth = ('<username>', '<password>') 

with requests.session() as s: 
    login1 = s.request('get', url_login, auth=myauth) 
    url_earthdata = login1.url 
    login2 = s.request('get', url_earthdata, auth=myauth)
like image 908
Adam Vigneron Avatar asked Jun 21 '16 12:06

Adam Vigneron


2 Answers

My solution to this would be use of "Session". Here is how you can implement Session.

import requests

s = requests.session()
url_login = "<loginUrl>"

payload = {
    "username": "<user>",
    "password": "<pass>"
}

req1 = s.post(url_login, data=payload)

# Now to make sure you do not get the "Access denied", use the same session variable for the request.

req2 = s.get(url_earthdata)

This should solve your problem.

like image 58
supersigdel Avatar answered Oct 19 '22 19:10

supersigdel


This isn't possible with Requests, by design. The issue stems from a security vulnerability, where if an attacker modifies the redirect URL and the credentials are automatically sent to the redirect URL, then the credentials are compromised. So, credentials are stripped from redirect calls.

There's a thread about this on github: https://github.com/psf/requests/issues/2949

like image 2
tag_this Avatar answered Oct 19 '22 18:10

tag_this