-
Notifications
You must be signed in to change notification settings - Fork 398
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
Non-obvious behavior with long lived oidc.Provider
objects: remoteKeySet
caches original context
#339
Comments
Some background:
Part of the issue is that the remote key set needs a context to refresh the keys in the background. In hindsight, creating a remote key set probably always should have taken a context. So instead of:
Something like:
Which would hopefully produce a clearer intent about what context corresponds to what variable lifetime. Maybe we could add "NewVerifier" and deprecate "Verifier"? |
I think that explicitly taking in a new context for the verifier makes sense, though I think that (generally) the context is less important in When you say that the remote key set needs to refresh a context in the background, are you referring to the goroutine in On a related note, it seems odd that |
Hey sorry for the delay. I was traveling. I'm not entirely sure if this answers your questions about goroutines, but the reason updateKeys doesn't use the context from keysFromRemote is because many clients may be requesting a key at a given time, and I don't want one of those clients canceling the context to impact other clients. Line 185 in 26c5037
Probably worth a comment in the code. We have the following documentation on RemoteKeySet but not IDTokenVerifier. Will send an update for the comment:
|
@kuttas great sleuthing. I encountered this same thing this week with a perma-canceled cache context. A warning on the tin here would be good. Even better, if the context on the |
I noticed a non-obvious "bug" in our codebase when using the go-oidc package to verify JWTs. It wasn't expected to me or documented in
oidc.NewProvider
that the supplied context must never be canceled if you are going to re-use the resultingProvider
, though on further investigation it is mentioned in the underlying comments foroidc.NewRemoteKeySet
. This is a little weird because it means that aProvider
object created in the context of an incoming HTTP server request cannot be cached and re-used safely in future requests unless you explicitly pass in a separate context that will never be canceled (e.g.context.Background()
.My default assumption was to pass in the context from the HTTP request, but HTTP request contexts are canceled after
ServeHTTP
is finished (according to https://pkg.go.dev/net/http#Request.Context). This led to a fairly hard-to-track-down bug in our codebase since we have a runtime cache ofoidc.Provider
s, but sometimes they would get created during one request but wouldn't fetch JWKS until a future request, at which point the fetch would fail with:failed to verify signature: fetching keys oidc: get keys failed Get "https://<some-oidc-provider>/.well-known/jwks.json": context canceled
The fact that
remoteKeySet
internally stores the context runs counter to the Golang standard recommendations of never storing contexts in structs, and always using the one passed in (e.g. the guidance given here https://go.dev/blog/context-and-structs and here https://pkg.go.dev/context). In this case, it seems odd/unintuitive thatremoteKeySet
(which actually accepts a context arg in most methods) would use its own stored contextr.ctx
inupdateKeys()
even thoughkeysFromRemote
(which is the only method that callsupdateKeys()
) takes a context arg and could just pass that in?Surprisingly it seems almost no one else has run into this; I only found one other issue via google search that seemed similar (dexidp/dex#1255).
Is this an oversight or intentional?
The text was updated successfully, but these errors were encountered: