From 29e56a321acad2de44edacf053d5fdd24a172a06 Mon Sep 17 00:00:00 2001 From: andres Date: Fri, 15 Dec 2023 09:29:26 -0500 Subject: [PATCH] Documents functions and updates readme --- .Rbuildignore | 3 ++ .gitignore | 1 + NAMESPACE | 24 ------------ R/auth.R | 80 +++++++++++++++++++++++++++++++++------ R/config.R | 77 ++++++++++++++++++++++++++++++++----- R/entra_id.R | 14 ++++--- R/google.R | 16 ++++---- R/shiny.R | 23 ++++++++++- R/utils.R | 29 ++++++++++++++ README.md | 36 ++++++------------ _pkgdown.yml | 4 ++ man/access_token.Rd | 20 ++++++++++ man/build_cookie.Rd | 20 ++++++++++ man/build_redirect_uri.Rd | 18 +++++++++ man/decode_token.Rd | 20 ++++++++++ man/expires_at.Rd | 17 +++++++++ man/expires_in.Rd | 17 +++++++++ man/get_access_token.Rd | 18 +++++++++ man/get_bearer.Rd | 18 +++++++++ man/get_client_id.Rd | 18 +++++++++ man/get_login_url.Rd | 19 ++++++++++ man/get_logout_url.Rd | 18 +++++++++ man/get_token_field.Rd | 17 +++++++++ man/is_expired.Rd | 17 +++++++++ man/is_valid.Rd | 18 +++++++++ man/new_openid_config.Rd | 37 ++++++++++++++++++ man/parse_cookies.Rd | 18 +++++++++ man/print.access_token.Rd | 16 ++++++++ man/refresh_jwks.Rd | 15 ++++++++ man/remove_bearer.Rd | 18 +++++++++ man/request_token.Rd | 20 ++++++++++ man/sso_shiny_app.Rd | 26 +++++++++++++ man/token.Rd | 18 +++++++++ 33 files changed, 646 insertions(+), 84 deletions(-) create mode 100644 _pkgdown.yml create mode 100644 man/access_token.Rd create mode 100644 man/build_cookie.Rd create mode 100644 man/build_redirect_uri.Rd create mode 100644 man/decode_token.Rd create mode 100644 man/expires_at.Rd create mode 100644 man/expires_in.Rd create mode 100644 man/get_access_token.Rd create mode 100644 man/get_bearer.Rd create mode 100644 man/get_client_id.Rd create mode 100644 man/get_login_url.Rd create mode 100644 man/get_logout_url.Rd create mode 100644 man/get_token_field.Rd create mode 100644 man/is_expired.Rd create mode 100644 man/is_valid.Rd create mode 100644 man/new_openid_config.Rd create mode 100644 man/parse_cookies.Rd create mode 100644 man/print.access_token.Rd create mode 100644 man/refresh_jwks.Rd create mode 100644 man/remove_bearer.Rd create mode 100644 man/request_token.Rd create mode 100644 man/sso_shiny_app.Rd create mode 100644 man/token.Rd diff --git a/.Rbuildignore b/.Rbuildignore index 5163d0b..afa5e21 100644 --- a/.Rbuildignore +++ b/.Rbuildignore @@ -1 +1,4 @@ ^LICENSE\.md$ +^_pkgdown\.yml$ +^docs$ +^pkgdown$ diff --git a/.gitignore b/.gitignore index dfcf473..e0f5575 100644 --- a/.gitignore +++ b/.gitignore @@ -49,3 +49,4 @@ po/*~ rsconnect/ example/.Renviron +docs diff --git a/NAMESPACE b/NAMESPACE index 77a7680..23bf731 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -1,35 +1,11 @@ # Generated by roxygen2: do not edit by hand -S3method(access_token,entra_id_config) -S3method(access_token,google_config) -S3method(decode_token,entra_id_config) -S3method(decode_token,google_config) -S3method(get_client_id,entra_id_config) -S3method(get_client_id,google_config) -S3method(get_login_url,entra_id_config) -S3method(get_login_url,google_config) -S3method(get_logout_url,entra_id_config) -S3method(get_logout_url,google_config) S3method(print,access_token) -S3method(request_token,entra_id_config) -S3method(request_token,google_config) -S3method(shiny_app,entra_id_config) -S3method(shiny_app,google_config) -export(access_token) -export(decode_token) export(expires_at) export(expires_in) -export(get_access_token) -export(get_bearer) -export(get_client_id) -export(get_login_url) -export(get_logout_url) export(get_token_field) export(is_expired) export(is_valid) export(new_openid_config) -export(refresh_jwks) -export(request_token) -export(shiny_app) export(sso_shiny_app) export(token) diff --git a/R/auth.R b/R/auth.R index cd5c9a5..d55f133 100644 --- a/R/auth.R +++ b/R/auth.R @@ -1,14 +1,21 @@ -#' @export -access_token <- function(config, token) { +#' @title Create a new Access Token +#' @description Creates a new access token from a config and a token string +#' +#' @param config An openid_config object +#' @param token_str A string containing the access token to decode +#' +#' @return An access_token object +#' @keywords internal +access_token <- function(config, token_str) { UseMethod("access_token") } -#' @export -access_token.google_config <- function(config, token) { - token_data <- decode_token(config, token) +#' @keywords internal +access_token.google_config <- function(config, token_str) { + token_data <- decode_token(config, token_str) structure( list( - access_token = token, + access_token = token_str, exp = lubridate::as_datetime(token_data$exp), iat = lubridate::as_datetime(token_data$iat), token_data = token_data @@ -17,12 +24,12 @@ access_token.google_config <- function(config, token) { ) } -#' @export -access_token.entra_id_config <- function(config, token) { - token_data <- decode_token(config, token) +#' @keywords internal +access_token.entra_id_config <- function(config, token_str) { + token_data <- decode_token(config, token_str) structure( list( - access_token = token, + access_token = token_str, exp = lubridate::as_datetime(token_data$exp), iat = lubridate::as_datetime(token_data$iat), token_data = token_data @@ -31,6 +38,11 @@ access_token.entra_id_config <- function(config, token) { ) } +#' @title Print an access token +#' @description Prints an access token's expiration date +#' +#' @param x An access_token object +#' @param ... Ignored #' @export print.access_token <- function(x, ...) { expiration_date <- expires_at(x) @@ -47,38 +59,82 @@ print.access_token <- function(x, ...) { "\n", sep = " " ) + return() } +#' @title Check if an access token is valid +#' @description Checks if an access token is valid +#' by checking if it is expired +#' +#' @param token An access_token object +#' +#' @return A boolean indicating if the token is valid #' @export is_valid <- function(token) { !is_expired(token) } +#' @title Check if an access token is expired +#' @description Checks if an access token is expired +#' +#' @param token An access_token object +#' +#' @return A boolean indicating if the token is expired #' @export is_expired <- function(token) { Sys.time() > token$exp } -#' @export +#' @title Get the Authorization header for an access token +#' @description Gets the Authorization header for an access token +#' +#' @param token An access_token object +#' +#' @return A string containing the Authorization header +#' @keywords internal get_bearer <- function(token) { paste0("Bearer ", token$access_token) } -#' @export +#' @title Get the access token string +#' @description Gets the access token string +#' +#' @param token An access_token object +#' +#' @return A string containing the access token +#' @keywords internal get_access_token <- function(token) { token$access_token } +#' @title Get the expiration time of an access token +#' @description Gets the expiration time of an access token +#' +#' @param token An access_token object +#' +#' @return A duration object containing the time until the token expires #' @export expires_in <- function(token) { token$exp - Sys.time() } +#' @title Get the expiration date and time of an access token +#' @description Gets the expiration date and time of an access token +#' +#' @param token An access_token object +#' +#' @return A POSIXct object containing the date and time the token expires #' @export expires_at <- function(token) { token$exp } +#' @title Get the issued at time of an access token +#' @description Gets the issued at time of an access token +#' +#' @param token An access_token object +#' +#' @return A POSIXct object containing the date and time the token was issued #' @export get_token_field <- function(token, field) { token$token_data[[field]] diff --git a/R/config.R b/R/config.R index b2c387e..237778c 100644 --- a/R/config.R +++ b/R/config.R @@ -1,3 +1,4 @@ +#' @keywords internal fetch_jwks <- function(url) { httr2::request(url) |> httr2::req_method("GET") |> @@ -7,40 +8,98 @@ fetch_jwks <- function(url) { purrr::map(jose::jwk_read) } +#' @title New openid configuration +#' @description Creates a new openid configuration object +#' for the given provider +#' +#' @param provider The openid provider to use +#' @param app_url The URL of the application +#' (used to build redirect, login, and logout URLs) +#' @param ... Additional arguments passed to the provider's configuration. +#' This depends on the provider. +#' +#' The `"google"` provider accepts the following arguments: +#' - `client_id` +#' - `client_secret` +#' +#' The `"entra_id"` provider accepts the following arguments: +#' - `client_id` +#' - `client_secret` +#' - `tenant_id` +#' +#' @return An openid_config object #' @export -new_openid_config <- function(provider, ...) { +new_openid_config <- function(provider, app_url, ...) { switch(provider, - entra_id = new_entra_id_config(...), - google = new_google_config(...) + entra_id = new_entra_id_config(app_url = app_url, ...), + google = new_google_config(app_url = app_url, ...) ) } -#' @export +#' @title Get the login URL for the app +#' @description Gets the URL that the provider should redirect to +#' after a login attempt. +#' +#' @param config An openid_config object +#' +#' @return A string containing the login URL +#' @keywords internal get_login_url <- function(config) { UseMethod("get_login_url") } -#' @export + +#' @title Get the logout URL for the provider +#' @description Gets the URL for SLO (single logout) +#' +#' @param config An openid_config object +#' +#' @return A string containing the logout URL +#' @keywords internal get_logout_url <- function(config) { UseMethod("get_logout_url") } -#' @export +#' @title Request a token from the provider +#' @description Requests a token from the provider +#' +#' @param config An openid_config object +#' @param authorization_code The authorization code to use +#' +#' @return An access_token object +#' @keywords internal request_token <- function(config, authorization_code) { UseMethod("request_token") } -#' @export +#' @title Decode a token +#' @description Decodes a token +#' +#' @param config An openid_config object +#' @param token The token to decode +#' +#' @return A list containing the decoded token's data +#' @keywords internal decode_token <- function(config, token) { UseMethod("decode_token") } -#' @export +#' @title Get the client ID +#' @description Gets the client ID for the provider +#' +#' @param config An openid_config object +#' +#' @return A string containing the client ID +#' @keywords internal get_client_id <- function(config) { UseMethod("get_client_id") } -#' @export +#' @title Refresh the JWKS +#' @description Refreshes the JWKS +#' +#' @param config An openid_config object +#' @keywords internal refresh_jwks <- function(config) { UseMethod("refresh_jwks") } diff --git a/R/entra_id.R b/R/entra_id.R index fb6e565..4c708bb 100644 --- a/R/entra_id.R +++ b/R/entra_id.R @@ -1,5 +1,6 @@ ENTRA_ID_BASE_URL <- "https://login.microsoftonline.com" +#' @keywords internal build_entra_id_login_url <- function(auth_url, client_id, redirect_uri) { url <- httr2::url_parse(auth_url) url$query <- list( @@ -13,6 +14,7 @@ build_entra_id_login_url <- function(auth_url, client_id, redirect_uri) { httr2::url_build(url) } +#' @keywords internal new_entra_id_config <- function(tenant_id, client_id, client_secret, app_url) { auth_url <- glue::glue("{ENTRA_ID_BASE_URL}/{tenant_id}/oauth2/v2.0/authorize") token_url <- glue::glue("{ENTRA_ID_BASE_URL}/{tenant_id}/oauth2/v2.0/token") @@ -35,17 +37,17 @@ new_entra_id_config <- function(tenant_id, client_id, client_secret, app_url) { ) } -#' @export +#' @keywords internal get_login_url.entra_id_config <- function(config) { config$login_url } -#' @export +#' @keywords internal get_logout_url.entra_id_config <- function(config) { stop("Logout not implemented for Entra ID") } -#' @export +#' @keywords internal request_token.entra_id_config <- function(config, authorization_code) { res <- httr2::request(config$token_url) |> httr2::req_method("POST") |> @@ -65,7 +67,7 @@ request_token.entra_id_config <- function(config, authorization_code) { access_token(config, resp_body$access_token) } -#' @export +#' @keywords internal decode_token.entra_id_config <- function(config, token) { decoded <- config$jwks |> purrr::map(function(jwk) { @@ -84,12 +86,12 @@ decode_token.entra_id_config <- function(config, token) { return(decoded) } -#' @export +#' @keywords internal get_client_id.entra_id_config <- function(config) { config$client_id } -#' @export +#' @keywords internal shiny_app.entra_id_config <- function(config, app) { app_handler <- app$httpHandler login_handler <- function(req) { diff --git a/R/google.R b/R/google.R index 0032478..7d3217c 100644 --- a/R/google.R +++ b/R/google.R @@ -1,3 +1,4 @@ +#' @keywords internal build_google_login_url <- function(auth_url, client_id, redirect_uri) { url <- httr2::url_parse(auth_url) url$query <- list( @@ -10,6 +11,7 @@ build_google_login_url <- function(auth_url, client_id, redirect_uri) { httr2::url_build(url) } +#' @keywords internal new_google_config <- function(client_id, client_secret, app_url) { auth_url <- "https://accounts.google.com/o/oauth2/v2/auth" token_url <- "https://oauth2.googleapis.com/token" @@ -31,17 +33,17 @@ new_google_config <- function(client_id, client_secret, app_url) { ) } -#' @export +#' @keywords internal get_login_url.google_config <- function(config) { config$login_url } -#' @export +#' @keywords internal get_logout_url.google_config <- function(config) { - stop("Logout not implemented for Entra ID") + stop("Not implemented") } -#' @export +#' @keywords internal request_token.google_config <- function(config, authorization_code) { res <- httr2::request(config$token_url) |> httr2::req_method("POST") |> @@ -61,7 +63,7 @@ request_token.google_config <- function(config, authorization_code) { access_token(config, resp_body$id_token) } -#' @export +#' @keywords internal decode_token.google_config <- function(config, token) { decoded <- config$jwks |> purrr::map(function(jwk) { @@ -80,12 +82,12 @@ decode_token.google_config <- function(config, token) { return(decoded) } -#' @export +#' @keywords internal get_client_id.google_config <- function(config) { config$client_id } -#' @export +#' @keywords internal shiny_app.google_config <- function(config, app) { app_handler <- app$httpHandler login_handler <- function(req) { diff --git a/R/shiny.R b/R/shiny.R index 16d686f..9fe6c64 100644 --- a/R/shiny.R +++ b/R/shiny.R @@ -1,3 +1,4 @@ +#' @keywords internal rsso_server <- function(config, server_func) { function(input, output, session) { cookies <- parse_cookies(session$request$HTTP_COOKIE) @@ -18,16 +19,36 @@ rsso_server <- function(config, server_func) { } } -#' @export +#' @keywords internal shiny_app <- function(config, app) { UseMethod("shiny_app") } +#' @title Get the access token +#' +#' @description Gets the access token from the session to be used +#' for internal logic. +#' +#' @param session A Shiny session +#' +#' @return An access_token object #' @export token <- function(session = shiny::getDefaultReactiveDomain()) { session$userData$token } +#' @title Create a Shiny app with SSO +#' +#' @description Creates a Shiny app with SSO (single sign-on) +#' based on the given configuration. +#' +#' @param config An openid_config object +#' @param ui A Shiny UI function +#' @param server A Shiny server function. This function requires +#' all three arguments: `input`, `output`, and `session`. +#' +#' @seealso [tapLock::new_openid_config()] +#' @return A Shiny app (Compatible with [`shinyApp()`][shiny::shinyApp]) #' @export sso_shiny_app <- function(config, ui, server) { app <- shiny::shinyApp(ui = ui, server = rsso_server(config, server)) diff --git a/R/utils.R b/R/utils.R index 50b719d..37e200d 100644 --- a/R/utils.R +++ b/R/utils.R @@ -1,3 +1,10 @@ +#' @title Remove bearer from token +#' @description Removes the "Bearer " prefix from a token +#' +#' @param token A string containing the token +#' +#' @return A string containing the token without the "Bearer " prefix +#' @keywords internal remove_bearer <- function(token) { if (is.null(token)) { return(NULL) @@ -6,6 +13,13 @@ remove_bearer <- function(token) { return(token) } +#' @title Parse cookies +#' @description Parses cookies from a string +#' +#' @param x A string containing the cookies +#' +#' @return A list containing the cookies +#' @keywords internal parse_cookies <- function(x) { if (is.null(x)) { return(list()) @@ -20,10 +34,25 @@ parse_cookies <- function(x) { return(cookie_pairs) } +#' @title Build a cookie +#' @description Builds an HttpOnly cookie from a key and value +#' +#' @param key A string containing the cookie key +#' @param value A string containing the cookie value +#' +#' @return A string containing the cookie +#' @keywords internal build_cookie <- function(key, value) { glue::glue("{key}={value}; path=/; SameSite=Lax; HttpOnly") } +#' @title Build a redirect URI +#' @description Builds a redirect URI from an app URL +#' +#' @param app_url A string containing the app URL +#' +#' @return A string containing the redirect URI +#' @keywords internal build_redirect_uri <- function(app_url) { url <- httr2::url_parse(app_url) path <- url$path diff --git a/README.md b/README.md index 6ba7c52..51adafe 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,10 @@ -# R.SSO +# tapLock ## Example Shiny App with Entra ID Authentication ```R library(shiny) -library(r.sso) +library(tapLock) auth_config <- new_openid_config( provider = "entra_id", @@ -15,14 +15,7 @@ auth_config <- new_openid_config( ) ui <- fluidPage( - tags$h1("r.sso example"), - tags$a( - tags$button( - "Logout", - class = "btn btn-primary" - ), - href = "/logout" - ), + tags$h1("tapLock example"), textOutput("user") ) @@ -33,20 +26,20 @@ server <- function(input, output, session) { family_name <- get_token_field(token(), "family_name") expires_at <- expires_at(token()) glue::glue( - "Hello {given_name} {family_name}! Your authenticated session will expire at {expires_at}." + "Hello {given_name} {family_name}!", + "Your authenticated session will expire at {expires_at}.", + .sep = " " ) }) } - -sso_shiny_app(auth_config, ui, server) ``` ## Example Shiny App with Google Authentication ```R library(shiny) -library(r.sso) +library(tapLock) auth_config <- new_openid_config( provider = "google", @@ -56,14 +49,7 @@ auth_config <- new_openid_config( ) ui <- fluidPage( - tags$h1("r.sso example"), - tags$a( - tags$button( - "Logout", - class = "btn btn-primary" - ), - href = "/logout" - ), + tags$h1("tapLock example"), textOutput("user") ) @@ -74,12 +60,12 @@ server <- function(input, output, session) { family_name <- get_token_field(token(), "family_name") expires_at <- expires_at(token()) glue::glue( - "Hello {given_name} {family_name}! Your authenticated session will expire at {expires_at}." + "Hello {given_name} {family_name}!", + "Your authenticated session will expire at {expires_at}.", + .sep = " " ) }) } - -sso_shiny_app(auth_config, ui, server) ``` diff --git a/_pkgdown.yml b/_pkgdown.yml new file mode 100644 index 0000000..d71acfb --- /dev/null +++ b/_pkgdown.yml @@ -0,0 +1,4 @@ +url: ~ +template: + bootstrap: 5 + diff --git a/man/access_token.Rd b/man/access_token.Rd new file mode 100644 index 0000000..88fc2cd --- /dev/null +++ b/man/access_token.Rd @@ -0,0 +1,20 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/auth.R +\name{access_token} +\alias{access_token} +\title{Create a new Access Token} +\usage{ +access_token(config, token_str) +} +\arguments{ +\item{config}{An openid_config object} + +\item{token_str}{A string containing the access token to decode} +} +\value{ +An access_token object +} +\description{ +Creates a new access token from a config and a token string +} +\keyword{internal} diff --git a/man/build_cookie.Rd b/man/build_cookie.Rd new file mode 100644 index 0000000..c4088dc --- /dev/null +++ b/man/build_cookie.Rd @@ -0,0 +1,20 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/utils.R +\name{build_cookie} +\alias{build_cookie} +\title{Build a cookie} +\usage{ +build_cookie(key, value) +} +\arguments{ +\item{key}{A string containing the cookie key} + +\item{value}{A string containing the cookie value} +} +\value{ +A string containing the cookie +} +\description{ +Builds an HttpOnly cookie from a key and value +} +\keyword{internal} diff --git a/man/build_redirect_uri.Rd b/man/build_redirect_uri.Rd new file mode 100644 index 0000000..54a826b --- /dev/null +++ b/man/build_redirect_uri.Rd @@ -0,0 +1,18 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/utils.R +\name{build_redirect_uri} +\alias{build_redirect_uri} +\title{Build a redirect URI} +\usage{ +build_redirect_uri(app_url) +} +\arguments{ +\item{app_url}{A string containing the app URL} +} +\value{ +A string containing the redirect URI +} +\description{ +Builds a redirect URI from an app URL +} +\keyword{internal} diff --git a/man/decode_token.Rd b/man/decode_token.Rd new file mode 100644 index 0000000..5f6f6d5 --- /dev/null +++ b/man/decode_token.Rd @@ -0,0 +1,20 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/config.R +\name{decode_token} +\alias{decode_token} +\title{Decode a token} +\usage{ +decode_token(config, token) +} +\arguments{ +\item{config}{An openid_config object} + +\item{token}{The token to decode} +} +\value{ +A list containing the decoded token's data +} +\description{ +Decodes a token +} +\keyword{internal} diff --git a/man/expires_at.Rd b/man/expires_at.Rd new file mode 100644 index 0000000..33b4a9c --- /dev/null +++ b/man/expires_at.Rd @@ -0,0 +1,17 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/auth.R +\name{expires_at} +\alias{expires_at} +\title{Get the expiration date and time of an access token} +\usage{ +expires_at(token) +} +\arguments{ +\item{token}{An access_token object} +} +\value{ +A POSIXct object containing the date and time the token expires +} +\description{ +Gets the expiration date and time of an access token +} diff --git a/man/expires_in.Rd b/man/expires_in.Rd new file mode 100644 index 0000000..82510b8 --- /dev/null +++ b/man/expires_in.Rd @@ -0,0 +1,17 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/auth.R +\name{expires_in} +\alias{expires_in} +\title{Get the expiration time of an access token} +\usage{ +expires_in(token) +} +\arguments{ +\item{token}{An access_token object} +} +\value{ +A duration object containing the time until the token expires +} +\description{ +Gets the expiration time of an access token +} diff --git a/man/get_access_token.Rd b/man/get_access_token.Rd new file mode 100644 index 0000000..a13413e --- /dev/null +++ b/man/get_access_token.Rd @@ -0,0 +1,18 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/auth.R +\name{get_access_token} +\alias{get_access_token} +\title{Get the access token string} +\usage{ +get_access_token(token) +} +\arguments{ +\item{token}{An access_token object} +} +\value{ +A string containing the access token +} +\description{ +Gets the access token string +} +\keyword{internal} diff --git a/man/get_bearer.Rd b/man/get_bearer.Rd new file mode 100644 index 0000000..0767303 --- /dev/null +++ b/man/get_bearer.Rd @@ -0,0 +1,18 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/auth.R +\name{get_bearer} +\alias{get_bearer} +\title{Get the Authorization header for an access token} +\usage{ +get_bearer(token) +} +\arguments{ +\item{token}{An access_token object} +} +\value{ +A string containing the Authorization header +} +\description{ +Gets the Authorization header for an access token +} +\keyword{internal} diff --git a/man/get_client_id.Rd b/man/get_client_id.Rd new file mode 100644 index 0000000..11592c1 --- /dev/null +++ b/man/get_client_id.Rd @@ -0,0 +1,18 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/config.R +\name{get_client_id} +\alias{get_client_id} +\title{Get the client ID} +\usage{ +get_client_id(config) +} +\arguments{ +\item{config}{An openid_config object} +} +\value{ +A string containing the client ID +} +\description{ +Gets the client ID for the provider +} +\keyword{internal} diff --git a/man/get_login_url.Rd b/man/get_login_url.Rd new file mode 100644 index 0000000..44fe457 --- /dev/null +++ b/man/get_login_url.Rd @@ -0,0 +1,19 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/config.R +\name{get_login_url} +\alias{get_login_url} +\title{Get the login URL for the app} +\usage{ +get_login_url(config) +} +\arguments{ +\item{config}{An openid_config object} +} +\value{ +A string containing the login URL +} +\description{ +Gets the URL that the provider should redirect to +after a login attempt. +} +\keyword{internal} diff --git a/man/get_logout_url.Rd b/man/get_logout_url.Rd new file mode 100644 index 0000000..8a4d960 --- /dev/null +++ b/man/get_logout_url.Rd @@ -0,0 +1,18 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/config.R +\name{get_logout_url} +\alias{get_logout_url} +\title{Get the logout URL for the provider} +\usage{ +get_logout_url(config) +} +\arguments{ +\item{config}{An openid_config object} +} +\value{ +A string containing the logout URL +} +\description{ +Gets the URL for SLO (single logout) +} +\keyword{internal} diff --git a/man/get_token_field.Rd b/man/get_token_field.Rd new file mode 100644 index 0000000..b7f2523 --- /dev/null +++ b/man/get_token_field.Rd @@ -0,0 +1,17 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/auth.R +\name{get_token_field} +\alias{get_token_field} +\title{Get the issued at time of an access token} +\usage{ +get_token_field(token, field) +} +\arguments{ +\item{token}{An access_token object} +} +\value{ +A POSIXct object containing the date and time the token was issued +} +\description{ +Gets the issued at time of an access token +} diff --git a/man/is_expired.Rd b/man/is_expired.Rd new file mode 100644 index 0000000..28acfd8 --- /dev/null +++ b/man/is_expired.Rd @@ -0,0 +1,17 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/auth.R +\name{is_expired} +\alias{is_expired} +\title{Check if an access token is expired} +\usage{ +is_expired(token) +} +\arguments{ +\item{token}{An access_token object} +} +\value{ +A boolean indicating if the token is expired +} +\description{ +Checks if an access token is expired +} diff --git a/man/is_valid.Rd b/man/is_valid.Rd new file mode 100644 index 0000000..938d051 --- /dev/null +++ b/man/is_valid.Rd @@ -0,0 +1,18 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/auth.R +\name{is_valid} +\alias{is_valid} +\title{Check if an access token is valid} +\usage{ +is_valid(token) +} +\arguments{ +\item{token}{An access_token object} +} +\value{ +A boolean indicating if the token is valid +} +\description{ +Checks if an access token is valid +by checking if it is expired +} diff --git a/man/new_openid_config.Rd b/man/new_openid_config.Rd new file mode 100644 index 0000000..473bf58 --- /dev/null +++ b/man/new_openid_config.Rd @@ -0,0 +1,37 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/config.R +\name{new_openid_config} +\alias{new_openid_config} +\title{New openid configuration} +\usage{ +new_openid_config(provider, app_url, ...) +} +\arguments{ +\item{provider}{The openid provider to use} + +\item{app_url}{The URL of the application +(used to build redirect, login, and logout URLs)} + +\item{...}{Additional arguments passed to the provider's configuration. +This depends on the provider. + +The \code{"google"} provider accepts the following arguments: +\itemize{ +\item \code{client_id} +\item \code{client_secret} +} + +The \code{"entra_id"} provider accepts the following arguments: +\itemize{ +\item \code{client_id} +\item \code{client_secret} +\item \code{tenant_id} +}} +} +\value{ +An openid_config object +} +\description{ +Creates a new openid configuration object +for the given provider +} diff --git a/man/parse_cookies.Rd b/man/parse_cookies.Rd new file mode 100644 index 0000000..6b78751 --- /dev/null +++ b/man/parse_cookies.Rd @@ -0,0 +1,18 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/utils.R +\name{parse_cookies} +\alias{parse_cookies} +\title{Parse cookies} +\usage{ +parse_cookies(x) +} +\arguments{ +\item{x}{A string containing the cookies} +} +\value{ +A list containing the cookies +} +\description{ +Parses cookies from a string +} +\keyword{internal} diff --git a/man/print.access_token.Rd b/man/print.access_token.Rd new file mode 100644 index 0000000..126b5ff --- /dev/null +++ b/man/print.access_token.Rd @@ -0,0 +1,16 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/auth.R +\name{print.access_token} +\alias{print.access_token} +\title{Print an access token} +\usage{ +\method{print}{access_token}(x, ...) +} +\arguments{ +\item{x}{An access_token object} + +\item{...}{Ignored} +} +\description{ +Prints an access token's expiration date +} diff --git a/man/refresh_jwks.Rd b/man/refresh_jwks.Rd new file mode 100644 index 0000000..950853f --- /dev/null +++ b/man/refresh_jwks.Rd @@ -0,0 +1,15 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/config.R +\name{refresh_jwks} +\alias{refresh_jwks} +\title{Refresh the JWKS} +\usage{ +refresh_jwks(config) +} +\arguments{ +\item{config}{An openid_config object} +} +\description{ +Refreshes the JWKS +} +\keyword{internal} diff --git a/man/remove_bearer.Rd b/man/remove_bearer.Rd new file mode 100644 index 0000000..1eeee61 --- /dev/null +++ b/man/remove_bearer.Rd @@ -0,0 +1,18 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/utils.R +\name{remove_bearer} +\alias{remove_bearer} +\title{Remove bearer from token} +\usage{ +remove_bearer(token) +} +\arguments{ +\item{token}{A string containing the token} +} +\value{ +A string containing the token without the "Bearer " prefix +} +\description{ +Removes the "Bearer " prefix from a token +} +\keyword{internal} diff --git a/man/request_token.Rd b/man/request_token.Rd new file mode 100644 index 0000000..9b249f3 --- /dev/null +++ b/man/request_token.Rd @@ -0,0 +1,20 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/config.R +\name{request_token} +\alias{request_token} +\title{Request a token from the provider} +\usage{ +request_token(config, authorization_code) +} +\arguments{ +\item{config}{An openid_config object} + +\item{authorization_code}{The authorization code to use} +} +\value{ +An access_token object +} +\description{ +Requests a token from the provider +} +\keyword{internal} diff --git a/man/sso_shiny_app.Rd b/man/sso_shiny_app.Rd new file mode 100644 index 0000000..29d6ee8 --- /dev/null +++ b/man/sso_shiny_app.Rd @@ -0,0 +1,26 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/shiny.R +\name{sso_shiny_app} +\alias{sso_shiny_app} +\title{Create a Shiny app with SSO} +\usage{ +sso_shiny_app(config, ui, server) +} +\arguments{ +\item{config}{An openid_config object} + +\item{ui}{A Shiny UI function} + +\item{server}{A Shiny server function. This function requires +all three arguments: \code{input}, \code{output}, and \code{session}.} +} +\value{ +A Shiny app (Compatible with \code{\link[shiny:shinyApp]{shinyApp()}}) +} +\description{ +Creates a Shiny app with SSO (single sign-on) +based on the given configuration. +} +\seealso{ +\code{\link[=new_openid_config]{new_openid_config()}} +} diff --git a/man/token.Rd b/man/token.Rd new file mode 100644 index 0000000..9aa4e8b --- /dev/null +++ b/man/token.Rd @@ -0,0 +1,18 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/shiny.R +\name{token} +\alias{token} +\title{Get the access token} +\usage{ +token(session = shiny::getDefaultReactiveDomain()) +} +\arguments{ +\item{session}{A Shiny session} +} +\value{ +An access_token object +} +\description{ +Gets the access token from the session to be used +for internal logic. +}