Although there are several other means of authentication, I have chosen the custom token authentication as it makes the most sense.
I have "server" like machines that gather data from some sensors in a building, these machines have isolated datastores where they can write/read, they cannot and should not access other instances scopes.
These machines must be permanently connected but their data access must be isolated, therefore I cannot use any other authentication than this based on custom tokens.
So secret based authentication is eliminated as that one allows an instance to access any scope, it would have been a good choice as it does not have expiration.
I also cannot give years of age to the token, that defeats the purpose of token security.
FIREBASE WARNING: auth() was canceled: Auth token is expired
First attempt
Let us check the docs
https://www.firebase.com/docs/web/guide/login/custom.htmlThere we find this gem:
To handle token expiration gracefully, the authentication function in the client library for each platform (JavaScript, Objetive-C, Java) allows us to set a cancel callback that is triggered when a token expires. The authentication function's success callback will provide authentication info. Using this, we can tell in advance when the token will expire.
Now, how do you set this cancel callback, no problem, let us dig deeper in the docs
https://www.firebase.com/docs/web/api/firebase/authwithcustomtoken.htmlThe documentation shows 3 parameters for this function, the first two are obvious, for the last one I could not find more than:
An object containing optional client arguments, such as configuring session persistence.
ARGH ... I have no idea what it means, happy it exists, what does it do ? there is nothing related to a cancel callback that is triggered when a token expires
Second attempt
Pre-emptive approach, by using the onComplete handler of authWithCustomToken one can detect expiration manually
scope.authWithCustomToken(token, function(error, authData) {
if (error) {
console.error('auth error', error, authData)
} else {
// handle successful authentication
signals.authenticated.dispatch(authData)
// start a token expiration monitor
var nowDate = new Date(),
expDate = new Date(authData.expires * 1000),
expTimeLeft= Math.floor((expDate.getTime() - (new Date().getTime()))/1000),
if (expTimeLeft === 0) {
console.log('token has expired - no more time left')
signals.tokenExpiring.dispatch()
} else {
console.log('token will expire in: ' + expTimeLeft + ' seconds')
setTimeout(function() {
console.log('token has expired')
signals.tokenExpiring.dispatch()
}, (expTimeLeft <= 0 ? 0 : expTimeLeft) * 1000)
}
}
})
Although simple, this method looks ugly, a patch, smelly and something that is not to be liked and it comes with additional confusion.
What am I supposed to do after the token expiration has been detected ? I want to continue the life of the server machine without disconnecting it.
Currently, at expiration, I call authWithCustomToken again, but I do not know if it is the right thing to do. This is also cumbersome, because all listeners that are added after authenticated signals is dispatched, must be tracked and cleared.
Questions
- Does that authentication function expiration callback in the client library for each platform really exist ? Where is it, how do you use it ?
- In case it does not exist, isn't there a way to just replace the token, without performing authentication again ?
- How do you guys handle this cleanly ?
P.S. - I am aware-ish of how other proposed to solve this, I did not like anything that I found. If Firebase SDK is able to display "FIREBASE WARNING: auth() was canceled: Auth token is expired." for sure it can be able to trigger a custom function just before or after that, without using the setTimeout that I have, if I could easily tap there.