pythongssapi / requests-gssapi

An authentication handler for using GSSAPI with Python Requests. Drop-in replacement for old requests-kerberos.
Other
32 stars 21 forks source link

Redirects cause mutual authentication to fail #12

Closed bewing closed 4 years ago

bewing commented 5 years ago

If you have a server that issues a redirect, to another page (Eg, Gitlab EE has a specific page to handle authenticating Kerberos and creating a session), requests-gssapi will attempt to authenticate both the original 302, and the page that is returned. This will either cause a failure because the context is already complete, or a failure because the second page doesn't process the challenge and return another token.

This appears to be related to requests/requests-kerberos#64

import logging

import requests_gssapi

logger = logging.getLogger(__name__)

logging.basicConfig(level=logging.DEBUG)

r = requests.get(
    "http://localhost.localdomain/auth/spnego",
    auth=requests_gssapi.HTTPSPNego(),
    verify=False)
DEBUG:urllib3.connectionpool:Starting new HTTP connection (1): localhost.localdomain:80
DEBUG:urllib3.connectionpool:http://localhost.localdomain:80 "GET /auth/spnego HTTP/1.1" 401 1524
DEBUG:requests_gssapi.gssapi_:handle_401(): Handling: 401
DEBUG:requests_gssapi.gssapi_:authenticate_user(): Authorization header: Negotiate <redacted>
DEBUG:urllib3.connectionpool:http://localhost.localdomain:80 "GET /auth/spnego HTTP/1.1" 302 0
DEBUG:requests_gssapi.gssapi_:authenticate_user(): returning <Response [302]>
DEBUG:requests_gssapi.gssapi_:handle_401(): returning <Response [302]>
DEBUG:requests_gssapi.gssapi_:handle_response(): returning <Response [302]>
DEBUG:requests_gssapi.gssapi_:handle_response() has seen 0 401 responses
DEBUG:requests_gssapi.gssapi_:handle_other(): Handling: 302
DEBUG:requests_gssapi.gssapi_:handle_other(): Authenticating the server
DEBUG:requests_gssapi.gssapi_:authenticate_server(): Authenticate header: <redacted>
DEBUG:requests_gssapi.gssapi_:authenticate_server(): returning <Response [302]>
DEBUG:requests_gssapi.gssapi_:handle_other(): returning <Response [302]>
DEBUG:requests_gssapi.gssapi_:handle_response(): returning <Response [302]>
DEBUG:urllib3.connectionpool:http://localhost.localdomain:80 "GET /admin/ HTTP/1.1" 302 226
DEBUG:requests_gssapi.gssapi_:handle_other(): Handling: 302
ERROR:requests_gssapi.gssapi_:handle_other(): Mutual authentication failed
Traceback (most recent call last):
  File "/home/bewing/.PyCharm2018.2/config/scratches/scratch_4.py", line 14, in <module>
    verify=False)
  File "/home/bewing/.pyenv/versions/3.6.6/envs/requests-gssapi/lib/python3.6/site-packages/requests/api.py", line 75, in get
    return request('get', url, params=params, **kwargs)
  File "/home/bewing/.pyenv/versions/3.6.6/envs/requests-gssapi/lib/python3.6/site-packages/requests/api.py", line 60, in request
    return session.request(method=method, url=url, **kwargs)
  File "/home/bewing/.pyenv/versions/3.6.6/envs/requests-gssapi/lib/python3.6/site-packages/requests/sessions.py", line 533, in request
    resp = self.send(prep, **send_kwargs)
  File "/home/bewing/.pyenv/versions/3.6.6/envs/requests-gssapi/lib/python3.6/site-packages/requests/sessions.py", line 668, in send
    history = [resp for resp in gen] if allow_redirects else []
  File "/home/bewing/.pyenv/versions/3.6.6/envs/requests-gssapi/lib/python3.6/site-packages/requests/sessions.py", line 668, in <listcomp>
    history = [resp for resp in gen] if allow_redirects else []
  File "/home/bewing/.pyenv/versions/3.6.6/envs/requests-gssapi/lib/python3.6/site-packages/requests/sessions.py", line 247, in resolve_redirects
    **adapter_kwargs
  File "/home/bewing/.pyenv/versions/3.6.6/envs/requests-gssapi/lib/python3.6/site-packages/requests/sessions.py", line 653, in send
    r = dispatch_hook('response', hooks, r, **kwargs)
  File "/home/bewing/.pyenv/versions/3.6.6/envs/requests-gssapi/lib/python3.6/site-packages/requests/hooks.py", line 31, in dispatch_hook
    _hook_data = hook(hook_data, **kwargs)
  File "/home/bewing/.pyenv/versions/3.6.6/envs/requests-gssapi/lib/python3.6/site-packages/requests_gssapi/gssapi_.py", line 288, in handle_response
    _r = self.handle_other(response)
  File "/home/bewing/.pyenv/versions/3.6.6/envs/requests-gssapi/lib/python3.6/site-packages/requests_gssapi/gssapi_.py", line 240, in handle_other
    "Unable to authenticate {0}".format(response))
requests_gssapi.exceptions.MutualAuthenticationError: Unable to authenticate <Response [302]>

Process finished with exit code 1
frozencemetery commented 5 years ago

Analysis conducted by the requests-kerberos folks suggests this is inherent in the requests model. Unfortunately I'm not aware of anything that makes our codebase different in this regard.

It's probably best to turn off mutual authentication here. This shouldn't be any risk if you're over TLS already.

frozencemetery commented 4 years ago

Closing since mutual auth is disabled by default now, and I can't do anything else about it.