Skip to content

auth: add ClockSkew option to RequireBearerTokenOptions#969

Open
BorisTyshkevich wants to merge 1 commit into
modelcontextprotocol:mainfrom
Altinity:auth-clock-skew-option
Open

auth: add ClockSkew option to RequireBearerTokenOptions#969
BorisTyshkevich wants to merge 1 commit into
modelcontextprotocol:mainfrom
Altinity:auth-clock-skew-option

Conversation

@BorisTyshkevich
Copy link
Copy Markdown
Contributor

Summary

  • Add a `ClockSkew time.Duration` field to `RequireBearerTokenOptions` that bounds the tolerance applied to a token's `Expiration` when checking elapsed validity.
  • Default zero preserves the existing strict comparison; positive values let resource servers tolerate the drift typical of distributed deployments and cloud-managed IdPs.

Motivation

Real-world resource servers running behind a CDN, in distributed deployments, or talking to an authorization server whose clock drifts a few seconds (common with cloud-managed IdPs) need a small positive tolerance when checking token expiration. Strict-equality comparison rejects tokens that are valid by the issuer's clock but momentarily appear expired by the verifier's. The reverse case — an issuer's clock running slightly fast at /token issuance — also reaches the verifier as a token whose `exp` lies microseconds in the past.

Test plan

  • `go test ./auth/...` passes.
  • New `TestRequireBearerToken_ClockSkew` exercises four cases: fresh accept, strict-expired reject, within-skew accept, beyond-skew reject.
  • Existing `TestRequireBearerToken` continues to pass with `ClockSkew` defaulting to zero.

Comment thread auth/auth.go Outdated
Comment on lines +149 to +153
skew := time.Duration(0)
if opts != nil {
skew = opts.ClockSkew
}
if tokenInfo.Expiration.Add(skew).Before(time.Now()) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
skew := time.Duration(0)
if opts != nil {
skew = opts.ClockSkew
}
if tokenInfo.Expiration.Add(skew).Before(time.Now()) {
if opts == nil {
opts = &RequireBearerTokenOptions{}
}
if tokenInfo.Expiration.Add(opts.ClockSkew).Before(time.Now()) {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Good call, adopted — hoisted the opts nil-normalization above the whole expiration block so both the AllowMissingExpiration check (from #971, since merged) and the new skew comparison use opts directly, dropping the opts == nil || guard. Also rebased onto main to resolve the conflict #971 introduced in this same block. Skew is applied in the else if so it only affects tokens that carry an expiration; a missing expiration stays governed solely by AllowMissingExpiration.

Resource servers running behind a CDN, in distributed deployments, or
communicating with an authorization server whose clock drifts a few
seconds need a small positive tolerance when checking token expiration.
The default zero value preserves the existing strict comparison.

Adds a ClockSkew time.Duration field to RequireBearerTokenOptions plus
a TestRequireBearerToken_ClockSkew test covering the four meaningful
combinations (fresh accept, strict-expired reject, within-skew accept,
beyond-skew reject).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@BorisTyshkevich BorisTyshkevich force-pushed the auth-clock-skew-option branch from f5da28d to 2876ffe Compare June 2, 2026 09:04
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