Im trying to access a SAS service on my company's intranet through python using requests but I cant get it to work due to authentication failure (401).
Im using python 3.7.4, requests 2.22.0 on Windows 10. So far I have tried/checked:
requests.get(follow_redirects=True)
HTTPBasicAuth('user', 'pass')
, HTTPDigestAuth()
, HttpNtlmAuth('user', 'pass')
requests_kerberos.HTTPKerberosAuth()
with all possible parameter combinations, including setting force_preemptive=True
flag and principal=user@REALM
. I have confirmed with klist
that multiple tickets do exist.requests_gssapi.HTTPSPNEGOAuth()
.curl -i -L -v --negotiate --user "domain\user:pswd" <protected_service_url>
in git bash, does authenticate.www-authenticate: Negotiate
challenge, respond with authentication ticket.Chrome request
[truncated]Authorization: Negotiate YIIIsgYGKwYBBQUCoIIIpjCC...
GSS-API Generic Security Service Application Program Interface
OID: 1.3.6.1.5.5.2 (SPNEGO - Simple Protected Negotiation)
Simple Protected Negotiation
negTokenInit
mechTypes: 4 items
mechToken: 6082086406092a864886f71201020201006e820853308208…
krb5_blob: 6082086406092a864886f71201020201006e820853308208…
KRB5 OID: 1.2.840.113554.1.2.2 (KRB5 - Kerberos 5)
krb5_tok_id: KRB5_AP_REQ (0x0001)
Kerberos
=> Chrome response status
HTTP/1.1 302 Found
The browser then proceeds to automatically redirect to the service.
And here is the requests_gssapi.HTTPSPNEGOAuth()
unsuccesful request:
[truncated]Authorization: Negotiate YIIHQQYJKoZIhvcSAQICAQBuggcw...
GSS-API Generic Security Service Application Program Interface
OID: 1.2.840.113554.1.2.2 (KRB5 - Kerberos 5)
krb5_blob: 01006e8207303082072ca003020105a10302010ea2070305…
krb5_tok_id: KRB5_AP_REQ (0x0001)
Kerberos
=> response status
HTTP/1.1 401 Unauthorized (text/html)
My testing code now is:
# 302 response is already handled by the first GET
r1 = session.get(url)
if r1.status_code != 401:
print("Error! Server authorization failed at step 2. Expected response 401 but instead got: " + str(r1.status_code))
return None
auth_url = r1.url
# step 2: server sends 401 and WWW-Authenticate: Negotiate header
# GSS-API (SPNEGO - Simple Protected Negotiation)
r2 = session.get(auth_url, auth=HTTPSPNEGOAuth(mutual_authentication=True))
Using the requests-gssapi library got me the closest but still authentication fails. I do not understand why. The Kerberos tickets used are the same. The only difference that I can see between the successful Chrome request and the failed python request is the OID
. However I do not know how I can change that as it seems to be a library implementation detail.
Any help is appreciated.
I managed to solve this. So for anyone facing a similar issue, here are my steps:
import gssapi
import requests
from requests_gssapi import HTTPSPNEGOAuth
try:
spnego = gssapi.mechs.Mechanism.from_sasl_name("SPNEGO")
except AttributeError:
spnego = gssapi.OID.from_int_seq("1.3.6.1.5.5.2")
gssapi_auth = HTTPSPNEGOAuth(mech=spnego)
r = requests.get("http://example.org", auth=gssapi_auth)
And done!