ADLS - Changes to OAuthModule to support getting an access token using RefreshToken or using a DeviceCode.

This commit is contained in:
omkarksa 2017-09-25 18:42:14 +05:30
Родитель 6d6acf3cd7
Коммит f367c20f55
10 изменённых файлов: 149 добавлений и 26 удалений

Просмотреть файл

@ -42,6 +42,7 @@ export(azureGetBlob)
export(azureGetTokenClientCredential)
export(azureGetTokenDeviceCode)
export(azureGetTokenDeviceCodeFetch)
export(azureGetTokenRefreshToken)
export(azureHDIConf)
export(azureHiveSQL)
export(azureHiveStatus)

Просмотреть файл

@ -40,8 +40,15 @@ azureAuthenticateOnAuthType <- function(azureActiveContext, authType, resource,
if (is.null(resource) || nchar(resource) == 0)
stop("Unspecified Resource. Please specify a valid resource.")
# before using the preferred auth type, check if access token can be fetched with a valid refresh token
refreshToken <- azureActiveContext$RefreshToken
if (!is.null(refreshToken) && nchar(refreshToken) > 0) {
authType <- "RefreshToken"
}
result <- switch(
authType,
RefreshToken = azureGetTokenRefreshToken(azureActiveContext),
ClientCredential = azureGetTokenClientCredential(azureActiveContext, resource = resource, verbose = verbose),
DeviceCode = azureGetTokenDeviceCode(azureActiveContext, resource = resource, verbose = verbose),
FALSE
@ -55,7 +62,7 @@ azureAuthenticateOnAuthType <- function(azureActiveContext, authType, resource,
return(result)
}
#' Get Azure token
#' Get Azure token using client credentials
#'
#' @inheritParams setAzureContext
#' @param resource Specify the resource with which the toke is obtained
@ -79,14 +86,16 @@ azureGetTokenClientCredential <- function(azureActiveContext, tenantID, clientID
assert_that(is_tenant_id(tenantID))
assert_that(is_client_id(clientID))
assert_that(is_authKey(authKey))
# TODO: check resource?
verbosity <- set_verbosity(verbose)
URLGT <- paste0("https://login.microsoftonline.com/", tenantID, "/oauth2/token?api-version=1.0")
authKeyEncoded <- URLencode(authKey, reserved = TRUE)
resourceEncoded <- URLencode(resource, reserved = TRUE)
bodyGT <- paste0("grant_type=client_credentials&resource=", resourceEncoded, "&client_id=",
clientID, "&client_secret=", authKeyEncoded)
bodyGT <- paste0("grant_type=client_credentials", "&client_id=", clientID, "&client_secret=", authKeyEncoded,
"&resource=", resourceEncoded)
r <- httr::POST(URLGT,
add_headers(
@ -109,7 +118,7 @@ azureGetTokenClientCredential <- function(azureActiveContext, tenantID, clientID
return(TRUE)
}
#' Authenticates against Azure Active directory application using DeviceCode flow.
#' Get Azure token using DeviceCode.
#'
#' @inheritParams setAzureContext
#' @param verbose Print Tracing information (Default False)
@ -152,16 +161,26 @@ azureGetTokenDeviceCode <- function(azureActiveContext, tenantID, clientID, reso
stopWithAzureError(r)
j1 <- content(r, "parsed", encoding = "UTF-8")
print(class(j1))
# display the message to user so that he can take appropriate action
showDeviceCodeMessageToUser(j1)
userCode <- j1$user_code
deviceCode <- j1$device_code
verificationURL <- j1$verification_url
messageToUser <- j1$message
expiresIn <- j1$expires_in
pollingInterval <- j1$interval
# wait_for_azure(
# sa_name %in% azureListSA(asc)$storageAccount
# )
iteration <- 0
waiting <- TRUE
while (iteration < 50 && waiting) {
Sys.sleep(pollingInterval)
if(azureGetTokenDeviceCodeFetch(azureActiveContext, tenantID, clientID, deviceCode, resource, verbose)) {
waiting <- FALSE
}
iteration <- iteration + 1
}
return(TRUE)
}
@ -188,20 +207,20 @@ azureGetTokenDeviceCodeFetch <- function(azureActiveContext, tenantID, clientID,
if (missing(tenantID)) tenantID <- azureActiveContext$tenantID
if (missing(clientID)) clientID <- azureActiveContext$clientID
if (missing(deviceCode)) deviceCode <- azureActiveContext$authKey
if (missing(deviceCode)) deviceCode <- azureActiveContext$deviceCode
if (missing(resource)) resource <- azureActiveContext$resource
assert_that(is_tenant_id(tenantID))
assert_that(is_client_id(clientID))
# TODO: check device code?
verbosity <- set_verbosity(verbose)
URLGT <- paste0("https://login.microsoftonline.com/", tenantID, "/oauth2/token?api-version=1.0")
authKeyEncoded <- URLencode(authKey, reserved = TRUE)
deviceCodeEncoded <- URLencode(deviceCode, reserved = TRUE)
resourceEncoded <- URLencode(resource, reserved = TRUE)
bodyGT <- paste0("grant_type=client_credentials&resource=", resourceEncoded, "&client_id=",
clientID, "&client_secret=", authKeyEncoded)
bodyGT <- paste0("grant_type=device_code&code=", deviceCodeEncoded,
"&client_id=", clientID, "&resource=", resourceEncoded)
r <- httr::POST(URLGT,
add_headers(
@ -209,18 +228,77 @@ azureGetTokenDeviceCodeFetch <- function(azureActiveContext, tenantID, clientID,
`Content-type` = "application/x-www-form-urlencoded")),
body = bodyGT,
verbosity)
# handle special error case
if(status_code(r) == 400) {
rr <- content(r)
if (rr$error == "authorization_pending") {
print("polled AAD for token, got authorization_pending (still waiting for user to complete login)")
return(FALSE)
}
}
stopWithAzureError(r)
j1 <- content(r, "parsed", encoding = "UTF-8")
azToken <- paste("Bearer", j1$access_token)
azRefreshToken <- j1$refresh_token
azureActiveContext$Token <- azToken
azureActiveContext$tenantID <- tenantID
azureActiveContext$clientID <- clientID
azureActiveContext$authKey <- authKey
azureActiveContext$EXPIRY <- Sys.time() + 3598
azureActiveContext$resource <- resource
azureActiveContext$RefreshToken <- azRefreshToken
return(TRUE)
}
#' Get Azure token using RefreshToken
#'
#' @inheritParams setAzureContext
#' @param resource Specify the resource with which the token is obtained
#' @param verbose Print Tracing information (Default False)
#'
#' @note See \url{https://azure.microsoft.com/en-us/documentation/articles/resource-group-create-service-principal-portal/} for instructions to set up an Active Directory application
#' @references \url{https://azure.microsoft.com/en-us/documentation/articles/resource-group-create-service-principal-portal/}
#'
#' @return If successful, returns TRUE
#' @family Azure resource functions
#'
#' @export
azureGetTokenRefreshToken <- function(azureActiveContext, tenantID, refreshToken, verbose = FALSE) {
assert_that(is.azureActiveContext(azureActiveContext))
if (missing(tenantID)) tenantID <- azureActiveContext$tenantID
if (missing(refreshToken)) refreshToken <- azureActiveContext$RefreshToken
assert_that(is_tenant_id(tenantID))
assert_that(is_client_id(clientID))
# TODO: need another validate function
#assert_that(is_authKey(refreshToken))
verbosity <- set_verbosity(verbose)
URLGT <- paste0("https://login.microsoftonline.com/", tenantID, "/oauth2/token?api-version=1.0")
refreshTokenEncoded <- URLencode(refreshToken, reserved = TRUE)
bodyGT <- paste0("grant_type=refresh_token&refresh_token=", refreshTokenEncoded)
r <- httr::POST(URLGT,
add_headers(
.headers = c(`Content-type` = "application/x-www-form-urlencoded")),
body = bodyGT,
verbosity)
stopWithAzureError(r)
j1 <- content(r, "parsed", encoding = "UTF-8")
azToken <- paste("Bearer", j1$access_token)
azRefreshToken <- j1$refresh_token
azureActiveContext$Token <- azToken
azureActiveContext$tenantID <- tenantID
azureActiveContext$clientID <- clientID
azureActiveContext$EXPIRY <- Sys.time() + 3598
azureActiveContext$RefreshToken <- azRefreshToken
return(TRUE)
}

Просмотреть файл

@ -42,6 +42,8 @@ createAzureContext <- function(tenantID, clientID, authKey, configFile, authType
#' @param azureActiveContext A container used for caching variables used by `AzureSMR`, created by [createAzureContext()]
#' @param tenantID The tenant ID provided during creation of the Active Directory application / service principal
#' @param clientID The client ID provided during creation of the Active Directory application / service principal
#' @param authType Auth type for getting token: "ClientCredential", "DeviceCode"
#' @param resource Resource to use for getting token
#' @param authKey The authentication key provided during creation of the Active Directory application / service principal
#' @param subscriptionID Subscription ID. This is obtained automatically by [azureAuthenticate()] when only a single subscriptionID is available via Active Directory
#' @param resourceGroup Name of the resource group
@ -55,8 +57,6 @@ createAzureContext <- function(tenantID, clientID, authKey, configFile, authType
#' @param hdiPassword HDInsight admin password. See [azureCreateHDI()]
#' @param container Storage container name. See [azureListStorageContainers()]
#' @param kind HDinsight kind: "hadoop","spark" or "rserver". See [azureCreateHDI()]
#' @param authType Auth type for getting token: "ClientCredential", "DeviceCode"
#' @param resource Resource to use for getting token
#'
#' @family azureActiveContext functions
#' @export

Просмотреть файл

@ -40,5 +40,6 @@ Other Azure resource functions: \code{\link{azureAuthenticateOnAuthType}},
\code{\link{azureCheckToken}},
\code{\link{azureGetTokenClientCredential}},
\code{\link{azureGetTokenDeviceCodeFetch}},
\code{\link{azureGetTokenDeviceCode}}
\code{\link{azureGetTokenDeviceCode}},
\code{\link{azureGetTokenRefreshToken}}
}

Просмотреть файл

@ -27,5 +27,6 @@ Other Azure resource functions: \code{\link{azureAuthenticate}},
\code{\link{azureCheckToken}},
\code{\link{azureGetTokenClientCredential}},
\code{\link{azureGetTokenDeviceCodeFetch}},
\code{\link{azureGetTokenDeviceCode}}
\code{\link{azureGetTokenDeviceCode}},
\code{\link{azureGetTokenRefreshToken}}
}

Просмотреть файл

@ -17,5 +17,6 @@ Other Azure resource functions: \code{\link{azureAuthenticateOnAuthType}},
\code{\link{azureAuthenticate}},
\code{\link{azureGetTokenClientCredential}},
\code{\link{azureGetTokenDeviceCodeFetch}},
\code{\link{azureGetTokenDeviceCode}}
\code{\link{azureGetTokenDeviceCode}},
\code{\link{azureGetTokenRefreshToken}}
}

Просмотреть файл

@ -2,7 +2,7 @@
% Please edit documentation in R/AzureAuthenticate.R
\name{azureGetTokenClientCredential}
\alias{azureGetTokenClientCredential}
\title{Get Azure token}
\title{Get Azure token using client credentials}
\usage{
azureGetTokenClientCredential(azureActiveContext, tenantID, clientID, authKey,
resource, verbose = FALSE)
@ -24,7 +24,7 @@ azureGetTokenClientCredential(azureActiveContext, tenantID, clientID, authKey,
If successful, returns TRUE
}
\description{
Get Azure token
Get Azure token using client credentials
}
\note{
See \url{https://azure.microsoft.com/en-us/documentation/articles/resource-group-create-service-principal-portal/} for instructions to set up an Active Directory application
@ -37,5 +37,6 @@ Other Azure resource functions: \code{\link{azureAuthenticateOnAuthType}},
\code{\link{azureAuthenticate}},
\code{\link{azureCheckToken}},
\code{\link{azureGetTokenDeviceCodeFetch}},
\code{\link{azureGetTokenDeviceCode}}
\code{\link{azureGetTokenDeviceCode}},
\code{\link{azureGetTokenRefreshToken}}
}

Просмотреть файл

@ -2,7 +2,7 @@
% Please edit documentation in R/AzureAuthenticate.R
\name{azureGetTokenDeviceCode}
\alias{azureGetTokenDeviceCode}
\title{Authenticates against Azure Active directory application using DeviceCode flow.}
\title{Get Azure token using DeviceCode.}
\usage{
azureGetTokenDeviceCode(azureActiveContext, tenantID, clientID, resource,
verbose = FALSE)
@ -22,7 +22,7 @@ azureGetTokenDeviceCode(azureActiveContext, tenantID, clientID, resource,
If successful, returns TRUE
}
\description{
Authenticates against Azure Active directory application using DeviceCode flow.
Get Azure token using DeviceCode.
}
\note{
See \url{https://azure.microsoft.com/en-us/documentation/articles/resource-group-create-service-principal-portal/} for instructions to set up an Active Directory application
@ -35,5 +35,6 @@ Other Azure resource functions: \code{\link{azureAuthenticateOnAuthType}},
\code{\link{azureAuthenticate}},
\code{\link{azureCheckToken}},
\code{\link{azureGetTokenClientCredential}},
\code{\link{azureGetTokenDeviceCodeFetch}}
\code{\link{azureGetTokenDeviceCodeFetch}},
\code{\link{azureGetTokenRefreshToken}}
}

Просмотреть файл

@ -35,5 +35,6 @@ Other Azure resource functions: \code{\link{azureAuthenticateOnAuthType}},
\code{\link{azureAuthenticate}},
\code{\link{azureCheckToken}},
\code{\link{azureGetTokenClientCredential}},
\code{\link{azureGetTokenDeviceCode}}
\code{\link{azureGetTokenDeviceCode}},
\code{\link{azureGetTokenRefreshToken}}
}

Просмотреть файл

@ -0,0 +1,38 @@
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/AzureAuthenticate.R
\name{azureGetTokenRefreshToken}
\alias{azureGetTokenRefreshToken}
\title{Get Azure token using RefreshToken}
\usage{
azureGetTokenRefreshToken(azureActiveContext, tenantID, refreshToken,
verbose = FALSE)
}
\arguments{
\item{azureActiveContext}{A container used for caching variables used by \code{AzureSMR}, created by \code{\link[=createAzureContext]{createAzureContext()}}}
\item{tenantID}{The tenant ID provided during creation of the Active Directory application / service principal}
\item{verbose}{Print Tracing information (Default False)}
\item{resource}{Specify the resource with which the token is obtained}
}
\value{
If successful, returns TRUE
}
\description{
Get Azure token using RefreshToken
}
\note{
See \url{https://azure.microsoft.com/en-us/documentation/articles/resource-group-create-service-principal-portal/} for instructions to set up an Active Directory application
}
\references{
\url{https://azure.microsoft.com/en-us/documentation/articles/resource-group-create-service-principal-portal/}
}
\seealso{
Other Azure resource functions: \code{\link{azureAuthenticateOnAuthType}},
\code{\link{azureAuthenticate}},
\code{\link{azureCheckToken}},
\code{\link{azureGetTokenClientCredential}},
\code{\link{azureGetTokenDeviceCodeFetch}},
\code{\link{azureGetTokenDeviceCode}}
}