Skip to content

Commit f8d30ac

Browse files
feat(auth): warn when DPoP-bound token sent under Bearer scheme
Per RFC 9449 §7.1, DPoP-bound access tokens (cnf.jkt claim present) MUST be presented under the "DPoP" Authorization scheme. The platform currently accepts either scheme as long as a valid DPoP proof is attached. This change emits a WARN log when a cnf-bound token arrives under "Bearer" scheme, surfacing non-compliant SDKs without breaking existing clients. A follow-up will promote this to a hard reject once all SDKs are compliant. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 5da2453 commit f8d30ac

1 file changed

Lines changed: 12 additions & 1 deletion

File tree

service/internal/auth/authn.go

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -630,14 +630,19 @@ func (a *Authentication) checkToken(ctx context.Context, authHeader []string, dp
630630
return a._testCheckTokenFunc(ctx, authHeader, dpopInfo, dpopHeader)
631631
}
632632

633-
var tokenRaw string
633+
var (
634+
tokenRaw string
635+
authScheme string
636+
)
634637

635638
// If we don't get a DPoP/Bearer token type, we can't proceed
636639
switch {
637640
case strings.HasPrefix(authHeader[0], "DPoP "):
638641
tokenRaw = strings.TrimPrefix(authHeader[0], "DPoP ")
642+
authScheme = "DPoP"
639643
case strings.HasPrefix(authHeader[0], "Bearer "):
640644
tokenRaw = strings.TrimPrefix(authHeader[0], "Bearer ")
645+
authScheme = "Bearer"
641646
default:
642647
a.logger.WarnContext(ctx, "failed to validate authentication header: not of type bearer or dpop", slog.String("header", authHeader[0]))
643648
return nil, nil, errors.New("not of type bearer or dpop")
@@ -661,6 +666,12 @@ func (a *Authentication) checkToken(ctx context.Context, authHeader []string, dp
661666
}
662667

663668
_, tokenHasCNF := accessToken.Get("cnf")
669+
if tokenHasCNF && authScheme == "Bearer" {
670+
// RFC 9449 §7.1: DPoP-bound access tokens MUST be presented under the "DPoP"
671+
// Authorization scheme. Warn for now to surface non-compliant SDKs; will be
672+
// promoted to a hard reject in a future release once all SDKs are compliant.
673+
a.logger.WarnContext(ctx, "DPoP-bound access token presented under Bearer Authorization scheme; per RFC 9449 §7.1 the DPoP scheme is required")
674+
}
664675
if !tokenHasCNF && !a.enforceDPoP {
665676
// this condition is not quite tight because it's possible that the `cnf` claim may
666677
// come from token introspection

0 commit comments

Comments
 (0)