Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for browser using multiple SMART clients at once. #157

Open
parlir opened this issue Aug 29, 2022 · 3 comments
Open

Support for browser using multiple SMART clients at once. #157

parlir opened this issue Aug 29, 2022 · 3 comments

Comments

@parlir
Copy link

parlir commented Aug 29, 2022

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).

@vlad-ignatov
Copy link
Collaborator

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):

  1. EHR calls our launch url with launch and iss parameters. We are supposed to send the launch back to the EHR and iss is our FHIR server url.
  2. We fetch some metadata from iss to discover the authorization endpoint
  3. We check for an "old state" at our well-known storage location and remove it
  4. We create new random key for our storage and store it under "SMART_KEY"
  5. We redirect to the authorize endpoint providing the launch we have gotten and that random key as state param
  6. 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_uri with two url parameters - code and state, where state is the same random key we created earlier.
  7. We use state to locate our runtime state in the storage
  8. We use the fact that code param is present as a signal that we need to complete the auth flow by exchanging that code for an access token
  9. We remove the code and state from the url so that the app does not re-authorize upon reload (refresh or other user navigation)
  10. 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.

@parlir
Copy link
Author

parlir commented Jan 17, 2023

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.

@parlir
Copy link
Author

parlir commented Jan 17, 2023

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants