Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

flow-client: Make sure to remove any potentially expired JWT from the client used to exchange a refresh token for an access token in refresh_authorizations() #1725

Merged
merged 2 commits into from
Oct 21, 2024

Conversation

jshearer
Copy link
Contributor

@jshearer jshearer commented Oct 21, 2024

While running down some issues with Dekaf, namely frequent consumer group rebalances, I noticed that these rebalances correlated with Dekaf errors such as:

dekaf: error=failed to obtain access token

Caused by:
    Unauthorized: {"code":"PGRST301","details":null,"hint":null,"message":"JWT expired"}

I then realized that Dekaf was passing a client containing an expired access token to refresh_authorizations. Since generate_access_token RPC performs its own authentication internally by way of the provided refresh token, it shouldn't be called with an authorization header.

This isn't a critical bug as it should just disconnect the session, causing a new connection to be created that'll have a freshly authenticated client, but nevertheless it's good to fix.


This change is Reviewable

… client used to exchange a refresh token for an access token in `refresh_authorizations()`

While running down some issues with Dekaf, namely frequent consumer group rebalances, I noticed that these rebalances correlated with Dekaf errors such as:

```
dekaf: error=failed to obtain access token

Caused by:
    Unauthorized: {"code":"PGRST301","details":null,"hint":null,"message":"JWT expired"}
```
Copy link
Member

@jgraettinger jgraettinger left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM % comment

let Response {
access_token,
refresh_token: next_refresh_token,
} = api_exec::<Response>(client.rpc(
} = api_exec::<Response>(client.clone().as_anonymous().rpc(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: couldn't this just be with_creds(None) ?

I also think that method should be renamed with_user_access_token() to match new() and the field itself...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also think that method should be renamed with_user_access_token() to match new() and the field itself...

Yup, now that the client doesn't have a refresh token, that sounds right to me

nit: couldn't this just be with_creds(None) ?

Yes. I don't remember why with_creds does user_access_token: user_access_token.or(self.user_access_token), but none of the usages of it currently pass anything other than Some(..), so I think it's safe to make it simply return

        Self {
            user_access_token,
            ..self
        }

@jshearer jshearer merged commit ac2fb0d into master Oct 21, 2024
4 checks passed
jshearer added a commit that referenced this pull request Oct 21, 2024
This is a follow-up to #1725. I was still seeing some JWT expired errors, this time they looked like this:

```
WARN serve{...}: dekaf: error=status: Unauthenticated, message: "parsing jwt: token is expired by 12m4.003303197s", details: [], metadata: MetadataMap { headers: {} }
```

After some more digging, I realized that a sufficiently long-lived session containing a sufficiently long-lived `Read` could run into this issue, as the Read's journal client is never refreshed. This fixes that.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants