Skip to content

Commit d27d75d

Browse files
seowalexaiudirog
andauthored
Use SPNEGO mechanism by default (#47)
Co-authored-by: Roger Aiudi <aiudirog@gmail.com>
1 parent 2c04c64 commit d27d75d

File tree

5 files changed

+29
-12
lines changed

5 files changed

+29
-12
lines changed

HISTORY.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ History
44
FUTURE: TBD
55
-----------
66
- Update HISTORY.rst to reflect previous releases made on GitHub
7+
- Use SPNEGO mechanism by default
78

89
0.4.0: 2024-11-28
910
-----------------

README.rst

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -171,21 +171,22 @@ applicable). However, an explicit credential can be in instead, if desired.
171171
Explicit Mechanism
172172
------------------
173173

174-
``HTTPSPNEGOAuth`` normally lets the underlying ``gssapi`` library decide which
175-
negotiation mechanism to use. However, an explicit mechanism can be used instead
176-
if desired. The ``mech`` parameter will be passed straight through to ``gssapi``
177-
without interference. It is expected to be an instance of ``gssapi.mechs.Mechanism``.
174+
``HTTPSPNEGOAuth`` normally lets SPNEGO decide which negotiation mechanism to use.
175+
However, an explicit mechanism can be used instead if desired. The ``mech``
176+
parameter will be passed straight through to ``gssapi`` without interference.
177+
It is expected to be an instance of ``gssapi.Mechanism``, ``gssapi.OID``, or
178+
raw bytes.
178179

179180
.. code-block:: python
180181
181182
>>> import gssapi
182183
>>> import httpx
183184
>>> from httpx_gssapi import HTTPSPNEGOAuth
184185
>>> try:
185-
... spnego = gssapi,mechs.Mechanism.from_sasl_name("SPNEGO")
186+
... krb5 = gssapi.mechs.Mechanism.from_sasl_name("GS2-KRB5")
186187
... except AttributeError:
187-
... spnego = gssapi.OID.from_int_seq("1.3.6.1.5.5.2")
188-
>>> gssapi_auth = HTTPSPNEGOAuth(mech=spnego)
188+
... krb5 = gssapi.OID.from_int_seq("1.2.840.113554.1.2.2")
189+
>>> gssapi_auth = HTTPSPNEGOAuth(mech=krb5)
189190
>>> r = httpx.get("http://example.org", auth=gssapi_auth)
190191
...
191192

httpx_gssapi/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
__all__ = (
1717
'HTTPSPNEGOAuth',
1818
'MutualAuthenticationError',
19+
'SPNEGO',
1920
'REQUIRED',
2021
'OPTIONAL',
2122
'DISABLED',
@@ -24,7 +25,7 @@
2425
import os
2526
import logging
2627

27-
from .gssapi_ import HTTPSPNEGOAuth, REQUIRED, OPTIONAL, DISABLED
28+
from .gssapi_ import HTTPSPNEGOAuth, SPNEGO, REQUIRED, OPTIONAL, DISABLED
2829
from .exceptions import MutualAuthenticationError
2930

3031
from ._version import get_versions

httpx_gssapi/gssapi_.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import logging
33
from itertools import chain
44
from functools import wraps
5-
from typing import Generator, Optional, List, Any
5+
from typing import Generator, Optional, List, Any, Union
66

77
from base64 import b64encode, b64decode
88

@@ -33,6 +33,9 @@
3333
OPTIONAL = 2
3434
DISABLED = 3
3535

36+
# OID for the SPNEGO mechanism
37+
SPNEGO = gssapi.OID.from_int_seq("1.3.6.1.5.5.2")
38+
3639
_find_auth = re.compile(r'Negotiate\s*([^,]*)', re.I).search
3740

3841

@@ -125,7 +128,9 @@ class HTTPSPNEGOAuth(Auth):
125128
Default is `None`.
126129
127130
`mech` is GSSAPI Mechanism (gssapi.Mechanism) to use for negotiation.
128-
Default is `None`
131+
If explicitly given as ``None``, the underlying ``gssapi`` library will
132+
decide which negotiation mechanism to use.
133+
Default is `SPNEGO`.
129134
130135
`sanitize_mutual_error_response` controls whether we should clean up
131136
server responses. See the `SanitizedResponse` class.
@@ -138,7 +143,7 @@ def __init__(self,
138143
delegate: bool = False,
139144
opportunistic_auth: bool = False,
140145
creds: gssapi.Credentials = None,
141-
mech: bytes = None,
146+
mech: Optional[Union[bytes, gssapi.OID]] = SPNEGO,
142147
sanitize_mutual_error_response: bool = True):
143148
self.mutual_authentication = mutual_authentication
144149
self.target_name = target_name

tests/test_mocked.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ def null_response(status=200, request=null_request(), **kwargs):
8282
def check_init(**kwargs):
8383
kwargs.setdefault('name', gssapi_name("HTTP@www.example.org"))
8484
kwargs.setdefault('creds', None)
85-
kwargs.setdefault('mech', None)
85+
kwargs.setdefault('mech', gssapi.OID.from_int_seq("1.3.6.1.5.5.2"))
8686
kwargs.setdefault('flags', gssflags)
8787
kwargs.setdefault('usage', "initiate")
8888
fake_init.assert_called_with(**kwargs)
@@ -397,5 +397,14 @@ def test_target_name(patched_ctx):
397397
fake_resp.assert_called_with(b"token")
398398

399399

400+
def test_os_default_mech(patched_ctx):
401+
resp = null_response(headers=neg_token)
402+
auth = httpx_gssapi.HTTPSPNEGOAuth(mech=None)
403+
auth.set_auth_header(resp.request, resp)
404+
assert resp.request.headers['Authorization'] == b64_negotiate_response
405+
check_init(mech=None)
406+
fake_resp.assert_called_with(b"token")
407+
408+
400409
if __name__ == '__main__':
401410
pytest.main()

0 commit comments

Comments
 (0)