Skip to content

Commit 77a7d4d

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 15d77e3 commit 77a7d4d

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
@@ -684,14 +684,19 @@ func (a *Authentication) checkToken(ctx context.Context, authHeader []string, dp
684684
return a._testCheckTokenFunc(ctx, authHeader, dpopInfo, dpopHeader)
685685
}
686686

687-
var tokenRaw string
687+
var (
688+
tokenRaw string
689+
authScheme string
690+
)
688691

689692
// If we don't get a DPoP/Bearer token type, we can't proceed
690693
switch {
691694
case strings.HasPrefix(authHeader[0], "DPoP "):
692695
tokenRaw = strings.TrimPrefix(authHeader[0], "DPoP ")
696+
authScheme = "DPoP"
693697
case strings.HasPrefix(authHeader[0], "Bearer "):
694698
tokenRaw = strings.TrimPrefix(authHeader[0], "Bearer ")
699+
authScheme = "Bearer"
695700
default:
696701
a.logger.WarnContext(ctx, "failed to validate authentication header: not of type bearer or dpop", slog.String("header", authHeader[0]))
697702
return nil, nil, errors.New("not of type bearer or dpop")
@@ -715,6 +720,12 @@ func (a *Authentication) checkToken(ctx context.Context, authHeader []string, dp
715720
}
716721

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

0 commit comments

Comments
 (0)