Skip to contents

Check a returning login request and exchange the provider's temporary authorization code for an OAuthToken (OAuth 2.0 Authorization Code flow). Use this in a custom callback handler after starting authorization with prepare_call(). It applies shinyOAuth's state, token, and configured identity checks while your application manages the HTTP callback and stores the returned token. oauth_module_server() handles these responsibilities for Shiny sessions.

Usage

handle_callback(
  client,
  code,
  state,
  browser_token,
  shiny_session = NULL,
  iss = NULL,
  oauth_client = NULL,
  payload = NULL
)

Arguments

client

An OAuthClient object.

code

Authorization code received from the provider on a classic direct callback.

state

Encrypted state payload returned by the provider on a classic direct callback. This should be the same value that was originally sent in prepare_call().

browser_token

Browser token present in the user's session. This is usually managed by oauth_module_server().

shiny_session

Optional captured Shiny session details for audit events. Normally supplied by the module; leave NULL when calling directly.

iss

Optional RFC 9207 callback issuer (iss) from the authorization response. Pass this when one callback URL can receive responses from more than one authorization server. If client@enforce_callback_issuer is TRUE, this parameter is required and must match the configured provider issuer before any token exchange occurs.

This low-level API cannot verify which redirect URI received the response. Clients configured with authorization_server_mode = "multi_redirect_uri" must use oauth_module_server() instead.

oauth_client

Compatibility alias for client. Supply only one spelling.

payload

Compatibility alias for state. Supply only one spelling.

Value

An OAuthToken object. If callback validation, token exchange, or token verification fails, the function raises an error.

Details

Pass the returned code, the callback's state, and the browser token saved for this login. This helper accepts direct code/state callbacks only. For signed responses using JWT Secured Authorization Response Mode (JARM; "jwt", "query.jwt", or "form_post.jwt"), use oauth_module_server() and, for POST responses, oauth_form_post_ui(). There is no public JARM resume API.

Examples

# Advanced example: your code supplies browser redirects and callback handling.
# For a Shiny app, oauth_module_server() manages these steps for you.

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"
  )

  # Get the login URL and store state in client's state store
  # `<browser_token>` must be unpredictable and persisted for this transaction
  # in storage bound to the application's exact origin (scheme, host, port).
  # The module combines origin-scoped storage with an independent marker cookie
  # and checks both on return. A cookie alone does not provide this boundary:
  # cookies can be shared by applications on different ports of the same host.
  # Shiny applications should use oauth_module_server() for the complete flow.
  authorization_url <- prepare_call(client, "<browser_token>")

  # Redirect user to authorization URL; retrieve code & state from the query;
  # recover this transaction's `<browser_token>` through the origin-bound flow
  # and verify its independent marker before calling handle_callback().
  code <- "..."
  state <- "..."
  browser_token <- "..."

  # Handle callback, exchanging code for token and validating state
  token <- handle_callback(client, code, state, browser_token)
}