hasura_connect icon indicating copy to clipboard operation
hasura_connect copied to clipboard

Subscriptions stop working after the token expires.

Open develogo opened this issue 4 years ago • 8 comments

Subscriptions stop working after the token expires. Even generating a new token and setting it as a new token, the subs do not work again.

develogo avatar Jan 06 '21 06:01 develogo

I am using hasura_connect myself, and I have seen this happening too, especially when your authentication header is based on firebase auth, and the id token expires. Would be nice to be able to catch this kind of error, or have hasura_connect handle them internally when the error happens.

andreyeurope avatar Jan 07 '21 10:01 andreyeurope

You can create an Interceptor instead of using the header argument in HasuraConnect. The interceptor can inject the token header into the request headers in every request with the latest JWT from your auth provider.

This an example of aTokenInterceptor using firebase taken from the readme with minor modifications:

class TokenInterceptor extends Interceptor {
  final FirebaseAuth auth;
  TokenInterceptor(this.auth);

  @override
  Future<void> onConnected(HasuraConnect connect) {}

  @override
  Future<void> onDisconnected() {}

  @override
  Future onError(HasuraError request) async {
    return request;
  }

  @override
  Future<Request> onRequest(Request request) async {
    var user = await auth.currentUser();
    var token = await user.getIdToken(); // firebase will return unexpired token (it takes care of the checking) 
    if (token != null) {
      try {
        request.headers["Authorization"] = "Bearer ${token.token}";
        return request;
      } catch (e) {
        return null;
      }
    } else {
    // do something if the token is null 
    }
  }

  @override
  Future onResponse(Response data) async {
    return data;
  }

  @override
  Future<void> onSubscription(Request request, Snapshot snapshot) {}

  @override
  Future<void> onTryAgain(HasuraConnect connect) {}
}

Now when you initialize the client, pass your TokenInterceptor like this:

final hasuraConnect = HasuraConnect(
    url,
    headers: headers, // use it for constant headers 
    interceptors: [TokenInterceptor(auth)],
  );

osaxma avatar Jan 20 '21 10:01 osaxma

Thank you @osaxma , but this approach doesn't work for subscriptions, because this is what I use for my hasura connect instance.

It works just fine until the token expires. When it expired, Hasura will send something like connection not authorized or similar (tested with Apollo in React), but nothing happens in hasura connect packages.

A solution would be to throw an exception or something to let us (the users of the library) know that you have to open a new connection or do something about the current connection, or internally call again the onRequest method .

andreyeurope avatar Jan 20 '21 11:01 andreyeurope

I totally missed that part. By the way, I'm not a maintainer here and I'm a user too... I just came across the issue few days ago and I thought that an interceptor would solve it but apparently not.. Thank you for clarifying that.

osaxma avatar Jan 20 '21 12:01 osaxma

Here's my workaround if anyone is interested:

https://gist.github.com/osaxma/141d6be2b522f8bfe8673af14eb20bd1

osaxma avatar Feb 08 '21 11:02 osaxma

Thank you @osaxma. I will look into your workaround later and come back with comments/feedback.

andreyeurope avatar Feb 08 '21 13:02 andreyeurope

Isn't that issue the same as #67?

evandrmb avatar Apr 16 '21 12:04 evandrmb

Isn't that issue the same as #67?

Yeah, I think it is the same. Probably we can close this one and use #67

andreyeurope avatar Apr 16 '21 14:04 andreyeurope