Documentation update only:
- Clarify that you can use `get_managed_token` to obtain tokens with a user-defined identity, not just a system identity
- Clarify the distinction between authentication and authorization in the `get_azure_token` help, and also in the Shiny vignette
This commit is contained in:
Hong Ooi 2021-09-03 14:50:36 +10:00 коммит произвёл GitHub
Родитель 4fac88b31d
Коммит 85898d1908
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
6 изменённых файлов: 85 добавлений и 32 удалений

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

@ -1,6 +1,6 @@
Package: AzureAuth
Title: Authentication Services for Azure Active Directory
Version: 1.3.2
Version: 1.3.2.9000
Authors@R: c(
person("Hong", "Ooi", , "hongooi73@gmail.com", role = c("aut", "cre")),
person("Tyler", "Littlefield", role="ctb"),

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

@ -1,3 +1,9 @@
# AzureAuth 1.3.2.9000
- Documentation update only:
- Clarify that you can use `get_managed_token` to obtain tokens with a user-defined identity, not just a system identity
- Clarify the distinction between authentication and authorization in the `get_azure_token` help, and also in the Shiny vignette
# AzureAuth 1.3.2
- Change the default caching behaviour to disable the cache if running inside Shiny.

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

@ -10,7 +10,7 @@
#' @param certificate A file containing the certificate for authenticating with (including the private key), an Azure Key Vault certificate object, or a call to the `cert_assertion` function to build a client assertion with a certificate. See 'Certificate authentication' below.
#' @param auth_type The authentication type. See 'Details' below.
#' @param aad_host URL for your AAD host. For the public Azure cloud, this is `https://login.microsoftonline.com/`. Change this if you are using a government or private cloud. Can also be a full URL, eg `https://mydomain.b2clogin.com/mydomain/other/path/names/oauth2` (this is relevant mainly for Azure B2C logins).
#' @param version The AAD version, either 1 or 2. Authenticating with a personal account as opposed to a work or school account requires AAD 2.0.
#' @param version The AAD version, either 1 or 2. Authenticating with a personal account as opposed to a work or school account requires AAD 2.0. The default is AAD 1.0 for compatibility reasons, but you should use AAD 2.0 if possible.
#' @param authorize_args An optional list of further parameters for the AAD authorization endpoint. These will be included in the request URI as query parameters. Only used if `auth_type="authorization_code"`.
#' @param token_args An optional list of further parameters for the token endpoint. These will be included in the body of the request for `get_azure_token`, or as URI query parameters for `get_managed_token`.
#' @param use_cache If TRUE and cached credentials exist, use them instead of obtaining a new token. The default value of NULL means to use the cache only if AzureAuth is not running inside a Shiny app.
@ -23,6 +23,8 @@
#'
#' `get_managed_token` is a specialised function to acquire tokens for a _managed identity_. This is an Azure service, such as a VM or container, that has been assigned its own identity and can be granted access permissions like a regular user. The advantage of managed identities over the other authentication methods (see below) is that you don't have to store a secret password, which improves security. Note that `get_managed_token` can only be used from within the managed identity itself.
#'
#' By default `get_managed_token` retrieves a token using the system-assigned identity for the resource. To obtain a token with a user-assigned identity, pass either the client, object or Azure resource ID in the `token_args` argument. See the examples below.
#'
#' The `resource` arg should be a single URL or GUID for AAD v1.0. For AAD v2.0, it should be a vector of _scopes_, where each scope consists of a URL or GUID along with a path that designates the type of access requested. If a v2.0 scope doesn't have a path, `get_azure_token` will append the `/.default` path with a warning. A special scope is `offline_access`, which requests a refresh token from AAD along with the access token: without this scope, you will have to reauthenticate if you want to refresh the token.
#'
#' The `auth_code` and `device_creds` arguments are intended for use in embedded scenarios, eg when AzureAuth is loaded from within a Shiny web app. They enable the flow authorization step to be separated from the token acquisition step, which is necessary within an app; you can generally ignore these arguments when using AzureAuth interactively or as part of an R script. See the help for [build_authorization_uri] for examples on their use.
@ -64,10 +66,20 @@
#' | `organizations` | Allows only users with work/school accounts from Azure AD to sign into the application. |
#' | `consumers` | Allows only users with personal Microsoft accounts (MSA) to sign into the application. |
#'
#' @section OpenID Connect:
#' `get_azure_token` can be used to obtain ID tokens along with regular OAuth access tokens, when using an interactive authentication flow (authorization_code or device_code). The behaviour depends on the AAD version:
#' @section Authentication vs authorization:
#' Azure Active Directory can be used for two purposes: _authentication_ (verifying that a user is who they claim they are) and _authorization_ (granting a user permission to access a resource). In AAD, a successful authorization process concludes with the granting of an OAuth 2.0 access token, as discussed above. Authentication uses the same process but concludes by granting an ID token, as defined in the OpenID Connect protocol.
#'
#' `get_azure_token` can be used to obtain ID tokens along with regular OAuth access tokens, when using an interactive flow (authorization_code or device_code). The behaviour depends on the AAD version:
#'
#' When retrieving ID tokens, the behaviour depends on the AAD version:
#' - AAD v1.0 will return an ID token as well as the access token by default; you don't have to do anything extra. However, AAD v1.0 will not _refresh_ the ID token when it expires; you must reauthenticate to get a new one. To ensure you don't pull the cached version of the credentials, specify `use_cache=FALSE` in the calls to `get_azure_token`.
#' - Unlike AAD v1.0, AAD v2.0 does not return an ID token by default. To get a token, specify `openid` as a scope. On the other hand it _does_ refresh the ID token, so bypassing the cache is not needed. It's recommended to use AAD v2.0 if you only want an ID token.
#' - Unlike AAD v1.0, AAD v2.0 does not return an ID token by default. To get a token, include `openid` as a scope. On the other hand it _does_ refresh the ID token, so bypassing the cache is not needed. It's recommended to use AAD v2.0 if you only want an ID token.
#'
#' If you _only_ want to do authentication and not authorization (for example if your app does not use any Azure resources), specify the `resource` argument as follows:
#' - For AAD v1.0, use a blank resource (`resource=""`).
#' - For AAD v2.0, use `resource="openid"` without any other elements. Optionally you can add `"offline_access"` as a 2nd element if you want a refresh token as well.
#'
#' See also the examples below.
#'
#' @section Caching:
#' AzureAuth caches tokens based on all the inputs to `get_azure_token` as listed above. Tokens are cached in a custom, user-specific directory, created with the rappdirs package. On recent Windows versions, this will usually be in the location `C:\\Users\\(username)\\AppData\\Local\\AzureR`. On Linux, it will be in `~/.config/AzureR`, and on MacOS, it will be in `~/Library/Application Support/AzureR`. Alternatively, you can specify the location of the directory in the environment variable `R_AZURE_DATA_DIR`. Note that a single directory is used for all tokens, and the working directory is not touched (which significantly lessens the risk of accidentally introducing cached tokens into source control).
@ -97,6 +109,7 @@
#' [build_authorization_uri], [get_device_creds]
#'
#' [Azure Active Directory for developers](https://docs.microsoft.com/en-us/azure/active-directory/develop/),
#' [Managed identities overview](https://docs.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/overview)
#' [Device code flow on OAuth.com](https://www.oauth.com/oauth2-servers/device-flow/token-request/),
#' [OAuth 2.0 RFC](https://tools.ietf.org/html/rfc6749) for the gory details on how OAuth works
#'
@ -199,6 +212,12 @@
#' # get a token from within a managed identity (VM, container or service)
#' get_managed_token("https://management.azure.com/")
#'
#' # get a token from a managed identity, with a user-defined identity:
#' # specify one of the identity's object_id, client_id and mi_res_id (Azure resource ID)
#' # you can get these values via the Azure Portal or Azure CLI
#' get_managed_token("https://management.azure.com/", token_args=list(
#' mi_res_id="/subscriptions/zzzz-zzzz/resourceGroups/resgroupname/..."
#' ))
#'
#' # use a refresh token from one resource to get an access token for another resource
#' tok <- get_azure_token("https://myresource", "mytenant", "app_id")

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

@ -98,7 +98,7 @@ is_azure_v2_token(object)
\item{aad_host}{URL for your AAD host. For the public Azure cloud, this is \verb{https://login.microsoftonline.com/}. Change this if you are using a government or private cloud. Can also be a full URL, eg \verb{https://mydomain.b2clogin.com/mydomain/other/path/names/oauth2} (this is relevant mainly for Azure B2C logins).}
\item{version}{The AAD version, either 1 or 2. Authenticating with a personal account as opposed to a work or school account requires AAD 2.0.}
\item{version}{The AAD version, either 1 or 2. Authenticating with a personal account as opposed to a work or school account requires AAD 2.0. The default is AAD 1.0 for compatibility reasons, but you should use AAD 2.0 if possible.}
\item{authorize_args}{An optional list of further parameters for the AAD authorization endpoint. These will be included in the request URI as query parameters. Only used if \code{auth_type="authorization_code"}.}
@ -122,6 +122,8 @@ Use these functions to authenticate with Azure Active Directory (AAD).
\code{get_managed_token} is a specialised function to acquire tokens for a \emph{managed identity}. This is an Azure service, such as a VM or container, that has been assigned its own identity and can be granted access permissions like a regular user. The advantage of managed identities over the other authentication methods (see below) is that you don't have to store a secret password, which improves security. Note that \code{get_managed_token} can only be used from within the managed identity itself.
By default \code{get_managed_token} retrieves a token using the system-assigned identity for the resource. To obtain a token with a user-assigned identity, pass either the client, object or Azure resource ID in the \code{token_args} argument. See the examples below.
The \code{resource} arg should be a single URL or GUID for AAD v1.0. For AAD v2.0, it should be a vector of \emph{scopes}, where each scope consists of a URL or GUID along with a path that designates the type of access requested. If a v2.0 scope doesn't have a path, \code{get_azure_token} will append the \verb{/.default} path with a warning. A special scope is \code{offline_access}, which requests a refresh token from AAD along with the access token: without this scope, you will have to reauthenticate if you want to refresh the token.
The \code{auth_code} and \code{device_creds} arguments are intended for use in embedded scenarios, eg when AzureAuth is loaded from within a Shiny web app. They enable the flow authorization step to be separated from the token acquisition step, which is necessary within an app; you can generally ignore these arguments when using AzureAuth interactively or as part of an R script. See the help for \link{build_authorization_uri} for examples on their use.
@ -168,13 +170,25 @@ There are 3 generic values that can be used as tenants when authenticating:\tabu
}
}
\section{OpenID Connect}{
\section{Authentication vs authorization}{
\code{get_azure_token} can be used to obtain ID tokens along with regular OAuth access tokens, when using an interactive authentication flow (authorization_code or device_code). The behaviour depends on the AAD version:
Azure Active Directory can be used for two purposes: \emph{authentication} (verifying that a user is who they claim they are) and \emph{authorization} (granting a user permission to access a resource). In AAD, a successful authorization process concludes with the granting of an OAuth 2.0 access token, as discussed above. Authentication uses the same process but concludes by granting an ID token, as defined in the OpenID Connect protocol.
\code{get_azure_token} can be used to obtain ID tokens along with regular OAuth access tokens, when using an interactive flow (authorization_code or device_code). The behaviour depends on the AAD version:
When retrieving ID tokens, the behaviour depends on the AAD version:
\itemize{
\item AAD v1.0 will return an ID token as well as the access token by default; you don't have to do anything extra. However, AAD v1.0 will not \emph{refresh} the ID token when it expires; you must reauthenticate to get a new one. To ensure you don't pull the cached version of the credentials, specify \code{use_cache=FALSE} in the calls to \code{get_azure_token}.
\item Unlike AAD v1.0, AAD v2.0 does not return an ID token by default. To get a token, specify \code{openid} as a scope. On the other hand it \emph{does} refresh the ID token, so bypassing the cache is not needed. It's recommended to use AAD v2.0 if you only want an ID token.
\item Unlike AAD v1.0, AAD v2.0 does not return an ID token by default. To get a token, include \code{openid} as a scope. On the other hand it \emph{does} refresh the ID token, so bypassing the cache is not needed. It's recommended to use AAD v2.0 if you only want an ID token.
}
If you \emph{only} want to do authentication and not authorization (for example if your app does not use any Azure resources), specify the \code{resource} argument as follows:
\itemize{
\item For AAD v1.0, use a blank resource (\code{resource=""}).
\item For AAD v2.0, use \code{resource="openid"} without any other elements. Optionally you can add \code{"offline_access"} as a 2nd element if you want a refresh token as well.
}
See also the examples below.
}
\section{Caching}{
@ -305,6 +319,12 @@ extract_jwt(tok2, "id")
# get a token from within a managed identity (VM, container or service)
get_managed_token("https://management.azure.com/")
# get a token from a managed identity, with a user-defined identity:
# specify one of the identity's object_id, client_id and mi_res_id (Azure resource ID)
# you can get these values via the Azure Portal or Azure CLI
get_managed_token("https://management.azure.com/", token_args=list(
mi_res_id="/subscriptions/zzzz-zzzz/resourceGroups/resgroupname/..."
))
# use a refresh token from one resource to get an access token for another resource
tok <- get_azure_token("https://myresource", "mytenant", "app_id")
@ -332,6 +352,7 @@ httr::GET("https://myresource/path/for/call", header, ...)
\link{build_authorization_uri}, \link{get_device_creds}
\href{https://docs.microsoft.com/en-us/azure/active-directory/develop/}{Azure Active Directory for developers},
\href{https://docs.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/overview}{Managed identities overview}
\href{https://www.oauth.com/oauth2-servers/device-flow/token-request/}{Device code flow on OAuth.com},
\href{https://tools.ietf.org/html/rfc6749}{OAuth 2.0 RFC} for the gory details on how OAuth works
}

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

@ -19,15 +19,20 @@ library(AzureAuth)
library(shiny)
library(shinyjs)
resource <- "https://management.azure.com"
tenant <- "your-tenant-here"
app <- "your-app-id-here"
# the Azure resource permissions needed
# if your app doesn't use any Azure resources (you only want to do authentication),
# set the resource to "openid" only
resource <- c("https://management.azure.com/.default", "openid")
# set this to the site URL of your app once it is deployed
# this must also be the redirect for your registered app in Azure Active Directory
redirect <- "http://localhost:8100"
options(shiny.port=as.numeric(httr::parse_url(redirect)$port))
port <- httr::parse_url(redirect)$port
options(shiny.port=if(is.null(port)) 80 else as.numeric(port))
# replace this with your app's regular UI
ui <- fluidPage(
@ -40,7 +45,7 @@ ui_func <- function(req)
opts <- parseQueryString(req$QUERY_STRING)
if(is.null(opts$code))
{
auth_uri <- build_authorization_uri(resource, tenant, app, redirect_uri=redirect)
auth_uri <- build_authorization_uri(resource, tenant, app, redirect_uri=redirect, version=2)
redir_js <- sprintf("location.replace(\"%s\");", auth_uri)
tags$script(HTML(redir_js))
}
@ -71,7 +76,7 @@ server <- function(input, output, session)
# this assumes your app has a 'public client/native' redirect:
# if it is a 'web' redirect, include the client secret as the password argument
token <- get_azure_token(resource, tenant, app, auth_type="authorization_code",
authorize_args=list(redirect_uri=redirect),
authorize_args=list(redirect_uri=redirect), version=2,
use_cache=FALSE, auth_code=opts$code)
output$token <- renderPrint(token)

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

@ -136,6 +136,27 @@ get_managed_token("myresource")
Using the interactive flows (authorization_code and device_code) from within a Shiny app requires separating the authorization (logging in to Azure) step from the token acquisition step. For this purpose, AzureAuth provides the `build_authorization_uri` and `get_device_creds` functions. You can use these from within your app to carry out the authorization, and then pass the resulting credentials to `get_azure_token` itself. See the "Authenticating from Shiny" vignette for an example app.
## Authentication vs authorization:
Azure Active Directory can be used for two purposes: _authentication_ (verifying that a user is who they claim they are) and _authorization_ (granting a user permission to access a resource). In AAD, a successful authorization process concludes with the granting of an OAuth 2.0 access token, as discussed above. Authentication uses the same process but concludes by granting an ID token, as defined in the OpenID Connect protocol.
You can use `get_azure_token` to obtain ID tokens, in addition to access tokens.
With AAD v1.0, using an interactive authentication flow (authorization_code or device_code) will return an ID token by default -- you don't have to do anything extra. However, AAD v1.0 will _not_ refresh the ID token when it expires (only the access token). Because of this, specify `use_cache=FALSE` to avoid picking up cached token credentials which may have been refreshed previously.
AAD v2.0 does not return an ID token by default, but you can get one by specifying `openid` as a scope. Again, this applies only to interactive authentication. If you only want an ID token, it's recommended to use AAD v2.0.
```r
# ID token with AAD v1.0
# if you only want an ID token, set the resource to blank ("")
tok <- get_azure_token("", "mytenant", "app_id")
extract_token(tok, "id")
# ID token with AAD v2.0
tok2 <- get_azure_token(c("openid", "offline_access"), "mytenant", "app_id", version=2)
extract_token(tok2, "id")
```
## Caching
AzureAuth caches tokens based on all the inputs to `get_azure_token`, as listed above. It defines its own directory for cached tokens, using the rappdirs package. On recent Windows versions, this will usually be in the location `C:\Users\(username)\AppData\Local\AzureR`. On Linux, it will be in `~/.local/share/AzureR`, and on MacOS, it will be in `~/Library/Application Support/AzureR`. Note that a single directory is used for all tokens, and the working directory is not touched (which significantly lessens the risk of accidentally introducing cached tokens into source control).
@ -163,25 +184,6 @@ If you want to bypass the cache, specify `use_cache=FALSE` in the call to `get_a
get_azure_token("myresource", "mytenant", "app_id", use_cache=FALSE)
```
## OpenID Connect
You can also use `get_azure_token` to obtain ID tokens, in addition to access tokens.
With AAD v1.0, using an interactive authentication flow (authorization_code or device_code) will return an ID token by default -- you don't have to do anything extra. However, AAD v1.0 will _not_ refresh the ID token when it expires (only the access token). Because of this, specify `use_cache=FALSE` to avoid picking up cached token credentials which may have been refreshed previously.
AAD v2.0 does not return an ID token by default, but you can get one by specifying `openid` as a scope. Again, this applies only to interactive authentication. If you only want an ID token, it's recommended to use AAD v2.0.
```r
# ID token with AAD v1.0
# if you only want an ID token, set the resource to blank ("")
tok <- get_azure_token("", "mytenant", "app_id")
extract_token(tok, "id")
# ID token with AAD v2.0
tok2 <- get_azure_token(c("openid", "offline_access"), "mytenant", "app_id", version=2)
extract_token(tok2, "id")
```
## Refreshing
A token object can be refreshed by calling its `refresh()` method. If the token's credentials contain a refresh token, this is used; otherwise a new access token is obtained by reauthenticating. In most situations you don't need to worry about this, as the AzureR packages will check if the credentials have expired and automatically refresh them for you.