How to manage updates to FCM push tokens? - react-native

I am wondering when in an app lifecycle to update the FCM registration token. I am using Firebase React native.
Currently, I send the FCM token to my backend:
on every app start
in onRefreshToken
sign in/out actions (to associate a user with the token)
I am wondering whether the above list is comprehensive and whether it contains extraneous update hooks (for instance, I am not certain that updating on every app start is necessary).
Main concerns revolve around:
what happens if the device loses access to the internet in onRefreshToken and the backend fails to be updated about the token refresh?
what happens if the FCM token gets refreshed when the app is not running? (and, hence, onRefreshToken is not invoked?
In summary, what is the officially recommended way to notify backend of updates to the FCM tokens?

because of the complexity of this and the difference depending on the application I have never seen an official recommendation, but a few things to add:
store the token on the device (e. g. shared preferences) to make sure you always use the latest or ask for the current one each time you need it
if it is critical you can store the state after an updated token and re-try more often if it has not been successfully transmitted.
on every app start is usually a good solution as fallback because many things can happen
consider logout without internet or uninstall. Here you will not remove the token on the server, so the next user could get the message without measures against that.
implement an update-process on the server to handle error-responses

Related

Is it bad practise to automatically use the refresh token in an interval?

As I am working on implementing a proper auth flow into a react web app, I am presented with different patterns of how to use access and refresh tokens.
I am considering the following two patterns:
Creating some sort of middleware to the fetch API:
This middleware runs before every request to the backend and checks whether the access token is still valid or not.
If it is invalid, it first calls the auth server to fetch a new access (and refresh) token.
Creating an interval which is independent from all other logic to keep the access token alive.
Say if the access token is valid for 5 minutes, the interval will run every 5 minutes to fetch a new access token
I would also make sure it only runs every five minutes, if the user is still active , so that the application left open without any user interaction for a long time will automatically log out
Any API call simply uses the currently active access token and does not need to worry about checking the token first or anything
The second approach seems much much easier and cleaner to implement for me, since it does not add any complexity to fetching data and is completely independent/seperate to the app otherwise.
I've been having a hard time to research this question though tbh. I'm not sure if there is some security issue I'm missing with that approach.
So my questions are:
Is there any security issue with fetching a new access token in an interval from the clients side?
Is there a common practise on how SPA apps (like the react app I mentioned) handle access tokens?
If yes, what is that common practise?
If there is no security issue, are there other cons of the second approach that I am missing out on?
Thank you for your answers in advance!
I think the answer depends, if you always do it every X minutes, and you have many active clients, it might create more load on the backend, compared do doing it on a need basis. Perhaps all clients are not so active all the time?
One thing to look out for is to make sure you don't trigger multiple requests at the same time to request new refresh tokens. If you get a race condition here, then you might be logged out (if you use one-time refresh tokens)
Also it is worth considering to use the BFF pattern, do watch this video
Using the BFF pattern to secure SPA and Blazor Applications - Dominick Baier - NDC Oslo 2021

How to store and use multiple users' keys for third party client

I want to build web app that uses Spotify API. I got case where user has to authenticate with his spotify account, then I recive access and refresh token that is being used in code to authenticate calls to Spotify to perform some actions on user's account.
I have trouble deciding how it should be really done. First thing that came to my mind - store them in Redis for some time, update on refresh and whenever we need to perform some action on any user we get his credentials and do it. Is this proper way? I tough about simply storing them in app memory but I might want to make in serverless.
Did anyone come accross that kind of problem? Do anyone know how to do it 'properly'.

How should I handle auto-refreshing a token?

I'm trying to automatically refresh a JWT within a react native mobile application. A pretty straightforward way of doing this is to use a setTimeout() where you calculate how long you need to wait until the token expires. Typically in my application this is going to be about a day.
However doing this in react native gives you a warning linking to https://github.com/facebook/react-native/issues/12981.
I'm totally OK with my token only being refreshed when the application is in the foreground, what concerns me more is the comment about performance. I'm wondering if there a better practise for handling token refreshing that I'm not aware of? Or in this instance should I be ignoring this warning?
When you successfully grab the token, add the time to state. When the app state becomes active, grab a new token if the current time is > the stored time plus one day.

Auth0: Specific questions about token storage and flow for mobile app

I’m building a react native app that will interact with APIs that I also write/manage. I have found Auth0 documentation for implementing this flow, but I’m not sure on where/when to save the tokens. I want to be sure I nail this step, because I feel like it has the potential to reduce the security of the flow by a great deal if I don’t do it correctly.
Here is the flow as I understand it (no error handling, only happy-path for sake of brevity):
A user enters the app for the first time, or is not already logged in
They log in using the Auth0 web-login-thingy
I receive a token
I can use the token to authenticate with my API
Questions:
Do I store that token? I don’t want my users to have to log in every time they use the app. If I do store the token, where do I store it?
If I’m not storing it, what do I do? Do I ping an authentication/authorization endpoint with Auth0 every time they open the app and get a new token?
Say I am storing the tokens, if I'm using the ID token for user data, should I be hitting the API again regularly to keep it up to date? Only when the user opens the app again? Not until they trigger a change in the app?
Instead of using the ID token for user data, should I just use that to get the user's ID and ping my database for user data?
I have the basics of this flow, and I'm able to sandbox it, but I want to start applying production-ready app logic to this flow and that's where I'm stuck. I’m a little lost here, so any help is good help.
Thanks!!
Here's a brief answer to your questions when using Auth0:
Yes! you store it, the most secure way to store the token is in your device's local storage, that way it is not kept either in application's state or in a global variable.
2&3. See above, but to add more information, you can configure your tokens to have an expiry length. in theory you would convert this 'expiry time from inception' to a date object, and can do one of two things; you can request a new token using the Refresh Token (that comes with the original) once the expiry has been reached, or force the user to re-log in and re issue a new token at this time (i prefer the latter, prevents people from just renewing their tokens forever as long as they remain logged in)
Use the auth token to request user information after login, this can be stored in app state/global variables/wherever. You then want to use the auth token in the Authorization Header for each API call, along with whatever data you are sending. this ensures that even once someone is INSIDE the application, they need to have a valid token to actually do anything involving data (imagine someone back-dooring into your app and skipping the authorization, or using something like postman to just hammer your API with garbage). it would work something like this: GET userData { Header: auth token } -> GET userProfile (by sending your user ID returned from GET userData) PLUS {Header: auth token }
I can give more in depth examples if you wish, and i apologize if i misunderstood any of the question and gave redundant/incorrect answers
Edit: Resources about using secure storage for keys
Document for when to use in-memory storage Vs persistent storage. The TL;DR is use in-memory if the key is expected to expire before a standard session duration, and persistent for storing a key between sessions
https://hackernoon.com/mobile-api-security-techniques-682a5da4fe10
link to Keychain Services doc
https://developer.apple.com/documentation/security/keychain_services#//apple_ref/doc/uid/TP30000897-CH203-TP1
link to SharedPreferences doc
https://developer.android.com/reference/android/content/SharedPreferences.html
AsyncStorage is a simple, unencrypted, asynchronous, persistent,
key-value storage system that is global to the app. [1]
You could store it in your AsyncStorage, but thats not necessarily a secure location itself (e.g. not encrypted, accessible on rooted devices...). Typically clients will issue access tokens that last anywhere from several hours to a couple days and these will provide their owner access to your API-resources. If there is sensitive data behind your login screen, you're probably better off simply re-doing the auth-flow and invalidate older access tokens on login.

AppEngine Channel API - Best way to check if a channel is still open (server side)

I have built a social network/dating type application on the AppEngine and am currently in the process of adding a chat built on top of the Channel API. However, the problem that I have is that users may reload or navigate to new pages while the chat is going on (as they can in Facebook). This means that the server doesn't easily know if it should generate a new channel ID token for a given client, or if a given client has already been assigned a channel token.
It would be extremely useful if there were a way to check (server side) if a particular client already has a channel open. For example, if I assign a client "Jack" a channel ID of "Jack-Jan-21-2010", then I would like to be able to check on the server side if there is already a channel open associated with the ID "Jack-Jan-21-2010". This can be (sort of) tracked on the client side by watching for an onerror() and onclose() callback, but I can't see anything server-side that allows me to just check if a channel associated with a given ID is already open.
Does anyone know an intelligent way to check (server side) if a channel has already been opened, while using the AppEngine Channel API?
Part 1: Solving your problem
See Part 2 below if you really need to track client connections, but I'm not sure from your question if what you're asking for will solve your problem.
Let me see if I can echo your problem back: you're writing a chat app, but it's for a site which isn't fully AJAX (in the way that, say, gmail is); the site contains page navigation where you may need to re-set up your channel after the user clicks on a link to another page. When the user navigates, the new page is rendered, and you want to avoid getting a new token at that point; you want to reuse the existing token and channel with the same client-id.
If that's correct, I have two alternate solutions, one easy but with not-great user experience, one trickier but with a much smoother end result.
Preserve the token in a cookie. When you re-render your page, just use the token from the cookie instead of calling channel.create_channel again. When the token expires you'll get an onerror callback just like if the user had stayed on the original page; at this point, call channel.create_channel again. The problem with this is that re-connection can be slow (up to 10 seconds or more in bad cases) because of the nature of Comet connections.
Wrap your entire site that's not chat-related in an iframe. Put your channel creation code and UI in the outer iframe. This way you don't have to re-connect every time the user navigates. This avoids the downtime on navigation. Note that orkut uses this technique, with floating divs, as a small amount of Firebug investigation will reveal.
Part 2: Your feature request
If it turns out I'm misunderstanding and you really do need to track client connections:
There's not a built-in way to check if a client is connected to a channel identified by a client-id now.
However, I am working right now on adding "presence" (in the chat sense) so that your app can register to get a post when a client connects to or disconnects from a channel created with a given client id. You also might be able to "probe" presence, to query whether a given client id is connected or not (still working on the details of this part).
Note that this won't be token-based, but rather client-id based.
I don't have a definite release date for this yet but as I said I'm actively working on it right now.
In the meantime, you could use a heartbeat HTTP request from your client back to your app that says, "hey, I'm still here" every minute or so. You'll need to have some sort of task that runs every, say, 2 minutes and marks any clients that haven't checked in as inactive, and you'll need to store this data someplace.