64 lines
1.4 KiB
Go
64 lines
1.4 KiB
Go
|
|
package pkce
|
||
|
|
|
||
|
|
import (
|
||
|
|
"crypto/sha256"
|
||
|
|
"encoding/base64"
|
||
|
|
"regexp"
|
||
|
|
"testing"
|
||
|
|
)
|
||
|
|
|
||
|
|
func TestGenerateVerifierLength(t *testing.T) {
|
||
|
|
verifier, _, err := Generate()
|
||
|
|
if err != nil {
|
||
|
|
t.Fatalf("unexpected error: %v", err)
|
||
|
|
}
|
||
|
|
|
||
|
|
if len(verifier) < 43 || len(verifier) > 128 {
|
||
|
|
t.Errorf("verifier length = %d, want 43-128", len(verifier))
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestGenerateVerifierCharacterSet(t *testing.T) {
|
||
|
|
verifier, _, err := Generate()
|
||
|
|
if err != nil {
|
||
|
|
t.Fatalf("unexpected error: %v", err)
|
||
|
|
}
|
||
|
|
|
||
|
|
// RFC 7636: unreserved characters [A-Z] / [a-z] / [0-9] / "-" / "." / "_" / "~"
|
||
|
|
valid := regexp.MustCompile(`^[A-Za-z0-9\-._~]+$`)
|
||
|
|
if !valid.MatchString(verifier) {
|
||
|
|
t.Errorf("verifier contains invalid characters: %q", verifier)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestGenerateChallengeCorrectness(t *testing.T) {
|
||
|
|
verifier, challenge, err := Generate()
|
||
|
|
if err != nil {
|
||
|
|
t.Fatalf("unexpected error: %v", err)
|
||
|
|
}
|
||
|
|
|
||
|
|
// Recompute challenge from verifier
|
||
|
|
h := sha256.Sum256([]byte(verifier))
|
||
|
|
expected := base64.RawURLEncoding.EncodeToString(h[:])
|
||
|
|
|
||
|
|
if challenge != expected {
|
||
|
|
t.Errorf("challenge = %q, want %q", challenge, expected)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestGenerateUniqueness(t *testing.T) {
|
||
|
|
v1, _, err := Generate()
|
||
|
|
if err != nil {
|
||
|
|
t.Fatalf("unexpected error: %v", err)
|
||
|
|
}
|
||
|
|
|
||
|
|
v2, _, err := Generate()
|
||
|
|
if err != nil {
|
||
|
|
t.Fatalf("unexpected error: %v", err)
|
||
|
|
}
|
||
|
|
|
||
|
|
if v1 == v2 {
|
||
|
|
t.Error("two Generate() calls produced identical verifiers")
|
||
|
|
}
|
||
|
|
}
|