realm-web: send extra HTTP headers with mongoClient and function calls
I propose modifying the realm-web package with an extension to Fetcher class to utilize headers provided in any of three ways: extension of the App object, extension of the User object, or an option on creating the mongoClient service.
Though it may seem a Typescript heresy, it is perfectly normal to extend Javascript objects, for example: Object.defineProperties(realmApp.currentUser, { "organization": identifier, "headers": { get: () => ({ 'X-MyCorp-tenant-organization': identifier }) } }
When that HTTP header is sent with every request, the user's tenant organization should then be accessible from request context in functions, rules, and filters. The presence or absence of the header can contribute to secure & reasonable behavior.
Looking forward to your feedback!
☑️ ToDos
- [ ] 📝 Changelog entry
- [ ] 📝
Compatibilitylabel is updated or copied from previous entry - [ ] 🚦 Tests
- [ ] 📝 Public documentation PR created or is not necessary
- [ ] 💥
Breakinglabel has been applied or is not necessary
If this PR adds or changes public API's:
- [ ] typescript definitions file is updated
- [ ] jsdoc files updated
- [ ] Chrome debug API is updated if API is available on React Native
I believe I understand your use-case: You want to associate additional data with your user as they're requesting a MongoDB function, right?
Have you tried other ways of associating this data with the user, such as custom user data or simply adding this as a argument of the function you're calling? If yes, can you help me understand why this is not sufficient for your use-case?
I believe I understand your use-case: You want to associate additional data with your user as they're requesting a MongoDB function, right?
Have you tried other ways of associating this data with the user, such as custom user data or simply adding this as a argument of the function you're calling? If yes, can you help me understand why this is not sufficient for your use-case?
Consider that the additional data is associated with the request. My app is served on a wildcard domain, and via some provisioning service, the domain maps to a tenant id used as an attribute of docs in Atlas collections. The user (specifically Realm user) may be anonymous & have no custom data. This is the web-client perspective.
From the Realm application (server-side) perspective, if the HTTP header is absent I can write a data source filter to reliably, succinctly eliminate tenant-owned docs from search. This is one fail-stupid barrier to augment data security for my tenants.
And additional to the security perspective, developers (myself included) are error-prone & likely somewhere to forget to include a find parameter. Just as they are likely to work around a complex model class that would have to rewrite every request. I'm looking for the one-and-done developer experience, I guess.
Note on user custom-data: my authenticated users could be authorized for none, one, or many organizations so the filter logic could become quite complex. By mapping a client-contextual organization into the Realm request I think I'm improving user-experience by matching end-user expectations.
I have a few comments that should be taken into consideration. We would also appreciate the tests being extended.
I added four tests, for each of the three individual sources of headers App/User/mongoClient and the interaction of all three.
CI failed on missing password for a Docker container: not sure how I can facilitate that.
Sending @kraenhansen a friendly ping.
Thanks again for you interest and PR. Sorry for keeping this hanging @tgerk. We're really busy getting Hermes support out. I suspect I'll be able to have a proper look at this some time during October.
thanks for the update
On Sun, Sep 26, 2021 at 10:27 PM Kræn Hansen @.***> wrote:
Sorry for keeping this hanging @tgerk https://github.com/tgerk. We're really busy getting Hermes support out. I suspect I'll be able to have a proper look at this some time during October.
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/realm/realm-js/pull/3935#issuecomment-927543371, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAMWLIV7ATW6TYMZBRHBN63UD76FZANCNFSM5DET2ZGQ . Triage notifications on the go with GitHub Mobile for iOS https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675 or Android https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub.
I've performed a squash and rebase onto current master (to resolve merge conflicts).
Includes simplified headers implementation in Fetcher compared to earlier reviews. Now merges headers on each clone.
Gotcha:Headers is a type defined by realm-network-transport package & different than Headers from Web Fetch API. This turns out to be helpful, since context that is dynamic in nature can be accommodated by using generic objects with dynamic getter properties. My User::setContext method takes advantage of this. Its value param accepts a function returning a string, as well as just a plain string.
For example, part of my User context is a capabilities JWT that is updated periodically by a 3rd-party SSO service. I can call myRealmUser.setContext('X-MyApp-Capabilites', () => ssoProvider.acquireOrRefreshCapToken(...) )