mcp connection
Some checks failed
CI / fixture (push) Has been cancelled
CI / test (push) Has been cancelled

This commit is contained in:
2026-09-22 10:58:02 +05:30
parent 4e1f746b22
commit f2aa3b3ad8
53 changed files with 12515 additions and 37 deletions

View File

@@ -0,0 +1,107 @@
package oauth
import (
"errors"
"strings"
"testing"
)
// The RFC 7636 appendix B worked example. Using the spec's own vector rather
// than a value this implementation produced means the test would catch an
// encoding mistake that is self-consistent — base64 standard instead of
// base64url, say, or padded instead of raw — which a round-trip test could not.
const (
specVerifier = "dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk"
specChallenge = "E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM"
)
func TestChallengeForMatchesTheRFCVector(t *testing.T) {
if got := ChallengeFor(specVerifier); got != specChallenge {
t.Errorf("ChallengeFor(RFC 7636 verifier) = %q, want %q", got, specChallenge)
}
}
func TestVerifyChallengeAcceptsTheCorrectVerifier(t *testing.T) {
if err := VerifyChallenge(specVerifier, specChallenge, MethodS256); err != nil {
t.Errorf("the RFC's own verifier was rejected: %v", err)
}
}
func TestVerifyChallengeRejectsAWrongVerifier(t *testing.T) {
// Same length and character set, one character different. A comparison
// that was accidentally checking length or prefix would let this through.
wrong := "dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXX"
err := VerifyChallenge(wrong, specChallenge, MethodS256)
if !errors.Is(err, ErrVerifierMismatch) {
t.Errorf("err = %v, want ErrVerifierMismatch", err)
}
}
func TestVerifyChallengeRejectsAMissingVerifier(t *testing.T) {
if err := VerifyChallenge("", specChallenge, MethodS256); !errors.Is(err, ErrMalformedVerifier) {
t.Errorf("err = %v, want ErrMalformedVerifier", err)
}
}
// `plain` must be refused wherever it appears. It is legal in RFC 7636 and
// forbidden by OAuth 2.1 for public clients, because the challenge IS the
// verifier and anyone who stole one stole both.
func TestPlainMethodIsRejected(t *testing.T) {
for _, method := range []string{"plain", "PLAIN", "", "s256", "S512"} {
t.Run("method="+method, func(t *testing.T) {
if err := ValidateChallenge(specChallenge, method); !errors.Is(err, ErrUnsupportedChallengeMethod) {
t.Errorf("ValidateChallenge: err = %v, want ErrUnsupportedChallengeMethod", err)
}
if err := VerifyChallenge(specVerifier, specChallenge, method); !errors.Is(err, ErrUnsupportedChallengeMethod) {
t.Errorf("VerifyChallenge: err = %v, want ErrUnsupportedChallengeMethod", err)
}
})
}
}
func TestMalformedChallengeIsRejected(t *testing.T) {
for name, challenge := range map[string]string{
"empty": "",
"too short": "abc",
"too long": strings.Repeat("a", 44),
"padded base64": "E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM=",
"standard base64": "E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw+cM",
"illegal char": "E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw!cM",
"whitespace": "E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw cM",
"newline injected": "E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw\ncM",
} {
t.Run(name, func(t *testing.T) {
if err := ValidateChallenge(challenge, MethodS256); !errors.Is(err, ErrMalformedChallenge) {
t.Errorf("err = %v, want ErrMalformedChallenge", err)
}
})
}
}
// RFC 7636 section 4.1 constrains the verifier to 43–128 unreserved characters.
// A verifier outside that range is malformed regardless of what it hashes to.
func TestMalformedVerifierIsRejected(t *testing.T) {
for name, verifier := range map[string]string{
"too short (42)": strings.Repeat("a", 42),
"too long (129)": strings.Repeat("a", 129),
"illegal char": strings.Repeat("a", 42) + "!",
"whitespace": strings.Repeat("a", 42) + " ",
} {
t.Run(name, func(t *testing.T) {
if err := VerifyChallenge(verifier, specChallenge, MethodS256); !errors.Is(err, ErrMalformedVerifier) {
t.Errorf("err = %v, want ErrMalformedVerifier", err)
}
})
}
}
// A verifier at each end of the legal range must be accepted, or clients
// generating the maximum length would fail against this server.
func TestVerifierBoundariesAreAccepted(t *testing.T) {
for _, length := range []int{43, 128} {
verifier := strings.Repeat("a", length)
if err := VerifyChallenge(verifier, ChallengeFor(verifier), MethodS256); err != nil {
t.Errorf("a %d-character verifier was rejected: %v", length, err)
}
}
}