Skip to content

About

Authentication/authorization helpers for C3G R Shiny apps behind oauth2-proxy

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

c3g.shiny.authz

Authentication/authorization helpers for C3G R Shiny apps sitting behind oauth2-proxy. See web-app-template's for-app-developers.md (#real-tier-3-for-shiny) and README.md for where this fits among the authentication/ authorization tiers.

Two independent layers, so an app only takes on what it needs:

Layer Function Does Needs OPA
Tier 2, cosmetic c3g_groups() Reads and parses the forwarded-groups header from session$request, once, correctly. No
Tier 3, real authz c3g_require_authz() Called at the top of a guarded observeEvent()/downloadHandler(). Builds an {action, groups} input, calls the app's local OPA sidecar, fails closed. Yes

Status: working, and verified end to end. c3g_require_authz() is tested against a real OPA server in CI, and checked inside a running Shiny app driven by a real browser (allowed, denied, no groups, OPA down). See CLAUDE.md for how to run both.

Pre-1.0: the API may change between minor versions until a first app has adopted it.

No OIDC-client layer is planned for this package — oauth2-proxy stays in front regardless of tier, since Shiny has no non-browser client the way pt_cli justifies one for project_tracking (which is meant to use c3g-oidc instead). That keeps this package doing one thing.

Install

remotes::install_github("c3g/c3g.shiny.authz@v0.1.0")

Usage

Tier 2, cosmetic UI only

server <- function(input, output, session) {
  groups <- c3g_groups(session)
  if ("admins" %in% groups) {
    # show an admin-only tab, button, etc. -- this is UI polish, not a security boundary;
    # oauth2-proxy already decided who gets this far before Shiny ever saw the request.
  }
}

Tier 3, real per-action authorization

server <- function(input, output, session) {
  observeEvent(input$export_btn, {
    # stops here, notifies the user, on deny
    c3g_require_authz("export_dataset", session, policy_path = "my_app/authz/allow")
    # ... proceed with the export
  })
}

policy_path names the app's rule in c3g-opa-policies: the Rego package and rule with dots replaced by slashes (package my_app.authz, rule allow → "my_app/authz/allow"). It has no default, since every app's policy lives under its own package.

By default, c3g_require_authz() calls the OPA sidecar at the C3G_OPA_URL environment variable, falling back to http://10.0.2.2:8181 -- the host-loopback address used throughout web-app-template's deployment docs for reaching a container's local sidecar. It gives up after 2 seconds (timeout) and denies: a Shiny process is single-threaded, so a hung OPA call would otherwise freeze the app for every user.

A complete example app is in inst/examples/authz-demo/.

About

Authentication/authorization helpers for C3G R Shiny apps behind oauth2-proxy

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages