Skip to content

Buffer for renewing both id_tokens and access_tokens when they are about to expire, but not actually expired. #790

Open
@jabbera

Description

@jabbera

Proposed change

If the id_token or access_token are going to expire within the next N minutes, I'd like to be able to have the refresh process renew them.

We use the tokens as part of the oauth OBO flow in hooks and actively on servers while they are running. Knowing the access/id token isn't expired exactly when the refresh process runs isn't helpful. First the id_token expiration isn't checked at all it seems, second the access/id_token could not be expired at T + 0 when refresh_runs but at T+1 when we need it in the hook it could be expired.

Alternative options

We have implemented the following hook:

It's ugly because it depends on the internal implementation of an HTTPClientError with a 400 error code is what causes the refresh process:

    async def modify_auth_state_hook(self, _, auth_state: dict[str, Any]) -> dict[str, Any]:
        if not (self._token_almost_expired(auth_state.get("access_token", None)) or self._token_almost_expired(auth_state.get("id_token", None))):
            self.log.error(f"Tokens are not expired for: {auth_state['user']['name']}")
            return auth_state

        raise HTTPClientError(
            401,
            "Tokens are expired. Please re-authenticate.",
        )


    def _token_almost_expired(self, str_token: str | None):
        """Returns True if the token is expired."""
        if not str_token:
            return True

        decoded_token = jwt.decode(str_token, options={"verify_signature": False})
        token_expiration = datetime.fromtimestamp(decoded_token["exp"], tz=timezone.utc)
        deadline = datetime.now(timezone.utc) + self._token_expiration_buffer
        return token_expiration < deadline

Who would use this feature?

Anyone who needs to use the access_token or id_token during hooks or server lifetime

(Optional): Suggest a solution

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions