client-js
client-js copied to clipboard
Support for browser using multiple SMART clients at once.
Because sessionStorage uses the hardcoded SMART_KEY it does not allow having multiple SMART clients within a single application.
This may be an edge case (some user wanting to register multiple SMART endpoints for their app) but I believe this could be easy to support (allow users to pass some unique identifier for their client that overrides the default SMART_KEY).
That is an interesting idea, but I'm afraid we do need a well-known location for our storage. Here is the gist of how that works for EHR launch (which is the most common):
- EHR calls our launch url with
launchandissparameters. We are supposed to send thelaunchback to the EHR andissis our FHIR server url. - We fetch some metadata from
issto discover the authorization endpoint - We check for an "old state" at our well-known storage location and remove it
- We create new random key for our storage and store it under "SMART_KEY"
- We redirect to the authorize endpoint providing the
launchwe have gotten and that random key asstateparam - The auth server may go through several redirects (for example to make us select a patient or to authorize the launch). Eventually we will be redirected to our
redirect_uriwith two url parameters -codeandstate, wherestateis the same random key we created earlier. - We use
stateto locate our runtime state in the storage - We use the fact that
codeparam is present as a signal that we need to complete the auth flow by exchanging thatcodefor an access token - We remove the
codeandstatefrom the url so that the app does not re-authorize upon reload (refresh or other user navigation) - After the app is launched and while the users navigate through its pages/routes, it has no way of knowing which storage key to use, unless it is stored in a well-known location ("SMART_KEY").
With that said, something you can try is (assuming your code works in browser):
// Do this fefore calling `ready`
FHIR.oauth2.settings.fullSessionStorageSupport = false;
FHIR.oauth2.ready().then(
client => { /* init my app */ },
console.error
);
This should preserve the state from the auth redirect parameter in the url and the library should use it as a storage key. You will also have to make sure that the state is preserved while navigating through various pages of your app.
Unless I'm misunderstanding I don't think the proposed solution would work for multiple clients. Because the library is checking for the state key either within the sessionStorage (using the hardcoded SMART_KEY where it gets set) or using url state parameter multiple smart clients still would not be possible on an app (they would override one another either in sessionStorage or on the urls parameters)?
My thoughts would be to instead allow a user to pass in a value during SMART client initiation that would tell the library where to pull/put the generated key in step 4. This would be a passed in parameter that would replace SMART_KEY where the generated key get's stored with another property and it would be the apps responsibility to store/know this key as opposed to the library. So effectively you would still be using a unique key generated within the library just where to find that key could be overwritten by the caller.
Rough draft of some code as an example that I think could work: https://github.com/smart-on-fhir/client-js/compare/master...parlir:client-js:upgrade_with_alts?expand=1