package auth import ( "crypto/sha256" "encoding/base64" "strings" ) // PKCEMethod represents the code challenge method type PKCEMethod string const ( // PKCEMethodPlain uses the verifier directly as the challenge PKCEMethodPlain PKCEMethod = "plain" // PKCEMethodS256 uses SHA256 hash of the verifier PKCEMethodS256 PKCEMethod = "S256" ) // VerifyPKCE verifies that the code verifier matches the code challenge func VerifyPKCE(verifier, challenge string, method PKCEMethod) bool { if verifier == "" || challenge == "" { return false } switch method { case PKCEMethodPlain, "": // Plain method or no method specified - direct comparison return verifier == challenge case PKCEMethodS256: // S256 method - SHA256 hash, base64url encoded computed := ComputeS256Challenge(verifier) return computed == challenge default: return false } } // ComputeS256Challenge computes the S256 code challenge from a verifier func ComputeS256Challenge(verifier string) string { hash := sha256.Sum256([]byte(verifier)) return base64URLEncode(hash[:]) } // base64URLEncode encodes bytes to base64url without padding func base64URLEncode(data []byte) string { encoded := base64.URLEncoding.EncodeToString(data) // Remove padding return strings.TrimRight(encoded, "=") }