NTLM authentication in httr2

Following up on an earlier question by @arthur.t - https://forum.posit.co/t/how-do-i-specity-authentication-type-in-httr2/140119 - I figured I should share what I worked out and see if anyone else has a more graceful solution.

tldr:

library(httr2)

  response <- request("https://www.example.com") |>
    req_options(httpauth = 8L) |>
    req_options(userpwd = ":") |>
    req_perform()

response

I need to do NTLM authentication while using httr2, which doesn't have the same range of easy authentication options as httr did. Turns out it's fairly easy but you need to get into the guts of curl to understand the numbers for options. You need to set the authentication option to CURLAUTH_NTLM . I ended up using httr2::req_options(httpauth = 8L) to pass this through to curl.

The option # for NTLM auth is 8 - you get that from finding CURLAUTH_NTLM in the source code for curl.h. The value (((unsigned long)1)<<3) calculates to 8 (1 x 2^3). Per curl::handle_setopt() you need to set these kinds of options as a number, hence using 8L to get a long int.

I don't like the roundabout way I found this and I'm sure there's a better/easier way. Does anyone know it?

1 Like

As followup, here is what I came up with as a long-term solution. If NTLM is available, Kerberos is probably also available and more secure, hence it's probably better to use "Negotiate" style authentication instead of just NTLM. The option code for "Negotiate" is 4. This is kind of documented in the internal httr2::auth_flags() (httr2/req-options.R at 2584361c1853e2ecf4d1728f80def74c351b1b59 · r-lib/httr2 · GitHub). That's only used for proxy request setting, so if we're making requests w/o proxies we need to set the curl option directly.

I created two little helper utilities that I use in my standard set of scripts so my httr2 requests are a bit more succinct. Maybe some day I'll submit a pull request to see if they want to include them in httr2; it's a really simple fix.

req_auth_negotiate <- function(req) {
  httr2::check_request(req)
  httr2::req_options(req, httpauth = 4L, userpwd = ":::")
}

req_auth_ntlm <- function(req) {
  httr2::check_request(req)
  httr2::req_options(req, httpauth = 8L, userpwd = ":::")
}

This lets me build requests that look just like normal httr2 requests:

library(httr2)

req_auth_negotiate <- function(req) {
  httr2::check_request(req)
  httr2::req_options(req, httpauth = 4L, userpwd = ":::")
}

  response <- request("https://www.example.com") |>
    req_auth_negotiate |>
    req_perform()

response
2 Likes

This topic was automatically closed 42 days after the last reply. New replies are no longer allowed.

If you have a query related to it or one of the replies, start a new topic and refer back with a link.