SMART on FHIR(Swift) Authentication for a single patient

935 views
Skip to first unread message

Keerthi Shekar

unread,
Feb 3, 2016, 8:03:11 AM2/3/16
to SMART on FHIR
Steps that were followed for integrating Smart on FHIR:

  • A New App was registered on the SandBox with the required information. In return we got Client ID and Registration Access Token.
  • We have integrated the SmartonFHIR (Swift) framework into our project and followed the example that was provided to get the flow for authentication.
  • Added the new client ID and pointed the redirectURL back to our app. 
Result:
On Authentication, we are getting a listView with all the patients that are available in the Global Sandbox. On selecting any of the patients we get the patient details.

Our Requirement is to let the patient login and in return just get that patient data. We parsed through the framework to check if there was any other authorize function for the client class. We couldn't find any (pardon me if i have missed it) . It will be helpful if you could point us to the function/delegate/class that allows us to authenticate as a single patient and retrieve data for only that patient.

Pascal Pfiffner

unread,
Feb 3, 2016, 10:36:26 AM2/3/16
to SMART on FHIR
Hi Keerthi

The use-case you describe is something the server should implement. SMART knows three different launch scenarios: with a launch-context (usually provided by the EHR and mapping to the currently active patient), prompting the user to select a patient, and no patient preselection. (more here: http://docs.smarthealthit.org/authorization/scopes-and-launch-context/).

The Swift-SMART framework allows to specify which context to use by setting smart.authProperties.granularity , e.g. to .PatientSelectWeb. (more here: https://github.com/smart-on-fhir/Swift-SMART/wiki/Client#authorization). If you set it to the latter, the SMART auth server displays a list of patients, from which the user can choose. In your use-case, there should only ever be one patient, the one that just logged in. In this case the server could instantly return, not prompting for patient selection but returning patient=123 (with the id of the logged-in patient). The end-result would be what your scenario requires: instant return of one patient after login.

It's not possible to implement this flow client-side only since you don't know the patient-id before logging in. One way would be to use the native patient selector (when set to .PatientSelectNative, the default) and make it automatically select a patient when it detects that there is only one.

Hope this helps!
Message has been deleted
Message has been deleted

aco...@mhealthbrain.com

unread,
Feb 3, 2016, 12:53:22 PM2/3/16
to SMART on FHIR

The SMART specification for Standalone Launch Sequence at http://docs.smarthealthit.org/authorization/ 

Inline image 1

In SMART's standalone launch flow (shown above), a user selects an app from outside the EHR, for example by tapping an app icon on a mobile phone home screen. This app will launch from its registered URL without a launch id.


Josh: SMART has example apps including a Python Flask app using this flow, at https://github.com/smart-on-fhir/client-py (just follow the instructions for flask_app.py in the README).

 

Cooper: I would like to connect to you as if your sandbox was "Saleforce.com" in the diagram in this URL:

 

Inline image 2

https://blogs.aws.amazon.com/security/post/Tx3LP54JOGBE0AY/Building-an-App-using-Amazon-Cognito-and-an-OpenID-Connect-Identity-Provider.

 

1.     The user accesses the sample app and clicks on Sign In with Salesforce button.

2.     The app redirects the user to Salesforce for signing in. After successful authentication, the app receives an ID token from Salesforce.

3.     The app exchanges the ID token for a Cognito token.

4.     The app exchanges the Cognito token for temporary AWS security credentials.

5.     The app uses the credentials to access a DynamoDB table.

 

Josh: you want to use our sandbox as an OIDC identity provider? This is possible if you just ask for the scopes "oidc" and "profile", as per the OIDC specification. If I've read the diagram right, that's the role Salesforce is playing there: an identity provider.

 

Cooper: We use Amazon Cognito client libraries and supply a list of identity providers (Facebook, Google, Twitter and SMART on FHIR). Cognito provides a single API abstracting the differences from my client. I found this video to be the most informative: https://www.youtube.com/watch?v=YHJzj4EKySY We would like to use this approach for our app to access your sandbox for HIMSS if we are lucky.

 

JoshYou may have trouble using a common library against our server because, although we provide an id_token via OpenID Connect, we don't require the user claims API. Instead, we use the OIDC "profile" property to pass a FHIR resource URL describing the Patient, Practitioner, or RelatedPerson representing the user.

Pascal Pfiffner

unread,
Feb 4, 2016, 3:35:59 AM2/4/16
to SMART on FHIR
Is this a follow-up to the original post? I don't quite follow I'm afraid.

Alan Cooper

unread,
Feb 4, 2016, 4:11:31 PM2/4/16
to Pascal Pfiffner, SMART on FHIR
Hello Pascal,

Keerthi and I are working on the same project. I added the conversation to this post that Josh and I had a month ago on this specific use case. It was my understanding that we would have the desired behavior (single patient client login and authentication), and not see all of the other patient's names. Can / will there be support for this use case / launch context for HiMSS?

Alan S. Cooper

--
You received this message because you are subscribed to a topic in the Google Groups "SMART on FHIR" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/smart-on-fhir/nAp6qcWiuzQ/unsubscribe.
To unsubscribe from this group and all its topics, send an email to smart-on-fhi...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--

Alan Cooper
Founder/VP, Engineering


1311 Sutter Street, Suite 202

San Francisco, CA 94109

(650) 796 1104

www.mhealthbrain.com
aco...@mhealthbrain.com


This email may contain confidential and privileged material for the sole use of the intended recipient. Any review, use, distribution or disclosure by others is strictly prohibited. If you are not the intended recipient (or authorized to receive for the recipient), please contact the sender by reply email and delete all copies of this message.

Pascal Pfiffner

unread,
Feb 5, 2016, 3:01:47 AM2/5/16
to SMART on FHIR, phase.o...@gmail.com
Ah I see, thanks Alan.

To go the route Josh suggested, on the Swift client side, you would provide "scope": "profile oidc" (plus the "patient/*.*" or "user/*.*" scopes you need) in the initialization settings dictionary. Then you would set authProperties.granularity to TokenOnly. This means that the server will not prompt for patient selection but should return an id_token. You can then validate and inspect the ID token (delivered in parameters in the authorize callback), find the URL to the Patient resource (representing the logged in user) in "patient", and from there on do what your app needs to do.

See "Scopes for requesting identity data" here: http://docs.smarthealthit.org/authorization/scopes-and-launch-context/

What I don't know is if and how your OIDC services know which user is which patient in our sandbox. Hopefully my fellow SMARTer friends can answer that.

Pascal

Josh Mandel

unread,
Feb 5, 2016, 7:24:31 AM2/5/16
to Pascal Pfiffner, SMART on FHIR

To answer Pascal's last question: of course it'd up to the EHR to correctly report (in an id_token) which Patient or Practitioner or RelatedPerson the current user "is".

This is a bit of a challenge in SMART's public sandbox since our actual users (software developers working with the API) are never the same as our FHIR Patients (deidentified/synthetic records). Currently our sandbox just pretends the logged in user is always "Practitioner/123" - but we're working on a more flexible way for developers to configure such details.

You received this message because you are subscribed to the Google Groups "SMART on FHIR" group.
To unsubscribe from this group and stop receiving emails from it, send an email to smart-on-fhi...@googlegroups.com.

aco...@mhealthbrain.com

unread,
Feb 5, 2016, 12:51:30 PM2/5/16
to SMART on FHIR, phase.o...@gmail.com
Hello Josh, Pascal,

Thank you for your replies.

  1. Will support for our use case be available for HiMSS?
  2. Can you provide pseudocode for us to reference for our IOS Objective C implementation to connect to the SMART-ON-FHIR sandbox for either how the sandbox behaves today (in case we have to hack the demo for HiMSS) or how you envision the best practice should be?
Thank you in advance,
    Alan S. Cooper

Josh Mandel

unread,
Feb 5, 2016, 1:13:44 PM2/5/16
to Alan Cooper, SMART on FHIR, Pascal Pfiffner
In terms of server support for HIMSS: I'm hoping that you can build what you need to today, against our current sandbox. If this is wrong/problematic, please let me know. I will leave your second question to Pascal.

Pascal Pfiffner

unread,
Feb 6, 2016, 3:14:33 PM2/6/16
to SMART on FHIR, phase.o...@gmail.com
You don't need to do anything special in your iOS app. Just follow the code examples from the framework's guide (linked above) or the demo app and set authProperties.granularity = .TokenOnly. Then retrieve the desired patient resource (either hard-coded or via id_token returned from auth right in the callback (the sample code starts loading Medications; that's the spot).

Keerthi Shekar

unread,
Feb 8, 2016, 8:13:54 AM2/8/16
to SMART on FHIR, phase.o...@gmail.com
Hi Pascal,

The exact same thing has happened as you have pointed out. The logged account is not linked to any patient in the sandbox. So im currently getting a nil for the patient from SMART.

Pascal Pfiffner

unread,
Feb 9, 2016, 4:47:11 AM2/9/16
to SMART on FHIR, phase.o...@gmail.com
Hi Keerthi

Are you adding the "profile" and "oidc" scopes to the client, and are you using "token only" authorization? Can you show me code where you initiate Client and do the authorization?

For reference:

Pascal

Keerthi Shekar

unread,
Feb 9, 2016, 5:49:05 AM2/9/16
to SMART on FHIR, phase.o...@gmail.com

I have attached a snapshot of the OAuth2JSON object while creating the Client Object

Here is the authProperties being set

The error message that is got on add oidc as on of the scopes.



I had one more question. When offline_access is added to the scope, same error is received. Can you guide me on how to get the refresh token on authentication along with the accessToken in the callback parameters

Pascal Pfiffner

unread,
Feb 9, 2016, 7:26:08 AM2/9/16
to SMART on FHIR, phase.o...@gmail.com
Seems the redirect error is not properly logged – the server returns "invalid scope", meaning it does not like the "oidc" scope. Remove that and try again.

Pascal

Keerthi Shekar

unread,
Feb 9, 2016, 7:34:29 AM2/9/16
to SMART on FHIR, phase.o...@gmail.com
On Removal of oidc it seems to work properly with response providing accessToken and idToken. But the scope offline_access doesnt seem to work as well for retrieving the refresh token. Can you guide me on getting the refresh Token

Pascal Pfiffner

unread,
Feb 9, 2016, 7:55:10 AM2/9/16
to SMART on FHIR, phase.o...@gmail.com
If you're specifying "offline_access" but not getting a refresh token, the server isn't issuing one. Can you post the log with all "OAuth2: " messages that you see in Xcode when authorizing the user?

Keerthi Shekar

unread,
Feb 9, 2016, 8:27:26 AM2/9/16
to SMART on FHIR, phase.o...@gmail.com

This is the scopes added

The response got is 

OAuth2: No access token, maybe I can refresh

OAuth2: I don't have a refresh token, not trying to refresh

OAuth2: Authorizing against https://authorize-dstu2.smarthealthit.org/authorize?aud=https%3A%2F%2Ffhir-api-dstu2.smarthealthit.org&redirect_uri=AsthmaBrain%3A%2F%2Fcallback&scope=openid+user%2F*.*+profile+offline_access&response_type=code&client_id=7866ed0c-5df0-4252-9718-5ef3b0fa17c6&state=6E4A787A

OAuth2: Handling redirect URL asthmabrain://callback?error=invalid_scope&error_description=Invalid+scope&state=6E4A787A&scope=launch%2Fencounter+user%2F*.read+launch+openid+user%2F*.*+patient%2F*.read+profile

OAuth2: No “code” received

SoF: Failed to authorize with error: Optional(No “code” received)

No “code” receivedFailed

Pascal Pfiffner

unread,
Feb 9, 2016, 8:42:38 AM2/9/16
to SMART on FHIR, phase.o...@gmail.com
You are getting "invalid_scope" again, seems it doesn't like "offline_access". Have to ask the server guys, maybe mobile apps are not allowed to use it?

Keerthi Shekar

unread,
Feb 9, 2016, 8:56:45 AM2/9/16
to SMART on FHIR, phase.o...@gmail.com
So do i contact Josh or Nikola on this? 

Adding the list of questions. Is there can way where the accessToken can be accessed using the Client or Server Object. I dont see any instance of OAuth2 created in Client or Server classes

Pascal Pfiffner

unread,
Feb 9, 2016, 11:06:31 AM2/9/16
to SMART on FHIR, phase.o...@gmail.com
What I forgot: to be able to use the "offline_access" scope, your client needs to specify its use during registration time. Did you register your client by hand or how are you retrieving your client-id/secret? You should be able to let the client register itself (just don't specify a client-id), but make sure you have all the scopes correctly set (as it will register with those). You can use forgetClientRegistration() to throw away existing client registration if you used dyn reg but need other scopes.

The access token is managed by an object that's not publicly exposed. What you do need it for?

Keerthi Shekar

unread,
Feb 9, 2016, 12:11:59 PM2/9/16
to Pascal Pfiffner, SMART on FHIR
I tried adding the scope in the registeration. I added offline_access and then saved. It didn't get saved. Didn't understand if it the registeration issue or issue with the registeration web app.

To answer your question on the access token. We would like to be consistent with the Amazon Cognito's use model
--

Deepak Swamy

unread,
Feb 9, 2016, 5:46:18 PM2/9/16
to SMART on FHIR, phase.o...@gmail.com
Hi Pascal,

I was wondering if the we can add additional service call to get the accessToken and refreshToken for the logged in user/patient.
Currently when we do an oAuth, we expect to get back the accessToken and refreshToken. It would be great if you can enable it, else, it would also be great if you could expose us a service through which I can access the tokens.
To unsubscribe from this group and all its topics, send an email to smart-on-fhir+unsubscribe@googlegroups.com.

Deepak Swamy

unread,
Feb 9, 2016, 6:45:46 PM2/9/16
to SMART on FHIR, phase.o...@gmail.com
Service call could be either on the client side framework, or from the backend.

Pascal Pfiffner

unread,
Feb 10, 2016, 6:30:46 AM2/10/16
to SMART on FHIR, phase.o...@gmail.com
I see the need, I'll think about ways to expose authentication parameters when authentication happens as well as make access to auth pieces public. This will however require some API changes (probably) and so won't happen in time. In the meantime it's probably best if you resort to handling OAuth2 yourself. You can use OAuth2CodeGrant directly to perform the OAuth2 dance, as shown at the link below. Using OAuth2CodeGrant (its superclass is OAuth2) directly gives you access to all parameters that come back during authorization and you can access the tokens via accessToken and refreshToken on this instance.


Hope this helps
Pascal

Keerthi Shekar

unread,
Feb 10, 2016, 7:01:09 AM2/10/16
to SMART on FHIR, phase.o...@gmail.com
Thank you for your help Pascal. 

We still have an issue with not being able to fetch refreshToken from Smart on fhir OAuth. 

Pascal Pfiffner

unread,
Feb 10, 2016, 9:08:49 AM2/10/16
to SMART on FHIR, phase.o...@gmail.com
You will need to register a client with "offline_access". If updating doesn't succeed, maybe try creating a new client.

Nikolai Schwertner

unread,
Feb 10, 2016, 9:15:32 AM2/10/16
to smart-...@googlegroups.com
Make sure that you enable the refresh token option when registering your client at http://docs.smarthealthit.org/sandbox/register
You received this message because you are subscribed to the Google Groups "SMART on FHIR" group.
To unsubscribe from this group and stop receiving emails from it, send an email to smart-on-fhi...@googlegroups.com.

Keerthi Shekar

unread,
Feb 11, 2016, 12:58:53 AM2/11/16
to SMART on FHIR
Worked like a charm. I think we have everything we need for now. Thank you for your help Pascal and Nikolai.

Karthik B

unread,
Feb 12, 2016, 7:47:16 AM2/12/16
to SMART on FHIR
Hi Pascal,

After authentication we are passing access token as part of header as mentioned in your doc Authorization: Bearer {{access_token}}. We noticed that we were able to access patient data with or without using access token (https://fhir-open-api-dstu2.smarthealthit.org/Patient/1186747). Also access token was not getting expired. Hence we were not able to test the token expiration.

Are we in the right path?

Pascal Pfiffner

unread,
Feb 12, 2016, 4:22:46 PM2/12/16
to SMART on FHIR
Hi Karthik

You're using our open server, which does not need authentication. Use fhir-api-dstu2.smarthealthit.org for a protected server; the data you receive will be the same. And, I'm not 100% sure but I think our access tokens do not expire indeed.

Karthik B

unread,
Feb 14, 2016, 11:28:09 PM2/14/16
to SMART on FHIR
Hi Pascal,

Thank you, Since we used open server we couldn't notice the token expiration. After using protected server we were able to see token getting expired. Everything is working fine now thanks once again.
Reply all
Reply to author
Forward
0 new messages