certificate error API connection within shiny app

My app is deployed on shinyapps and I am using read.table to connect to an API like so:

(I am masking the URL of the API because the data is confidential)

ds_file = '*****'
ds = read.table(file=ds_file)

Locally, it runs perfectly but when I deploy on shinyapps.io the logs show:

Warning in open.connection(file, "rt") :
URL '': status was 'Peer certificate cannot be authenticated with given CA certificates'
Error in open.connection: cannot open the connection to '
*'
open.connection
read.table
Error in open.connection(file, "rt") :
cannot open the connection to '********'

This solution did not work: https://stackoverflow.com/questions/40397932/r-peer-certificate-cannot-be-authenticated-with-given-ca-certificates-windows

Any ideas?

1 Like

This sounds like the API is behind https , but it is using a private / self-signed certificate. There are usually ways in httr or other HTTP libraries (curl, etc.) to connect without verifying the certificate. This is generally a very insecure practice because there is no guarantee that you are connecting to the correct API.

Instead, it might be preferable to include a CA bundle for your API in the bundle you publish to shinyapps.io , so that you can connect securely. For instance, using curl on the command line:

curl --cacert mycacert.pem https://myapi.com

The easier solution is to use a "real" certificate from a standard Certificate Authority so that the shinyapps.io execution environment will trust it by default, but if you do not own the API or infrastructure it runs on, then this is not something you have control over.

Thanks for the reply. I think I might be able to get the certificate of that API. But how do I include it in my bundle? If I place it in the root directory the error persists.

Also as I said it runs fine locally, why would it be different on shinyapps.io?

Your local machine probably trusts that CA, but shinyapps does not. If you are a part of an organization / enterprise, that is pretty standard (all internal computers automatically trust the internal CA, but no external computers will know about it).

So if you are using curl to get the file, you have --cacert and other params you can use to specify your own bundle. Whatever you are using to retrieve the API request (httr, etc.) will need to support the ability to specify your own CA bundle on the request, otherwise yes, you will keep having the issue.

The user running your R code will not have enough privileges to add your provided CA cert to the "system store" on shinyapps.io.

That didnt work for me or I couldn't figure it out. R studio support came up with this solution that works:

h <- new_handle()
handle_setopt(h, ssl_verifypeer = 0);
read.table(curl(*****, handle = h))

Its skips the SSL check though which may not be ideal.

Yeah, skipping the SSL check is one option, but definitely the less secure. If you have a CA bundle, you should be able to make this work using one of the other curl_options(), capath, maybe?

I don't have a great way to craft a working example at the moment, but may have a chance to take a look later!

curl::curl_options("ssl_verifypeer")
#> ssl_verifypeer 
#>             64
curl::curl_options("capath")
#> capath 
#>  10097

Created on 2020-06-05 by the reprex package (v0.3.0)

Ok! I finally got a chance to come back to this! The option you want is cainfo. Apparently, capath specifies a directory to use, but I had trouble with it working as I expected... :man_shrugging:

geturl <- function(handle) {
  paste0(
    substr(
      rawToChar(
        curl::curl_fetch_memory("https://ssl-connect:3939", handle = handle)$content
        )
      ,1,20)
    , "..."
  )
}
# fails on cert trust issue
h <- curl::new_handle()
geturl(h)
#> Error in curl::curl_fetch_memory("https://ssl-connect:3939", handle = handle): SSL certificate problem: unable to get local issuer certificate
rm(h)

# bypass cert trust - not good
h <- curl::new_handle()
curl::handle_setopt(h, ssl_verifypeer = 0)
geturl(h)
#> [1] "<!DOCTYPE html>\n<htm..."
rm(h)

# use custom cert authority - good!
h <- curl::new_handle()
curl::handle_setopt(h, cainfo = "/auth-docker.pem")
geturl(h)
#> [1] "<!DOCTYPE html>\n<htm..."
rm(h)

Created on 2020-06-08 by the reprex package (v0.3.0)

Oooh! And another one, using httr (my HTTP client of choice, usually)

httr::status_code(httr::GET("https://ssl-connect:3939"))
#> Error in curl::curl_fetch_memory(url, handle = handle): SSL certificate problem: unable to get local issuer certificate


httr::status_code(httr::GET("https://ssl-connect:3939", config = httr::config(cainfo = "/auth-docker.pem")))
#> [1] 200

Created on 2020-06-08 by the reprex package (v0.3.0)

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