CodeSampleX

Пример

cloud.google.com/go/auth v0.18.2: PKCEOptions

Проверенный пример — golang cloud.google.com/go/auth v0.18.2: PKCEOptions. Контракт выполнен на go 1.26 · linux debian/x64 · docker и пройден.

sha256:6014c0dfe10b5b1478899de59ede7d010b8adca547b67b3795cd65d037a315d0

Эта сеть предлагает одно: образец, который собирается. Она запустила его в песочнице и сохранила подписанную квитанцию. Она ничего не оценивает и ничего не гарантирует — собирается ли тот же код у вас, она не измеряла. Сколько различных ключей подписи подали пройденную квитанцию контракта. Один — только автор; больше одного — значит, кто-то ещё тоже собрал. Ключ создаётся сам и не имеет зарегистрированной личности, поэтому считаются ключи, а не люди. MIT-0

Свидетельства выполнения

Заявленное окружение и подписанные запуски разделены, чтобы вы точно видели, что этот образец запускал и где.

Основа свидетельства
Подписанный контракт пройден
Квитанции проверки
1
Ключи подписи, собравшие его
1
Заявленная среда linux 24 · ubuntu · glibc 2.39 x64 go

Среды запусков проверки

Окружение Контракт Этапы Запуск
go 1.26 · linux debian/x64 · docker ed25519:c1973797be207ac4 PASS compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS
CONTAINER_RUN · golang@1golang:1.26@sha256:e30143be198a…
2026-10-11

Кейс

HOW
Цель
verify cloud.google.com/go/auth.PKCEOptions in pkg:golang/cloud.google.com/go/auth@v0.18.2
Пакеты
Символы
  • cloud.google.com/go/auth.PKCEOptions
Создан
2026-10-11T08:49:27Z

Контракт

  1. PKCEOptions initializes Challenge, ChallengeMethod, and Verifier fields
  2. PKCEOptions with S256 challenge populates code_challenge and code_challenge_method in authorization URL
  3. PKCEOptions with Verifier sends code_verifier in authorization code token exchange request body
  4. PKCEOptions with Challenge and empty ChallengeMethod supplies code_challenge without code_challenge_method
  5. Nil PKCEOptions in AuthorizationHandlerOptions produces authorization URL and token request without PKCE parameters

Файлы

  • PROMPT.md
  • csx.json
  • go.mod
  • go.sum
  • main.go
  • spec.json
  • test/contract.go

Скачать артефакт с исходным кодом (tar.gz)

Исходный код

PROMPT.md
Clean-room public code sample — generation instructions

Write a brand-new, minimal, self-contained code sample in this clean-room directory.
Do not copy, paraphrase, or reference any existing project source. Work only from this spec.

A csx.json manifest scaffold already exists. Do not recreate it from memory. Preserve its case.goal, packages and symbols; fill its empty case.contract with exact assertions and correct its environment, commands and verifierAdapter for the files you generate.

Goal: verify cloud.google.com/go/auth.PKCEOptions in pkg:golang/cloud.google.com/go/auth@v0.18.2
Kind: HOW

Use EXACTLY these public packages and versions:
  - pkg:golang/cloud.google.com/go/auth@v0.18.2
Demonstrate these symbols/APIs:
  - cloud.google.com/go/auth.PKCEOptions

Rules:
  - One focused purpose; the smallest project that proves the goal.
  - Include a contract test (test/contract.*) that runs OFFLINE and exits 0 exactly when the goal behavior works.
  - Pin every dependency with a lockfile so resolution is reproducible.
  - No secrets, credentials, or tokens. No real URLs (only example.com or localhost). No absolute paths.
  - No personal names, emails, company names, or project identifiers of any kind.
  - No binaries and no generated output (node_modules, dist, target, venv, .git, .env).
  - Keep it under 200 files and 256KB packed.
csx.json
{"case":{"caseId":"case:sha256:00804ef8d4ce8d51ccbcf41bd2f43de0188ee673732f87b5977a4e4e84916ba8","contract":["PKCEOptions initializes Challenge, ChallengeMethod, and Verifier fields","PKCEOptions with S256 challenge populates code_challenge and code_challenge_method in authorization URL","PKCEOptions with Verifier sends code_verifier in authorization code token exchange request body","PKCEOptions with Challenge and empty ChallengeMethod supplies code_challenge without code_challenge_method","Nil PKCEOptions in AuthorizationHandlerOptions produces authorization URL and token request without PKCE parameters"],"goal":"verify cloud.google.com/go/auth.PKCEOptions in pkg:golang/cloud.google.com/go/auth@v0.18.2","kind":"HOW","packages":["pkg:golang/cloud.google.com/go/auth@v0.18.2"],"schemaVersion":1,"symbols":["cloud.google.com/go/auth.PKCEOptions"]},"contractCommand":["go","run","./test"],"environment":{"arch":"x64","distro":"ubuntu","ecosystem":"golang","libc":"glibc","libcVersion":"2.39","os":"linux","osVersionBucket":"24","packageManager":"go","schemaVersion":1},"license":"MIT-0","packages":["pkg:golang/cloud.google.com/go/auth@v0.18.2"],"schemaVersion":1,"subject":"pkg:golang/cloud.google.com/go/auth@v0.18.2","symbols":["cloud.google.com/go/auth.PKCEOptions"],"verifierAdapter":"golang@1"}
go.mod
module sample

go 1.26.6

require cloud.google.com/go/auth v0.18.2

require (
	cloud.google.com/go/compute/metadata v0.9.0 // indirect
	github.com/googleapis/gax-go/v2 v2.17.0 // indirect
	golang.org/x/sys v0.40.0 // indirect
)
go.sum
cloud.google.com/go/auth v0.18.2 h1:+Nbt5Ev0xEqxlNjd6c+yYUeosQ5TtEUaNcN/3FozlaM=
cloud.google.com/go/auth v0.18.2/go.mod h1:xD+oY7gcahcu7G2SG2DsBerfFxgPAJz17zz2joOFF3M=
cloud.google.com/go/compute/metadata v0.9.0 h1:pDUj4QMoPejqq20dK0Pg2N4yG9zIkYGdBtwLoEkH9Zs=
cloud.google.com/go/compute/metadata v0.9.0/go.mod h1:E0bWwX5wTnLPedCKqk3pJmVgCBSM6qQI1yTBdEb3C10=
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/s2a-go v0.1.9 h1:LGD7gtMgezd8a/Xak7mEWL0PjoTQFvpRudN895yqKW0=
github.com/google/s2a-go v0.1.9/go.mod h1:YA0Ei2ZQL3acow2O62kdp9UlnvMmU7kA6Eutn0dXayM=
github.com/googleapis/enterprise-certificate-proxy v0.3.11 h1:vAe81Msw+8tKUxi2Dqh/NZMz7475yUvmRIkXr4oN2ao=
github.com/googleapis/enterprise-certificate-proxy v0.3.11/go.mod h1:RFV7MUdlb7AgEq2v7FmMCfeSMCllAzWxFgRdusoGks8=
github.com/googleapis/gax-go/v2 v2.17.0 h1:RksgfBpxqff0EZkDWYuz9q/uWsTVz+kf43LsZ1J6SMc=
github.com/googleapis/gax-go/v2 v2.17.0/go.mod h1:mzaqghpQp4JDh3HvADwrat+6M3MOIDp5YKHhb9PAgDY=
go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=
go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 h1:F7Jx+6hwnZ41NSFTO5q4LYDtJRXBf2PD0rNBkeB/lus=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0/go.mod h1:UHB22Z8QsdRDrnAtX4PntOl36ajSxcdUMt1sF7Y6E7Q=
go.opentelemetry.io/otel v1.39.0 h1:8yPrr/S0ND9QEfTfdP9V+SiwT4E0G7Y5MO7p85nis48=
go.opentelemetry.io/otel v1.39.0/go.mod h1:kLlFTywNWrFyEdH0oj2xK0bFYZtHRYUdv1NklR/tgc8=
go.opentelemetry.io/otel/metric v1.39.0 h1:d1UzonvEZriVfpNKEVmHXbdf909uGTOQjA0HF0Ls5Q0=
go.opentelemetry.io/otel/metric v1.39.0/go.mod h1:jrZSWL33sD7bBxg1xjrqyDjnuzTUB0x1nBERXd7Ftcs=
go.opentelemetry.io/otel/trace v1.39.0 h1:2d2vfpEDmCJ5zVYz7ijaJdOF59xLomrvj7bjt6/qCJI=
go.opentelemetry.io/otel/trace v1.39.0/go.mod h1:88w4/PnZSazkGzz/w84VHpQafiU4EtqqlVdxWy+rNOA=
golang.org/x/crypto v0.47.0 h1:V6e3FRj+n4dbpw86FJ8Fv7XVOql7TEwpHapKoMJ/GO8=
golang.org/x/crypto v0.47.0/go.mod h1:ff3Y9VzzKbwSSEzWqJsJVBnWmRwRSHt/6Op5n9bQc4A=
golang.org/x/net v0.49.0 h1:eeHFmOGUTtaaPSGNmjBKpbng9MulQsJURQUAfUwY++o=
golang.org/x/net v0.49.0/go.mod h1:/ysNB2EvaqvesRkuLAyjI1ycPZlQHM3q01F02UY/MV8=
golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ=
golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE=
golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8=
google.golang.org/genproto v0.0.0-20260128011058-8636f8732409 h1:VQZ/yAbAtjkHgH80teYd2em3xtIkkHd7ZhqfH2N9CsM=
google.golang.org/genproto/googleapis/rpc v0.0.0-20260128011058-8636f8732409 h1:H86B94AW+VfJWDqFeEbBPhEtHzJwJfTbgE2lZa54ZAQ=
google.golang.org/genproto/googleapis/rpc v0.0.0-20260128011058-8636f8732409/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ=
google.golang.org/grpc v1.78.0 h1:K1XZG/yGDJnzMdd/uZHAkVqJE+xIDOcmdSFZkBUicNc=
google.golang.org/grpc v1.78.0/go.mod h1:I47qjTo4OKbMkjA/aOOwxDIiPSBofUtQUI5EfpWvW7U=
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
main.go
package main

import (
	"context"
	"encoding/json"
	"fmt"
	"net/http"
	"net/http/httptest"
	"net/url"
	"time"

	"cloud.google.com/go/auth"
)

func main() {
	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		_ = r.ParseForm()
		w.Header().Set("Content-Type", "application/json")
		_ = json.NewEncoder(w).Encode(map[string]any{
			"access_token":  "mock-pkce-access-token",
			"token_type":    "Bearer",
			"refresh_token": "mock-pkce-refresh-token",
			"expires_in":    3600,
		})
	}))
	defer server.Close()

	pkce := &auth.PKCEOptions{
		Challenge:       "E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM",
		ChallengeMethod: "S256",
		Verifier:        "dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk",
	}

	opts := &auth.Options3LO{
		ClientID:  "pkce-sample-client",
		AuthURL:   server.URL + "/auth",
		TokenURL:  server.URL + "/token",
		AuthStyle: auth.StyleInParams,
		Client:    server.Client(),
		AuthHandlerOpts: &auth.AuthorizationHandlerOptions{
			State:    "sample-pkce-state",
			PKCEOpts: pkce,
			Handler: func(authCodeURL string) (string, string, error) {
				parsed, err := url.Parse(authCodeURL)
				if err != nil {
					return "", "", err
				}
				return "sample-auth-code", parsed.Query().Get("state"), nil
			},
		},
	}

	tp, err := auth.New3LOTokenProvider(opts)
	if err != nil {
		panic(err)
	}

	tok, err := tp.Token(context.Background())
	if err != nil {
		panic(err)
	}

	fmt.Printf("PKCE Token obtained: %s (type: %s, expiry: %s)\n", tok.Value, tok.Type, tok.Expiry.Format(time.RFC3339))
}
spec.json
{
  "schemaVersion": 1,
  "goal": "verify cloud.google.com/go/auth.PKCEOptions in pkg:golang/cloud.google.com/go/auth@v0.18.2",
  "kind": "HOW",
  "packages": [
    "pkg:golang/cloud.google.com/go/auth@v0.18.2"
  ],
  "symbols": [
    "cloud.google.com/go/auth.PKCEOptions"
  ]
}
test/contract.go
package main

import (
	"context"
	"encoding/json"
	"fmt"
	"net/http"
	"net/http/httptest"
	"net/url"
	"os"

	"cloud.google.com/go/auth"
)

func main() {
	if err := runContractTests(); err != nil {
		fmt.Fprintf(os.Stderr, "Contract test failed: %v\n", err)
		os.Exit(1)
	}
	fmt.Println("All contract tests passed successfully.")
}

func runContractTests() error {
	ctx := context.Background()

	// 1. PKCEOptions initializes Challenge, ChallengeMethod, and Verifier fields
	{
		opts := &auth.PKCEOptions{
			Challenge:       "test-challenge-str",
			ChallengeMethod: "S256",
			Verifier:        "test-verifier-str",
		}
		if opts.Challenge != "test-challenge-str" {
			return fmt.Errorf("test 1: expected Challenge 'test-challenge-str', got %q", opts.Challenge)
		}
		if opts.ChallengeMethod != "S256" {
			return fmt.Errorf("test 1: expected ChallengeMethod 'S256', got %q", opts.ChallengeMethod)
		}
		if opts.Verifier != "test-verifier-str" {
			return fmt.Errorf("test 1: expected Verifier 'test-verifier-str', got %q", opts.Verifier)
		}
	}

	// 2. PKCEOptions with S256 challenge populates code_challenge and code_challenge_method in authorization URL
	{
		var receivedChallenge string
		var receivedMethod string
		var receivedState string

		server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			w.Header().Set("Content-Type", "application/json")
			_ = json.NewEncoder(w).Encode(map[string]any{
				"access_token": "token-test-2",
				"token_type":   "Bearer",
				"expires_in":   3600,
			})
		}))
		defer server.Close()

		opts := &auth.Options3LO{
			ClientID:  "client-test-2",
			AuthURL:   server.URL + "/auth",
			TokenURL:  server.URL + "/token",
			AuthStyle: auth.StyleInParams,
			Client:    server.Client(),
			AuthHandlerOpts: &auth.AuthorizationHandlerOptions{
				State: "state-test-2",
				PKCEOpts: &auth.PKCEOptions{
					Challenge:       "challenge-abc-123",
					ChallengeMethod: "S256",
					Verifier:        "verifier-abc-123",
				},
				Handler: func(authCodeURL string) (string, string, error) {
					u, err := url.Parse(authCodeURL)
					if err != nil {
						return "", "", err
					}
					receivedChallenge = u.Query().Get("code_challenge")
					receivedMethod = u.Query().Get("code_challenge_method")
					receivedState = u.Query().Get("state")
					return "code-test-2", receivedState, nil
				},
			},
		}

		tp, err := auth.New3LOTokenProvider(opts)
		if err != nil {
			return fmt.Errorf("test 2: New3LOTokenProvider error: %w", err)
		}
		_, err = tp.Token(ctx)
		if err != nil {
			return fmt.Errorf("test 2: Token() error: %w", err)
		}
		if receivedChallenge != "challenge-abc-123" {
			return fmt.Errorf("test 2: expected code_challenge 'challenge-abc-123', got %q", receivedChallenge)
		}
		if receivedMethod != "S256" {
			return fmt.Errorf("test 2: expected code_challenge_method 'S256', got %q", receivedMethod)
		}
	}

	// 3. PKCEOptions with Verifier sends code_verifier in authorization code token exchange request body
	{
		var receivedGrantType string
		var receivedVerifier string
		var receivedCode string

		server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			_ = r.ParseForm()
			receivedGrantType = r.Form.Get("grant_type")
			receivedVerifier = r.Form.Get("code_verifier")
			receivedCode = r.Form.Get("code")

			w.Header().Set("Content-Type", "application/json")
			_ = json.NewEncoder(w).Encode(map[string]any{
				"access_token": "token-test-3",
				"token_type":   "Bearer",
				"expires_in":   3600,
			})
		}))
		defer server.Close()

		opts := &auth.Options3LO{
			ClientID:  "client-test-3",
			AuthURL:   server.URL + "/auth",
			TokenURL:  server.URL + "/token",
			AuthStyle: auth.StyleInParams,
			Client:    server.Client(),
			AuthHandlerOpts: &auth.AuthorizationHandlerOptions{
				State: "state-test-3",
				PKCEOpts: &auth.PKCEOptions{
					Challenge:       "challenge-xyz-789",
					ChallengeMethod: "S256",
					Verifier:        "verifier-secret-token-value",
				},
				Handler: func(authCodeURL string) (string, string, error) {
					return "auth-code-test-3", "state-test-3", nil
				},
			},
		}

		tp, err := auth.New3LOTokenProvider(opts)
		if err != nil {
			return fmt.Errorf("test 3: New3LOTokenProvider error: %w", err)
		}
		tok, err := tp.Token(ctx)
		if err != nil {
			return fmt.Errorf("test 3: Token() error: %w", err)
		}
		if tok.Value != "token-test-3" {
			return fmt.Errorf("test 3: unexpected token value %q", tok.Value)
		}
		if receivedGrantType != "authorization_code" {
			return fmt.Errorf("test 3: expected grant_type 'authorization_code', got %q", receivedGrantType)
		}
		if receivedCode != "auth-code-test-3" {
			return fmt.Errorf("test 3: expected code 'auth-code-test-3', got %q", receivedCode)
		}
		if receivedVerifier != "verifier-secret-token-value" {
			return fmt.Errorf("test 3: expected code_verifier 'verifier-secret-token-value', got %q", receivedVerifier)
		}
	}

	// 4. PKCEOptions with Challenge and empty ChallengeMethod supplies code_challenge without code_challenge_method
	{
		var receivedChallenge string
		var hasMethodParam bool

		server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			w.Header().Set("Content-Type", "application/json")
			_ = json.NewEncoder(w).Encode(map[string]any{
				"access_token": "token-test-4",
				"token_type":   "Bearer",
				"expires_in":   3600,
			})
		}))
		defer server.Close()

		opts := &auth.Options3LO{
			ClientID:  "client-test-4",
			AuthURL:   server.URL + "/auth",
			TokenURL:  server.URL + "/token",
			AuthStyle: auth.StyleInParams,
			Client:    server.Client(),
			AuthHandlerOpts: &auth.AuthorizationHandlerOptions{
				State: "state-test-4",
				PKCEOpts: &auth.PKCEOptions{
					Challenge:       "plain-challenge-only",
					ChallengeMethod: "",
					Verifier:        "plain-verifier-only",
				},
				Handler: func(authCodeURL string) (string, string, error) {
					u, err := url.Parse(authCodeURL)
					if err != nil {
						return "", "", err
					}
					receivedChallenge = u.Query().Get("code_challenge")
					_, hasMethodParam = u.Query()["code_challenge_method"]
					return "code-test-4", "state-test-4", nil
				},
			},
		}

		tp, err := auth.New3LOTokenProvider(opts)
		if err != nil {
			return fmt.Errorf("test 4: New3LOTokenProvider error: %w", err)
		}
		_, err = tp.Token(ctx)
		if err != nil {
			return fmt.Errorf("test 4: Token() error: %w", err)
		}
		if receivedChallenge != "plain-challenge-only" {
			return fmt.Errorf("test 4: expected code_challenge 'plain-challenge-only', got %q", receivedChallenge)
		}
		if hasMethodParam {
			return fmt.Errorf("test 4: expected no code_challenge_method parameter in URL")
		}
	}

	// 5. Nil PKCEOptions in AuthorizationHandlerOptions produces authorization URL and token request without PKCE parameters
	{
		var hasChallengeParam bool
		var hasMethodParam bool
		var hasVerifierParam bool

		server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			_ = r.ParseForm()
			_, hasVerifierParam = r.Form["code_verifier"]

			w.Header().Set("Content-Type", "application/json")
			_ = json.NewEncoder(w).Encode(map[string]any{
				"access_token": "token-test-5",
				"token_type":   "Bearer",
				"expires_in":   3600,
			})
		}))
		defer server.Close()

		opts := &auth.Options3LO{
			ClientID:  "client-test-5",
			AuthURL:   server.URL + "/auth",
			TokenURL:  server.URL + "/token",
			AuthStyle: auth.StyleInParams,
			Client:    server.Client(),
			AuthHandlerOpts: &auth.AuthorizationHandlerOptions{
				State:    "state-test-5",
				PKCEOpts: nil,
				Handler: func(authCodeURL string) (string, string, error) {
					u, err := url.Parse(authCodeURL)
					if err != nil {
						return "", "", err
					}
					_, hasChallengeParam = u.Query()["code_challenge"]
					_, hasMethodParam = u.Query()["code_challenge_method"]
					return "code-test-5", "state-test-5", nil
				},
			},
		}

		tp, err := auth.New3LOTokenProvider(opts)
		if err != nil {
			return fmt.Errorf("test 5: New3LOTokenProvider error: %w", err)
		}
		_, err = tp.Token(ctx)
		if err != nil {
			return fmt.Errorf("test 5: Token() error: %w", err)
		}
		if hasChallengeParam {
			return fmt.Errorf("test 5: unexpected code_challenge parameter in URL when PKCEOpts is nil")
		}
		if hasMethodParam {
			return fmt.Errorf("test 5: unexpected code_challenge_method parameter in URL when PKCEOpts is nil")
		}
		if hasVerifierParam {
			return fmt.Errorf("test 5: unexpected code_verifier parameter in token request when PKCEOpts is nil")
		}
	}

	return nil
}

Исходный сидер

аноним