Safeguard
Developer Tools•

SMART on FHIR scopes explained: patient, user, system and cruds

How to read scopes like patient/Observation.rs and system/*.cruds: the three prefixes, the five permission letters, ordering rules and launch scopes.

Safeguard Security Team
3 min read

A SMART scope has three parts: a prefix saying who the access is for (patient, user or system), a resource type, and permission letters from c, r, u, d and s. For example, patient/Observation.rs lets an app read and search observations for the patient in context. Ask for the narrowest scope that works.

The prefixes

These notes follow SMART App Launch version 2.2.0, built on FHIR R4.

  • patient/ limits access to the patient in context. Example from the spec: patient/Observation.rs.
  • user/ covers data the logged in user can access, which is wider than data about that user. Example: user/Appointment.cruds.
  • system/ is for a client with no user present, such as a reporting or bulk export service. Example: system/*.rs.

The resource part

The resource name follows the prefix and a dot. Names are case sensitive. A wildcard covers all resource types, including ones the server adds later, which is a reason to avoid it. Example: patient/*.cruds.

The permission letters

Letters come from c, r, u, d, s and must appear in that order.

  • c: create
  • r: read, including vread and history of one instance
  • u: update and patch
  • d: delete
  • s: search, plus type and system level history

Write permission does not imply read. An app that needs both must ask for both. Out of order or undefined combinations, such as a letter string in the wrong sequence, may be ignored or rejected, so keep scopes in their shortest correct form.

Version 1 scopes map as follows: .read becomes .rs, .write becomes .cud, and .* becomes .cruds. So a v1 write scope does not grant read in v2 terms, which can surprise teams migrating.

Narrowing with search parameters

You may append a query to narrow a scope. The spec example limits observations to laboratory results by category. Modifiers, chaining and the _filter parameter in these constraints are marked experimental, so do not depend on them across servers.

Launch, identity and refresh scopes

  • launch is needed for an EHR launch, paired with the launch URL parameter.
  • launch/patient asks for a patient context, often chosen at the start of a standalone app. launch/encounter asks for an encounter context.
  • openid returns an id token to authenticate the user, and fhirUser adds a claim holding the URL of a FHIR resource for the user.
  • offline_access gives a refresh token usable whether or not the user is online, if the server allows. online_access gives one usable only while the user stays online.

Practical advice

  1. Start with the smallest set of resources and letters.
  2. Split read and write apps where possible.
  3. Prefer patient/ over user/ for patient facing apps.
  4. Reserve system/ for backend jobs, and see SMART Backend Services.
  5. Treat offline_access as a risk decision, since the refresh token outlives the session.

Quick check

Does write access include read?

No. In SMART v2 scopes, create, update and delete do not imply read or search. Request r and s separately if the app needs them.

What does user/ cover compared with patient/?

patient/ is limited to the patient in context. user/ covers data the logged in user is able to access, which can span many patients.

Sources

Last reviewed: 19 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.