Skip to content

Commit

Permalink
Merge pull request #320 from DOI-USGS/token
Browse files Browse the repository at this point in the history
improve token handling. related to #317, #318, and #319.
  • Loading branch information
dblodgett-usgs authored Jan 17, 2024
2 parents a107d84 + 717dc29 commit 2f82a86
Show file tree
Hide file tree
Showing 8 changed files with 58 additions and 19 deletions.
2 changes: 1 addition & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Package: sbtools
Title: USGS ScienceBase Tools
Maintainer: David Blodgett <[email protected]>
Version: 1.3.0
Version: 1.3.1
Authors@R: c(person("David", "Blodgett", role=c("cre"),
email = "[email protected]"),
person("Luke", "Winslow", role = c("aut"),
Expand Down
1 change: 1 addition & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ import(jsonlite)
importFrom(curl,curl_version)
importFrom(methods,is)
importFrom(mime,guess_type)
importFrom(tools,R_user_dir)
importFrom(utils,globalVariables)
importFrom(utils,packageVersion)
importFrom(utils,setTxtProgressBar)
Expand Down
4 changes: 4 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
# version 1.3.1

Improved handling of cached token.

# version 1.3.0

In this release, sbtools underwent a significant migration from `josso` login to `keycloak`-based two factor authentication. See #314 for details of the changes.
Expand Down
2 changes: 0 additions & 2 deletions R/AAA.R
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@
pkg.env <- new.env()
pkg.env$username = ""

pkg.env$token_stache <- file.path(tools::R_user_dir(package = "sbtools"), "token")

.onLoad = function(libname, pkgname){
set_endpoint()
}
Expand Down
56 changes: 45 additions & 11 deletions R/authenticate_sb.R
Original file line number Diff line number Diff line change
Expand Up @@ -158,11 +158,12 @@ initialize_sciencebase_session <- function(username = NULL, token_text = NULL) {
if(token != "") {
check_current <- try(
initialize_keycloack_env(
token), silent = TRUE)
token, warn_on_fail = FALSE),
silent = TRUE)

if(isTRUE(check_current)) {
pkg.env$username <- username
return(TRUE)
return(invisible(TRUE))
}
}

Expand All @@ -180,18 +181,18 @@ initialize_sciencebase_session <- function(username = NULL, token_text = NULL) {

if(!inherits(worked, "try-error")) {
stache_token(token_text)
TRUE
return(invisible(TRUE))
} else {
FALSE
return(invisible(FALSE))
}
}

initialize_keycloack_env <- function(token_text) {
initialize_keycloack_env <- function(token_text, warn_on_fail = TRUE) {
pkg.env$keycloak_token <- jsonlite::fromJSON(token_text)

pkg.env$keycloak_expire <- Sys.time()

token_refresh()
token_refresh(warn_on_fail = warn_on_fail)
}

# utility to clean environment for testing
Expand All @@ -207,15 +208,46 @@ clean_session <- function() {
pkg.env$uid <- NULL
}

#' Get or set token stache data directory
#' @description if left unset, will return the user data dir
#' as returned by `tools::R_user_dir` for this package.
#' @param dir path of desired token stache file
#' @return character path of data directory (silent when setting)
#' @importFrom tools R_user_dir
#' @noRd
#'
token_stache_path <- function(dir = NULL) {

if(is.null(dir)) {
token_stache <- try(get("token_stache", envir = pkg.env), silent = TRUE)

if(inherits(token_stache, "try-error")) {
assign("token_stache",
file.path(tools::R_user_dir(package = "sbtools"), "token"),
envir = pkg.env)
}

return(get("token_stache", envir = pkg.env))
} else {
assign("token_stache",
dir,
envir = pkg.env)
return(invisible(get("token_stache", envir = pkg.env)))
}


}

stache_token <- function(token_text) {
dir.create(dirname(pkg.env$token_stache), recursive = TRUE, showWarnings = FALSE)
dir.create(dirname(token_stache_path()), recursive = TRUE, showWarnings = FALSE)

write(token_text, file = pkg.env$token_stache)
write(token_text, file = token_stache_path())
}

grab_token <- function() {
if(file.exists(pkg.env$token_stache)) {
readChar(pkg.env$token_stache, file.info(pkg.env$token_stache)$size)

if(file.exists(token_stache_path())) {
readChar(token_stache_path(), file.info(token_stache_path())$size)
} else {
""
}
Expand All @@ -232,7 +264,9 @@ readPassword <- function(prompt) {
if (exists(".rs.askForPassword", mode = "function")) {
pass <- .rs.askForPassword(prompt)
} else {
pass <- readline(prompt)
message("paste your token - expecting up to four lines")
pass <- readLines(n = 4)
pass <- paste(token, collapse = "")
}
return (pass)
}
Expand Down
4 changes: 2 additions & 2 deletions R/current_session.R
Original file line number Diff line number Diff line change
Expand Up @@ -161,14 +161,14 @@ refresh_token_before_expired <- function(refresh_amount_seconds = 600) {
return(invisible(FALSE))
}

token_refresh <- function(client_id = pkg.env$keycloak_client_id) {
token_refresh <- function(client_id = pkg.env$keycloak_client_id, warn_on_fail = TRUE) {

data = list(
client_id = client_id,
grant_type = "refresh_token",
refresh_token = get_refresh_token())

token <- RETRY("POST", pkg.env$token_url, body = data, encode = "form")
token <- RETRY("POST", pkg.env$token_url, body = data, encode = "form", quiet = TRUE)

if(!token$status_code == 200) {
warning('Unable to refresh SB cloud token. Some functionality may not work.')
Expand Down
4 changes: 2 additions & 2 deletions tests/testthat/test-auth.R
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ test_that("login results in valid session and renew works (new)", {
skip("Authenticated tests skipped due to lack of login info")
}

unlink(sbtools:::pkg.env$token_stache, force = TRUE)
unlink(sbtools:::token_stache_path(), force = TRUE)

if(!initialize_sciencebase_session(Sys.getenv("sb_user"), token)) {
sbtools:::clean_session()
Expand All @@ -83,7 +83,7 @@ test_that("login results in valid session and renew works (new)", {

on.exit(sbtools:::clean_session())

expect_true(file.exists(sbtools:::pkg.env$token_stache))
expect_true(file.exists(sbtools:::token_stache_path()))

expect_true(initialize_sciencebase_session())

Expand Down
4 changes: 3 additions & 1 deletion vignettes/sbtools.Rmd
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,9 @@ Much of `sbtools` is intended to be used after authentication. This part of `sbt

The old way used `authenticate_sb()` with a username and password. The password could be cached using the `keyring` package.

```{r}
NOTE: This method no longer works and is shown here for reference with regard to old code and workflows.

```{r, eval=FALSE}
authenticate_sb(Sys.getenv("sb_user"))
my_home_item <- user_id()
Expand Down

0 comments on commit 2f82a86

Please sign in to comment.