Was running into an issue where ID tokens were being used by the
authenticator even after the 1-hour validity period, and weren't being
refreshed.
After enabling debug logs, I found out that this was happening because
ID-token-only responses don't contain the `expires_in` field, so the
authenticator assumes it doesn't expire.
Interestingly, this doesn't happen when using the service account
impersonation flow, because it's explicitly handled there by defaulting
the expiration to 1 hour.
The ID token is a JWT so it's possible to decode it to get the
expiration date, but to avoid introducing a JWT decoding dependency,
I've gone for the same approach of defaulting to 1 hour, as indicated in
the GCP docs.
The `from_environment` function in
`ApplicationDefaultCredentialsAuthenticator` had an `unwrap` call on an
io::Result after reading the service account key from file. File
operations are inherently fallible, and panicking on such a failure is
generally a bad convention compared to propagating the IO error.
Propagating that error from the `from_environment` function is not
practical however, because the returned Result type does not include IO
errors, and changing the function signature would be semver
incompatible.
This change instead defers reading the key file to a later function
call. Now `from_environment` only reads the value of the
`GOOGLE_APPLICATION_CREDENTIALS` into a PathBuf, and a later call to
`ServiceAccountFlow::new` will actually read the file. That constructor
already returns an io::Result, so folding the read error into it is
possible, and none of the changes impact public items so it's all
semver-compatible.
For google stuff these are relevant when trying to invoke e.g. Cloud
Run services. I'm not at all knowledgeable enough with OAuth to be able
to tell if what I'm doing here is correct.
This is a breaking change. `AccessToken` got renamed to just `Token`
(since it now encompasses more than just `access_token` and there are
some changes to the `TokenInfo` type too.
Sponsored by: standard.ai