waldronlab / cBioPortalData

Integrate the cancer genomics portal, cBioPortal, using MultiAssayExperiment
https://waldronlab.io/cBioPortalData/
30 stars 13 forks source link

How to handle using API token #17

Closed inodb closed 2 years ago

inodb commented 4 years ago

cBioPortal provides a way to connect to authenticated portals using an API token. I'm guessing we can pass the token to rapiclient somehow. This probably isn't too tricky. Volunteering myself to solve this

LiNk-NY commented 4 years ago

@inodb Do you have an example? The AnVIL::Service class allows for authentication. Perhaps that is enough?

inodb commented 4 years ago

@LiNk-NY not directly an example but could try that, thanks for the suggestion!

The docs are here:

https://docs.cbioportal.org/2.2-authorization-and-authentication/authenticating-users-via-tokens#using-data-access-tokens

need to have some way to add an authorization header to each request like:

curl \
     -X GET "http://www.cbioportal.org/api/studies" \
     -H "accept: application/json" \
     -H "Authorization: Bearer 63efa81c-2490-4e15-9d1c-fb6e8e50e35d"
LiNk-NY commented 4 years ago

Yup, it looks like the Service class supports it.

LiNk-NY commented 4 years ago

@inodb I would look at the AnVIL package for some examples using authentication

schaffman5 commented 3 years ago

I ran into this issue as well and there is a larger issue with the rapiclient package as I reported here https://github.com/bergant/rapiclient/issues/18. One workaround is to manually create the service, but this uses non-public methods. Perhaps there is a more elegant way to fix this or rely less on the rapiclient for this functionality.

# override get_api function in rapiclient R package
my_get_api <- function (url, config = NULL){
  api = NULL
  api <- tryCatch({
    # new code to properly handle the config parameters instead of just
    # calling jsonlite::fromJSON directly with the url and no other parameters
    res<-httr::GET(url, type="text/json", config=config)
    res.json<-httr::content(res, as="text", encoding="UTF-8")
    jsonlite::fromJSON(res.json, simplifyDataFrame = FALSE)
    # end of new code

    # old code:
    # jsonlite::fromJSON(url, simplifyDataFrame = FALSE)
  }, error = function(x) NULL)
  if (is.null(api))
    tryCatch({
      if (startsWith(url, "http")) {
        url0 <- url(url)
        open(url0)
        api <- yaml::yaml.load_file(url0) # this probably also needs to handle config
        close(url0)
      }
      else {
        api <- yaml::yaml.load_file(url)
      }
    }, error = function(x) NULL)
  if (is.null(api))
    stop("'url' does not appear to be JSON or YAML")
  if (is.null(api$swagger)) {
    warning("Missing Swagger Specification version")
  }
  if (is.null(api$info)) {
    warning("Missing Specification Info")
  }
  if (is.null(api$host)) {
    host <- httr::parse_url(url)$hostname
    if (!is.null(host)) {
      port <- httr::parse_url(url)$port
      if (!is.null(port)) {
        host <- paste0(host, ":", port)
      }
      api$host <- host
    }
  }
  if (is.null(api$basePath)) {
    api$basePath <- ""
  }
  api$basePath <- gsub("/$", "", api$basePath)
  if (is.null(api$schemes)) {
    api$schemes <- httr::parse_url(url)$scheme
  }
  if (is.null(api$paths)) {
    warning("There is no paths element in the API specification")
  }
  if (!(is.null(config) || inherits(config, "request")))
    stop("'config' must be NULL or an instance of httr::config()")
  api$config <- config
  class(api) <- c(rapiclient:::.class_api, class(api)) # added rapiclient:::.class_api
  api
}

Then the following will work.

cbio.api.url<-"<your_cbio_url>/api/api-docs"
cbio.token<-"<your_cbio_token>"

config <- httr::add_headers(Authorization = sprintf("Bearer %s", cbio.token))

cbio.api<-my_get_api(cbio.api.url, config)

cbioService<-AnVIL:::.Service(service ="cBioPortal", config=config, api = cbio.api)
cbio<-cBioPortalData:::.cBioPortal(cbioService)

cBioPortalData::getStudies(cbio)
cBioPortalData::clinicalData(cbio, "acc_tcga")
LiNk-NY commented 3 years ago

Hi @schaffman5

This is related to https://github.com/Bioconductor/AnVIL/issues/42 I've created a branch called token in cBioPortalData based on the changes in the AnVIL branch.

You can test this functionality with:

devtools::install_github("waldronlab/cBioPortalData", ref = "token")
devtools::install_github("Bioconductor/AnVIL", ref = "Service_api_header")

Let me know if this works. Best, Marcel

schaffman5 commented 3 years ago

Thanks. The cBioPortalData branch you referenced requires R version 4.2.0, which is not a current release. Could you modify the Description file to allow v4.1.0 instead?

LiNk-NY commented 3 years ago

Hi @schaffman5

The proposed changes would get merged to the Bioc-devel branch which currently uses R-devel. The R >= 4.2.0 is appropriate. For testing, you could modify the R version on a local checkout.

Best, Marcel

schaffman5 commented 3 years ago

@LiNk-NY Yes, the token branch works on our internal cBioPortal deployment. Thanks!

LiNk-NY commented 2 years ago

This should be implemented. Feel free to comment if you have any further issues with API tokens.

ZWael commented 2 years ago

Hi @schaffman5

The proposed changes would get merged to the Bioc-devel branch which currently uses R-devel. The R >= 4.2.0 is appropriate. For testing, you could modify the R version on a local checkout.

Best, Marcel

Hi I'am using R version 4.1 and i have installed CbioPortalData from bioconductor which install the version 2.6.1 but unfortunately it is not yet supporting token argument in the cBioPortal() function using devtools::install_github("waldronlab/cBioPortalData", ref = "token") require R 4.2 how can i make it work in R 4.1?

LiNk-NY commented 2 years ago

This feature is not available in R < 4.2. It is only available in Bioconductor-devel or soon-to-be RELEASE_3_15 .