On this page:

8.12SMART on FHIR: Scopes

 

The OAuth2 specification uses "scopes" as a mechanism for an application to request specific API permissions for actions it wishes to perform.

8.12.1Picking Scopes

 

When setting up a new SMART on FHIR application that will consume FHIR APIs, one of the most important security considerations is which scopes to allow the app to request. The purpose of scopes is sometimes misunderstood: You can think of a scope as being a mechanism to allow an app to request the permission to do something on the user's behalf. So an app that only provides data viewing capabilities of some sort (e.g. viewing a patient's appointment schedule, or accessing lab reesults) should only be allowed to request "read" scopes.

Remember that scopes are not user permissions, they are app permissions. An example clinician user might have read/write permissions against the CDR, but if an app they are using has only been granted read permissions, the app can not write data on the user's behalf.

A further desicion to be made is around whether to prompt the user for scope approval. Smile CDR fully supports allowing the user to see which scopes an app is requesting, and make a decision about whether to approve them. Internet users are familiar with this workflow, as it is often seen when granting consumer internet apps permissions to see a user's profile information via common "Login with Google" and "Login with Facebook" type flows. This scope approval flow happens on the OpenID Connect Approval Page (sometimes called the "Consent Screen").

The explicit user approval step is not mandatory however. Scopes may be configured as Auto-Approve in the Smile CDR Client Definition screen if an organization wishes to approve these scopes automatically without showing them to the user. This might be done for enterprise apps where the app is fully trusted, or in cases where the app has been vetted by an organization and is believed to not require user permissions. Scopes can even be configured as Auto-Grant, which means that they will be granted any time a successful authentication occurs, even if the application did not request them.

Scopes are short strings of text, with no whitespace in them. For example in SMART on FHIR, the patient/Encounter.read scope can be used by an application to request access to access Encounter resources belonging to the currently authorized Patient. A user-visible text description of SMART on FHIR scopes can be customized as well.

8.12.2Launch Context Scopes

 

Background: Mobile App and Patient Portal

In many cases an app wants to be authorized without knowing which patient it is expected to display.

For example, consider a 3rd party Mobile App that is authorizing itself against a hospital Patient Portal that acts as both a SMART on FHIR compliant Authorization Server and Resource Server. Users already have an account (with username and password) in the Patient Portal application, and by authorizing against those credentials the Mobile App can download data from the Patient Portal.

In this case the user is associated with a Patient resource ID on the Resource Server, but neither the Mobile App nor the user are aware of what resource ID that would be.

Background: Micro-Application Portal

Another use-case for launch scopes would be a portal which functions as a "desktop" of micro-applications (small web applications that do one thing, and do it well).

In this case, it could be assumed that the portal itself has a concept of which Patient (and/or which practitioner, which location, etc) is currently selected. The user's expectation would be that if a Patient is selected in the portal, any micro-apps would launch with the same Patient selected.

Launch Scopes

SMART on FHIR specifies a set of scopes which request that the Authorization Server return the launch context to the Client. These scopes are named launch/[type], where [type] is one of patient, location, practitioner, or another type of your choosing.

From the Client's perspective, a flow using a launch scope works as follows:

  • The client performs an OAuth2 grant request (typically using the implicit or authorization code flows). In the initial authorize request, the client requests the launch/patient scope. This is a request for the Authorization Server to include a patient launch context.

http://myserver:9200/oauth/authorize?response_type=code&scope=openid+profile+launch/patient&client_id=my-client-id&state=af0ifjsldkj&redirect_uri=https://myapp.example.com/cb

  • At the end of the flow (several steps have been skipped here) when the access_token and id_token are received, the response will contain an additional claim called patient.
{
   "access_token":"eyJraWQiOiJ1bml0dGV (..snipped..)",
   "token_type":"bearer",
   "scope":"launch/patient openid profile",
   "id_token":"eyJraWQiOiJ1bml0dGVzdC1 (..snipped..)",
   "patient":"123"
}
  • In addition, the decoded access token will also contain the same "patient": "123" claim.

8.12.3The OpenID and Profile Scopes

 

The openid and profile scopes are used by the Client to request user identity information from the Authorization Server as a part of the auth flow.

When these scopes are requested, an additional claim is returned by the authentication server called id_token. This claim is called the ID Token, and you can see it being returned in many of the examples above.

The ID Token is a Signed JWT. It may be decoded, revealing a number of attributes.

{
   "jti":"d34af0de-e65a-4c19-8e38-365916948356"
   "at_hash":"xDKTbwLJPrb6hr_loWD8Qw",
   "sub":"user123",
   "profile":"http:\/\/example.com\/issuer\/fhir\/RelatedPerson\/123",
   "iss":"http:\/\/example.com\/issuer",
   "nonce":"NONCETEXT-123",
   "aud":"my-client-id",
   "auth_time":1532416414,
   "exp":1532416474,
   "iat":1532416414,
   "name":"John Smith",
   "given_name":"John",
   "family_name":"Smith",
}