novuhq / novu

Open-Source Notification Platform. Embeddable Notification Center, E-mail, Push and Slack Integrations.
https://novu.co
Other
34.76k stars 3.56k forks source link

[NV-3043] 🚀 Feature: react-native support for Headless JavaScript Service #4499

Open tarcon opened 1 year ago

tarcon commented 1 year ago

I'm submitting a...

I'd like to be able to use the HeadlessService in a react-native client and need to store the token somewhere else.

Other information The token storage seems to be the only issue that's preventing the HeadlessService from working in react-native.

To solve this, I'd suggest to provide a custom tokenStorage option in the HeadlessService constructor, so that a client can provide a react-native compatible storage.

I have a working implementation for it: https://github.com/novuhq/novu/compare/next...holi-social:novu:next

I'd gladly open a PR for that. Please assign me to this issue.

NV-3043

p-fernandez commented 1 year ago

This sounds fantastic. How do you plan to solve the localStorage problem? What alternative would you use for a react native compatible solution?

tarcon commented 1 year ago

react-native-mmkv is a synchronous store which seems compatible with the browsers local-storage interface (it doesn't work in Expo Go unfortunately)

To prove my concept, this simple variable store enables the HeadlessService to work both in react native and a Next.js app:

let token: string | null = null

export const novuTokenStorage = {
  getItem: () => token,
  removeItem: () => {
    token = null
  },
  setItem: (_: string, value: string) => {
    token = value
  },
}

new HeadlessService({
      ...
      tokenStorage: novuTokenStorage,
})

We could discuss the overall need to persist the token instead of just holding it in memory.

A reason to use persisted tokens is to reduce load on the backend. But the headless package currently leaves session initialization to the client and doesn't encourage its economical use.

So we might as well replace localstorage use in the HeadlessService in general to keep things simple and compatible with react-native. Maybe i am over-pragmatic about it. Let me know if I miss a good reason for persisting the token.

p-fernandez commented 1 year ago

Mainly the main reason for that is to persist the Headless authentication across refreshes or pages closed without having to initialise the session. Also it avoids CSRF (https://owasp.org/www-community/attacks/csrf) but vulnerable to XSS attacks. I understand the choice we made was based on a quick developer experience plus the minimal amount of security possible combined.

tarcon commented 11 months ago

I won't work on this any further. I chose to use the base ApiService from the novu/client package for now as the HeadlessService was not working as I expected. It lacked a way for the client to reload notifications without having to reinitialize the client.

UncleSamtoshi commented 10 months ago

@tarcon What was the problem you were encountering with just reinitializing the client each time?

UncleSamtoshi commented 10 months ago

@tarcon What was the problem you were encountering with just reinitializing the client each time?

You can ignore this as I misread your earlier message and missed that you were having problems with reloading notifications.

eduardo-santos-tribia commented 4 months ago

I won't work on this any further. I chose to use the base ApiService from the novu/client package for now as the HeadlessService was not working as I expected. It lacked a way for the client to reload notifications without having to reinitialize the client.

@tarcon could you provide your solution or give a more clear idea of how to solve it? What is the link with proper documentation to this "base ApiService"?