ReqNtlm
Req plugin for HTTP NTLM authentication.
NTLM ("NTLMSSP") is a challenge/response authentication protocol used by Windows-based servers (IIS, Exchange, internal corporate services, ...). Unlike Basic or Bearer authentication, it is a connection-oriented three-way handshake:
- the client sends a
NEGOTIATE_MESSAGE, - the server replies
401with aCHALLENGE_MESSAGE, - the client resends the request with an
AUTHENTICATE_MESSAGEcomputed from the challenge and the user's credentials (NTLMv2).
ReqNtlm implements this purely as a request step (sets the authorization
header for the current leg) and a response step (reacts to a 401 NTLM
challenge by resending the request). It does not ship its own HTTP
adapter — whichever adapter the request already uses (Req.Finch by
default, or anything else configured via Req.new(adapter: ...)) keeps
being used.
This means NTLM's requirement that all legs of the handshake share the same
TCP connection is only as good as that adapter's connection reuse for two
requests issued back-to-back to the same host. For Req.Finch, that is
generally the case for sequential (non-concurrent) requests against the same
{scheme, host, port}, but it's not a hard guarantee. If you need stronger
guarantees (e.g. under concurrent load), configure the adapter's connection
pool accordingly for the affected host (see Req.Finch options).
Usage
Mix.install([
{:req, "~> 0.5"},
{:req_ntlm, "~> 0.1.0"}
])
req = Req.new() |> ReqNtlm.attach()
Req.get!(req,
url: "http://intranet.example.com/private",
ntlm: [username: "bob", password: "secret", domain: "CORP"]
)
The username may also be given in "DOMAIN\user" form, in which case
:domain can be omitted:
Req.get!(req,
url: "http://intranet.example.com/private",
ntlm: [username: "CORP\bob", password: "secret"]
)
A {username, password} tuple is accepted as a shortcut too:
Req.get!(req, url: "...", ntlm: {"CORP\bob", "secret"})
Request Options
:ntlm- credentials used to perform the NTLM handshake. One of:- a
{username, password}tuple, - a keyword list or map with
:username,:password, and optionally:domainand:workstation(defaults to"").
When this option is not set,
ReqNtlmdoes not interfere with the request at all.- a
Limitations
- Only NTLMv2 is implemented (there is no NTLMv1 downgrade).
- As explained above, the handshake relies on the configured adapter reusing
the same connection across the two requests it takes; it is not pinned to
a single socket by
ReqNtlmitself. - Message confidentiality/integrity (NTLM signing/sealing) and session key
exchange are not implemented — only the authentication handshake itself,
which is what's needed to get past a
401challenge.
Installation
def deps do
[
{:req_ntlm, "~> 0.1.0"}
]
end
Documentation can be generated with ExDoc and published on HexDocs. Once published, the docs can be found at https://hexdocs.pm/req_ntlm.
Authorship
This library was written by Claude (Anthropic).