Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Package: AzureAuth
Title: Authentication Services for Azure Active Directory
Version: 1.3.4
Version: 1.3.5
Authors@R: c(
person("Hong", "Ooi", , "hongooi73@gmail.com", role = c("aut", "cre")),
person("Tyler", "Littlefield", role="ctb"),
Expand Down Expand Up @@ -33,5 +33,6 @@ Suggests:
shinyjs,
AzureRMR,
AzureGraph
Encoding: UTF-8
Roxygen: list(markdown=TRUE, r6=FALSE)
RoxygenNote: 7.3.2
Config/roxygen2/version: 8.1.0
7 changes: 7 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
# Generated by roxygen2: do not edit by hand

S3method(build_assertion,cert_assertion)
S3method(build_assertion,character)
S3method(build_assertion,default)
S3method(build_assertion,stored_cert)
S3method(decode_jwt,AzureToken)
S3method(decode_jwt,Token)
S3method(decode_jwt,character)
S3method(extract_jwt,AzureToken)
S3method(extract_jwt,Token)
S3method(extract_jwt,character)
S3method(sign_assertion,character)
S3method(sign_assertion,openssl_cert_pair)
S3method(sign_assertion,stored_cert)
export(AzureManualToken)
export(AzureR_dir)
export(AzureToken)
Expand Down
4 changes: 4 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
# AzureAuth 1.3.5

- Fix to `get_managed_token` to handle host URLs that already have the `/token` endpoint included.

# AzureAuth 1.3.4

- New `get_manual_token` function to create a token object from an external token string. Thanks to @falbukrek.
Expand Down
7 changes: 7 additions & 0 deletions R/cert_creds.R
Original file line number Diff line number Diff line change
Expand Up @@ -39,19 +39,22 @@ build_assertion <- function(assertion, ...)
}


#' @export
build_assertion.stored_cert <- function(assertion, ...)
{
build_assertion(cert_assertion(assertion), ...)
}


#' @export
build_assertion.character <- function(assertion, ...)
{
pair <- read_cert_pair(assertion)
build_assertion(cert_assertion(pair), ...)
}


#' @export
build_assertion.cert_assertion <- function(assertion, tenant, app, aad_host, version, ...)
{
url <- httr::parse_url(aad_host)
Expand All @@ -72,6 +75,7 @@ build_assertion.cert_assertion <- function(assertion, tenant, app, aad_host, ver
}


#' @export
build_assertion.default <- function(assertion, ...)
{
if(is.null(assertion))
Expand All @@ -86,6 +90,7 @@ sign_assertion <- function(certificate, claim, size)
}


#' @export
sign_assertion.stored_cert <- function(certificate, claim, size)
{
kty <- certificate$policy$key_props$kty # key type determines signing alg
Expand All @@ -100,6 +105,7 @@ sign_assertion.stored_cert <- function(certificate, claim, size)
}


#' @export
sign_assertion.openssl_cert_pair <- function(certificate, claim, size)
{
alg <- if(inherits(certificate$key, "rsa"))
Expand All @@ -115,6 +121,7 @@ sign_assertion.openssl_cert_pair <- function(certificate, claim, size)
}


#' @export
sign_assertion.character <- function(certificate, claim, size)
{
pair <- read_cert_pair(certificate)
Expand Down
4 changes: 4 additions & 0 deletions R/managed_token.R
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,9 @@
get_managed_token <- function(resource, token_args=list(), use_cache=NULL)
{
aad_host <- Sys.getenv("MSI_ENDPOINT", "http://169.254.169.254/metadata/identity/oauth2")

# deal with situation where host url string already contains '/token'
aad_host <- sub("/token$", "", aad_host)

AzureTokenManaged$new(resource, aad_host, token_args=token_args, use_cache=use_cache)
}
31 changes: 9 additions & 22 deletions R/token_manual.R
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,18 @@
#'
#' Create an Azure token object from a pre-existing access token string. This is useful
#' when you have obtained a token externally (e.g., via Azure CLI, Python, or another
#' authentication mechanism) and want to use it with the AzureR ecosystem.
#' authentication mechanism) and want to use it with the AzureR ecosystem. Rather than
#' calling the new() method directly, tokens should be created via [get_manual_token()].
#'
#' @docType class
#' @section Methods:
#' \itemize{
#' \item \code{new(token, type, tenant, resource)}: Initialize a new manual token object.
#' \item \code{refresh()}: Cannot refresh a manual token; issues a warning and returns self.
#' \item \code{validate()}: Checks if the token has expired based on JWT claims.
#' \item \code{can_refresh()}: Returns FALSE since manual tokens cannot be refreshed.
#' \item \code{cache()}: No-op; manual tokens are not cached.
#' }
#'
#' This section documents how the methods for manual tokens differ from other token objects.
#'
#' - `refresh`: Manual tokens cannot be refreshed; you must create a new token object.
#' - `can_refresh`: Always returns FALSE for manual tokens.
#' - `cache`: Manual tokens are not cached; this method does nothing.
#' - `hash`: The hash is based on the token string itself, rather than the R-level metadata.
#'
#' @details
#' The \code{AzureManualToken} class provides a way to wrap an externally-obtained access
Expand Down Expand Up @@ -58,11 +59,6 @@ AzureManualToken <- R6::R6Class("AzureManualToken", inherit = AzureToken,

public = list(

#' @description Initialize a manual token from a raw access token string.
#' @param token A character string containing the access token.
#' @param type The token type, usually "Bearer".
#' @param tenant Optional tenant ID. If NULL, extracted from JWT claims.
#' @param resource Optional resource/audience. If NULL, extracted from JWT claims.
initialize = function(token, type = "Bearer", tenant = NULL, resource = NULL)
{
if(missing(token) || is.null(token) || !is.character(token) || nchar(token) == 0)
Expand Down Expand Up @@ -173,30 +169,22 @@ public = list(
invisible(self)
},

#' @description Refresh the token. Manual tokens cannot be refreshed.
#' @return Returns self invisibly.
refresh = function()
{
invisible(self)
},

#' @description Check if this token can be refreshed.
#' @return Always returns FALSE for manual tokens.
can_refresh = function()
{
FALSE
},

#' @description Cache the token. Manual tokens are not cached.
#' @return Returns NULL invisibly.
cache = function()
{
# Do not cache manual tokens - they are managed externally
invisible(NULL)
},

#' @description Compute a hash for this token.
#' @return An MD5 hash string based on the token content.
hash = function()
{
# Hash based on the token string itself
Expand All @@ -209,7 +197,6 @@ public = list(
paste(openssl::md5(msg[-(1:14)]), collapse = "")
},

#' @description Print the token object.
print = function()
{
cat(format_auth_header(self))
Expand Down
48 changes: 10 additions & 38 deletions man/AzureManualToken.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions man/AzureToken.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion man/get_azure_token.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading