Refreshes an OAuth session by obtaining a new access token with the refresh token. When configured, shinyOAuth also re-fetches userinfo and validates any new ID token returned by the provider.
Per OIDC Core Section 12.2, providers may omit the ID token from refresh responses. When omitted, the original ID token from the initial login is preserved.
If the provider does return a new ID token during refresh, refresh_token()
requires that an original ID token from the initial login is available so it
can enforce subject continuity (OIDC 12.2: sub MUST match). If no original
ID token is available, refresh fails with an error.
When id_token_validation = TRUE, any refresh-returned ID token is also
fully validated (signature and claims) in addition to the OIDC 12.2 sub
continuity check.
When userinfo_required = TRUE, userinfo is re-fetched using the fresh
access token. Whenever shinyOAuth has both refreshed userinfo and a
validated ID token baseline, it checks that their sub claims still match.
If userinfo_id_token_match = TRUE, the absence of a trustworthy ID token
baseline is treated as an error instead of silently accepting unbound
userinfo data.
Arguments
- oauth_client
OAuthClient object
- token
OAuthToken object containing the refresh token
- async
Logical, default FALSE. If TRUE and an async backend is configured, the refresh is dispatched through shinyOAuth's async promise path and this function returns a promise-compatible async result that resolves to an updated
OAuthToken. mirai::mirai is preferred when daemons are configured viamirai::daemons(); otherwise the current future::future plan is used. Non-sequential future plans run off the main R session;future::sequential()stays in-process.- introspect
Logical, default FALSE. After a successful refresh, if the provider exposes an introspection endpoint, introspect the new access token for validation and audit/diagnostics. When enabled, refresh fails if introspection is unsupported, inactive, or missing required
introspect_elements. The raw introspection result is not stored separately, but a successful introspection response may backfilltoken@cnf.- shiny_session
Optional pre-captured Shiny session context (from
capture_shiny_session_context()) to include in audit events. Used when calling from async workers that lack access to the reactive domain.
Value
An updated OAuthToken object with refreshed credentials.
What changes:
access_token: Always updated to the fresh tokenexpires_at: Computed fromexpires_inwhen provided; otherwise a finite fallback expiry fromresolve_missing_expires_in()refresh_token: Updated if the provider rotates it; otherwise preservedid_token: Updated only if the provider returns one (and it validates); otherwise the original from login is preserveduserinfo: Refreshed ifuserinfo_required = TRUE; otherwise preservedcnf: Updated from the token response when present, and may be backfilled from refresh-time introspection when enabled
Validation failures cause errors: If the provider returns a new ID
token that fails validation (wrong issuer, audience, expired, or subject
mismatch with original), or if userinfo subject doesn't match the new ID
token, the refresh fails with an error. In oauth_module_server(), this
clears the session and sets authenticated = FALSE.
Examples
# Please note: `get_userinfo()`, `introspect_token()`, and `refresh_token()`
# are typically not called by users of this package directly, but are called
# internally by `oauth_module_server()`. These functions are exported
# nonetheless for advanced use cases. Most users will not need to
# call these functions directly
# Example requires a real token from a completed OAuth flow
# (code is therefore not run; would error with placeholder values below)
if (interactive()) {
# Define client
client <- oauth_client(
provider = oauth_provider_github(),
client_id = Sys.getenv("GITHUB_OAUTH_CLIENT_ID"),
client_secret = Sys.getenv("GITHUB_OAUTH_CLIENT_SECRET"),
redirect_uri = "http://127.0.0.1:8100"
)
# Have a valid OAuthToken object; fake example below
# (typically provided by `oauth_module_server()` or `handle_callback()`)
token <- handle_callback(client, "<code>", "<payload>", "<browser_token>")
# Get userinfo
user_info <- get_userinfo(client, token)
# Introspect token (if supported by provider)
introspection <- introspect_token(client, token)
# Refresh token
new_token <- refresh_token(client, token, introspect = TRUE)
}