---
title: "Package options reference"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{Package options reference}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

## What package options are for

Package options control settings shared by the whole R process, including
network timeouts and diagnostic logging. `oauth_client()` and
`oauth_module_server()` arguments apply to one app registration or module.
The [Usage](usage.html) guide covers login setup.

## Set an option at app startup

For example, give a slow provider up to ten seconds per network request. Put
this near the top of `app.R`, before creating the provider and client:

```{r, eval = FALSE}
options(shinyOAuth.timeout = 10)
```

A longer timeout gives a slow provider more time to respond, but delays failure
when the service is unavailable. Restore the default with
`options(shinyOAuth.timeout = NULL)`.

Options affect every session sharing that R process; they are app-wide
settings rather than per-user settings.

Times use seconds unless a setting explicitly says milliseconds.

## Logging

These options control diagnostic events and the request details they contain.

- `options(shinyOAuth.audit_hook = function(event){ ... })` – receive structured audit and error events
- `options(shinyOAuth.audit_include_http = FALSE)` – exclude HTTP request details from audit events (default: `TRUE`)
- `options(shinyOAuth.audit_include_raw_session_token = TRUE)` – include the raw `shiny_session[["token"]]` in native audit-hook payloads. By default, hooks receive only `shiny_session[["session_token_digest"]]`
- `options(shinyOAuth.audit_redact_http = FALSE)` – disable automatic redaction of sensitive data in audit events (default: `TRUE`). Debug only: raw mode can expose cookies, authorization headers, codes, state values, and client IP addresses
- `options(shinyOAuth.telemetry_path_scrubber = function(path) NULL)` – return
  approved route labels for audit and OTel paths, which are omitted by default.
  Return `NULL` for unknown routes, remove identifying segments, and make the
  function idempotent.

- `options(shinyOAuth.audit_digest_key = ...)` – shared HMAC-SHA256 key of at
  least 32 bytes for audit/OTel correlation. The default is a random per-process
  key; invalid configured keys cause an error.

- `options(shinyOAuth.otel_tracing_enabled = FALSE)` – disable 'shinyOAuth' OpenTelemetry span creation and async trace-context propagation. Default: `TRUE`
- `options(shinyOAuth.otel_logging_enabled = FALSE)` – disable 'shinyOAuth' OpenTelemetry log emission. Default: `TRUE`
- `options(shinyOAuth.otel_include_authorization_details = TRUE)` – include raw scope names, claim targets, and ACR values in telemetry. Default: `FALSE` (counts only). These fields can reveal private information and produce many distinct telemetry values.

See [Audit logging](audit-logging.html) for R hook examples and
[OpenTelemetry](opentelemetry.html) for log and trace exporter setup.

## HTTP settings (timeout, retries, user agent)

Network settings limit request duration and response size.

- `options(shinyOAuth.tls_min_version = "1.2")` - require TLS 1.2 or later
  for package HTTPS requests (the default). Use `"1.3"` for a higher minimum;
  an absent option or `NULL` restores TLS 1.2. Set this before discovery or
  login. It applies to async workers too; browser and reverse-proxy TLS must
  be configured separately.

- `options(shinyOAuth.timeout = 5)` – default HTTP timeout (seconds) applied to all outbound requests
  (discovery, JWKS, token exchange, userinfo). Increase if your provider/network is slow. Values beyond
  curl's supported timeout range are capped
- `options(shinyOAuth.retry_max_tries = 3L)` – maximum attempts after network
  errors or HTTP 408, 429 or 5xx responses. Code exchange and refresh skip
  automatic retries, apart from one DPoP nonce-challenge retry.

- `options(shinyOAuth.dpop_nonce_max_bytes = 4096L)` – maximum DPoP nonce size
  in bytes; supported range 1 to 65536.

- `options(shinyOAuth.retry_backoff_base = 0.5)` – base backoff in seconds used for exponential backoff with jitter
- `options(shinyOAuth.retry_backoff_cap = 5)` – per‑attempt cap on backoff seconds (before jitter)
- `options(shinyOAuth.retry_after_cap = 60)` – maximum synchronous sleep in seconds for a server-provided `Retry-After` value; this is separate from the client-side backoff cap
- `options(shinyOAuth.retry_status = c(408L, 429L, 500:599))` – HTTP statuses considered transient and retried
- `options(shinyOAuth.user_agent = "shinyOAuth/<version> R/<version> httr2/<version>")` – override
  the HTTP User-Agent. The default includes the installed package and R versions.

- `options(shinyOAuth.allow_redirect = FALSE)` – reject redirects on sensitive
  provider requests by default. The opt-in permits redirects in all sessions,
  potentially forwarding codes, tokens or credentials to another destination.

- `options(shinyOAuth.max_body_bytes = 1048576)` - maximum response size
  (default 1 MiB) for package requests and connection calls.
  `perform_resource_req()` applies it to prepared requests as well as URLs.

## Async timeout (mirai)

A task timeout limits how long background work may run. Configure workers first,
as shown in [Usage](usage.html#asynchronous-execution).

- `options(shinyOAuth.async_timeout = 10000)` – per-task timeout in milliseconds for mirai async tasks.
  When using mirai with dispatcher (the default), timed-out tasks are automatically cancelled and resolve
  as a mirai error. Use `NULL` (the default) for no timeout, or a whole number from 0 to 2147483647.
  Ignored when falling back to the 'future' backend

## Async condition replay

Background workers can return warnings and messages to the app. Turn replay off
if another logging system already handles those diagnostics.

- `options(shinyOAuth.replay_async_conditions = FALSE)` – when `FALSE`, warnings and messages captured
  from async workers are silently discarded instead of being re-emitted on the main R process. Default is
  `TRUE` (replay all captured conditions). Useful if worker diagnostics are too noisy or handled
  separately via `audit_hook`

## Token lifetime fallback

Some providers omit the token lifetime. This fallback lets ordinary OAuth
clients track expiry in that case.

- `options(shinyOAuth.default_expires_in = 3600)` – fallback token lifetime (in seconds)
  when the provider omits `expires_in` from the token response

## Validation and URL policy

These settings control which token responses and addresses the app accepts.

- `options(shinyOAuth.access_token_cnf = "opaque")` – use `"opaque"` to avoid
  decoding access-token binding data. The compatibility default `"jwt"` reads
  `cnf` without signature verification.

- `options(shinyOAuth.leeway = 30)` – default clock skew leeway (seconds) for ID token `exp`/`iat`/`nbf` checks and state payload `issued_at` future check
- `options(shinyOAuth.max_id_token_lifetime = 86400)` – maximum ID token lifetime in seconds (`exp - iat`). This is an additional package check beyond the OIDC expiry check. Default `86400` (24 hours). Set to `Inf` to disable the check
- `options(shinyOAuth.allowed_non_https_hosts = c("localhost", "127.0.0.1", "::1", "[::1]"))` - allows these hosts to use `http://` in non-OIDC URL checks; it does not relax OIDC discovery
- `options(shinyOAuth.allow_insecure_oidc_loopback = TRUE)` – development-only opt-in for OIDC issuer and endpoint URLs on HTTP loopback origins; production OIDC metadata URLs must use HTTPS
- `options(shinyOAuth.allowed_hosts = c())` – when non-empty, restricts accepted hosts
  to this list
- `options(shinyOAuth.allow_hs = TRUE)` – opt‑in HMAC validation for ID tokens (HS256/HS384/HS512). Requires a strictly server‑side `client_secret` and exactly one HS algorithm in `id_token_allowed_algs`, binding the shared key to one algorithm (RFC 8725 section 3.1)
- `options(shinyOAuth.client_assertion_ttl = 120L)` – lifetime in seconds for JWT client assertions used with
  `client_secret_jwt` or `private_key_jwt` token endpoint authentication. Finite values below 60 seconds are coerced to
  60 seconds, finite values above 300 seconds are clamped to 300 seconds, and `NA` or non-finite values fall back to
  the 120-second default
- `options(shinyOAuth.state_fail_delay_ms = 0)` – delay before state-validation
  failures, in milliseconds. Default `0` adds no delay; one positive number sets
  a fixed delay, two set random bounds. Positive delays block R even with `async
  = TRUE`; they add timing noise rather than constant-time validation.

`allowed_hosts` patterns support globs (`*`, `?`). For example,
`c(".example.com")` matches the domain and its subdomains; `"*"` accepts any host.

## State store

Pending login records let the app recognize the returning browser. Shared
stores must consume each record only once, even when several R processes
handle requests.

- `options(shinyOAuth.allow_non_atomic_state_store = TRUE)` – allow separate
  reads and deletes in a shared store. Default `FALSE` requires atomic
  `[["take"]]()`. Enabling this can let concurrent requests reuse a login
  record; the default rejects this backend. See
  [custom_cache()](https://lukakoning.github.io/shinyOAuth/reference/custom_cache.html).

## Size caps

### State envelope

- `options(shinyOAuth.state_max_token_chars = 8192)` – maximum allowed length of the base64url-encoded `state` query parameter
- `options(shinyOAuth.state_max_wrapper_bytes = 8192)` – maximum decoded byte size of the outer JSON wrapper (before parsing)
- `options(shinyOAuth.state_max_ct_b64_chars = 8192)` – maximum allowed length of the base64url-encoded ciphertext inside the wrapper
- `options(shinyOAuth.state_max_ct_bytes = 8192)` – maximum decoded byte size of the ciphertext before attempting AES-GCM decrypt

These limits keep oversized state parameters from using excessive CPU or memory
during decoding and decryption.

### Callback query

- `options(shinyOAuth.callback_max_code_bytes = 8192)` – maximum decoded
  authorization-code bytes. Oversized values are rejected without truncation.

- `options(shinyOAuth.callback_max_state_bytes = 8192)` – maximum byte length of the `state` query parameter (outer token string)
- `options(shinyOAuth.callback_max_error_bytes = 256)` – maximum byte length of the `error` query parameter
- `options(shinyOAuth.callback_max_error_description_bytes = 4096)` – maximum byte length of the `error_description` query parameter
- `options(shinyOAuth.callback_max_error_uri_bytes = 2048)` – maximum byte length of the `error_uri` query parameter
- `options(shinyOAuth.callback_max_iss_bytes = 2048)` – maximum byte length of the `iss` query parameter (RFC 9207 issuer identification)
- `options(shinyOAuth.callback_max_query_bytes = <derived>)` – maximum raw query
  bytes. Applies before parsing to app queries, callbacks and hosted Request
  Objects.

- `options(shinyOAuth.callback_max_browser_token_bytes = 256)` – maximum byte length of the `browser_token` argument accepted by `handle_callback()`
- `options(shinyOAuth.callback_max_form_post_body_bytes = <derived>)` – maximum byte length of the raw `form_post` callback body before parsing
- `options(shinyOAuth.callback_max_form_post_handle_bytes = 128)` – maximum byte length of the transient `shinyOAuth_form_post` handle query parameter
- `options(shinyOAuth.callback_max_form_post_id_bytes = 256)` – maximum byte length of the transient `shinyOAuth_form_post_id` module-id query parameter

These limits reject oversized callback URLs and POST bodies before they cause
excessive processing or logging.

Generated login state must fit both `shinyOAuth.callback_max_state_bytes` and
the state envelope limits above. Their outer-token defaults both allow 8192
bytes (base64url state is ASCII). Lowering either limit can restrict ordinary
logins with many scopes or other state metadata. `prepare_call()` checks both
budgets before storing pending login state, publishing a Request Object, or
sending PAR.

## Configuration assessments

Use `check_oauth21(client)` to review settings without making requests or changing
the app. The report separates configuration problems, recommendations and things
that need deployment testing. See [check_oauth21()](https://lukakoning.github.io/shinyOAuth/reference/check_oauth21.html)
for an example and the specification revision assessed.

## Local debugging

- `options(shinyOAuth.skip_browser_token = TRUE)` – skip browser cookie binding in tests or interactive sessions
- `options(shinyOAuth.skip_id_sig = TRUE)` – skip ID token signature verification in tests or interactive sessions
- `options(shinyOAuth.allow_unsigned_userinfo_jwt = TRUE)` – accept unsigned (`alg=none`) UserInfo JWTs in tests or interactive sessions; outside those contexts 'shinyOAuth' errors instead of honoring it
- `options(shinyOAuth.debug = TRUE)` – re‑raise errors during token exchange
- `options(shinyOAuth.expose_error_body = TRUE)` – enable sanitized diagnostic
  text for local debugging. Fields are capped at 512 UTF-8 bytes and can still
  contain private provider data. The option is disabled by default and takes
  effect only in tests or interactive sessions.

## Advanced transport constraints

Response limits cover both downloaded and decoded gzip data; other encodings
are rejected. Use `perform_resource_req(token, request)` to retain the decoded
size limit, adding `client` for DPoP or mTLS. Direct `httr2::req_perform()` uses
httr2's transport settings instead.

## Advanced parameter overrides

Overrides allow selected extra parameters beyond the normal client and provider
arguments.

By default, shinyOAuth blocks security-critical parameters in `extra_auth_params`,
`extra_token_params`, and `extra_token_headers` to protect state binding, PKCE
and client authentication from accidental overrides.

Set the callback format with `oauth_client(response_mode = ...)`.

- `options(shinyOAuth.unblock_auth_params = c("redirect_uri"))` – allow selected
  authorization-parameter overrides.

- `options(shinyOAuth.unblock_token_params = c(...))` – allow selected
  token-exchange parameter overrides.

- `options(shinyOAuth.unblock_token_headers = c("authorization"))` – allow
  selected token-header overrides, matched case-insensitively. `Authorization`
  and `Cookie` are blocked by default.
