Packages

Req plugin for HTTP NTLM authentication

Current section

Files

Jump to
req_ntlm README.md
Raw

README.md

# ReqNtlm
[`Req`](https://github.com/wojtekmach/req) plugin for HTTP NTLM authentication.
<!-- MDOC !-->
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:
1. the client sends a `NEGOTIATE_MESSAGE`,
2. the server replies `401` with a `CHALLENGE_MESSAGE`,
3. the client resends the request with an `AUTHENTICATE_MESSAGE` computed
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
```elixir
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:
```elixir
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:
```elixir
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
`:domain` and `:workstation` (defaults to `""`).
When this option is not set, `ReqNtlm` does not interfere with the request
at all.
## 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 `ReqNtlm` itself.
- 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 `401` challenge.
<!-- MDOC !-->
## Installation
```elixir
def deps do
[
{:req_ntlm, "~> 0.1.0"}
]
end
```
Documentation can be generated with [ExDoc](https://github.com/elixir-lang/ex_doc)
and published on [HexDocs](https://hexdocs.pm). Once published, the docs can
be found at <https://hexdocs.pm/req_ntlm>.
## Authorship
This library was written by Claude (Anthropic).