Repository: istio-ecosystem/authservice
Pull request #265 (2024-10-09 20:05:58)

Add support for PKCE
This PR adds support for PKCE (Proof Key for Code Exchange) to enhance the security of the OAuth 2.0 Authorization Code flow. It includes generating a code verifier and code challenge, and ensures these parameters are used during the authorization and token exchange processes. This update aligns with OAuth 2.0 best practices and improves compatibility with identity providers that require PKCE.

More details about PKCE here: 
* https://oauth.net/2/pkce/
* https://blog.postman.com/what-is-pkce/


nacx: CI complains about project not being go mod tidied.

Since we have code generation, the `check` job makes sure there are no changes after regrating/formatting everything, and fails early if that's not the case.

If you run locally `make check` locally, it should update what's missing and you can commit that to have that check pass.

Patch:
diff --git a/.licenserc.yaml b/.licenserc.yaml
new file mode 100644
index 0000000..33ba603
--- /dev/null
+++ b/.licenserc.yaml
@@ -0,0 +1,35 @@
+# Copyright 2024 Tetrate
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+header:
+  license:
+    spdx-id: Apache-2.0
+    copyright-owner: Tetrate
+  paths-ignore:
+    - '**/go.mod'
+    - '**/go.sum'
+    - '**/*.md'
+    - '**/*.lock'
+    - '**/*.txt'
+    - '**/*.json'
+    - '**/*.crt'
+    - '**/*.csr'
+    - '**/*.srl'
+    - '**/*.key'
+    - '**/.gitignore'
+    - '**/kubeconfig'
+    - '**/bin/*'
+    - LICENSE
+    - CODEOWNERS
+    - 'config/**/*.go'
diff --git a/.licenserignore b/.licenserignore
deleted file mode 100644
index c54f896..0000000
--- a/.licenserignore
+++ /dev/null
@@ -1,16 +0,0 @@
-*.txt
-.idea
-go.mod
-go.sum
-*.png
-*.lock
-config/**/*.go
-bin/
-.vimrc
-*.json
-LICENSE
-*.crt
-*.csr
-*.srl
-*.key
-kubeconfig
diff --git a/Makefile b/Makefile
index 4d8f219..e89ed8c 100644
--- a/Makefile
+++ b/Makefile
@@ -203,7 +203,7 @@ lint: $(GOLANGCI_LINT_CONFIG) config/lint  ## Lint checks for all Go code
 .PHONY: format
 format: go.mod  ## Format all Go code
 	@echo "Formatting code"
-	@go run $(LICENSER) apply -r "Tetrate"
+	@@go run $(SWEYES) header fix
 	@go run $(GOSIMPORTS) -local $(GO_MODULE) -w .
 	@gofmt -w .
 
diff --git a/config/Makefile b/config/Makefile
index cd7d4ca..dcb9a4c 100644
--- a/config/Makefile
+++ b/config/Makefile
@@ -12,14 +12,13 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-BUF ?= github.com/bufbuild/buf/cmd/buf@v1.17.0
+BUF ?= github.com/bufbuild/buf/cmd/buf@v1.32.2
 
 PROTO_SOURCES := $(shell find . -name '*.proto')
 
 .PHONY: build
 build: $(PROTO_SOURCES) ## Generate the Go code from the protobuf definitions
 	@echo "Generating Go code from protobuf definitions"
-	@go run $(BUF) mod update
 	@go run $(BUF) build
 	@go run $(BUF) generate
 	@go mod tidy
diff --git a/config/buf.gen.yaml b/config/buf.gen.yaml
index 4e0e53a..c054895 100644
--- a/config/buf.gen.yaml
+++ b/config/buf.gen.yaml
@@ -24,7 +24,7 @@ plugins:
     out: gen/go
     opt:
       - paths=source_relative
-  - plugin: buf.build/bufbuild/validate-go
+  - plugin: buf.build/bufbuild/validate-go:v1.0.4
     out: gen/go
     opt:
       - paths=source_relative
diff --git a/config/buf.lock b/config/buf.lock
index 8585935..fafef03 100644
--- a/config/buf.lock
+++ b/config/buf.lock
@@ -4,5 +4,5 @@ deps:
   - remote: buf.build
     owner: envoyproxy
     repository: protoc-gen-validate
-    commit: 6607b10f00ed4a3d98f906807131c44a
-    digest: shake256:acc7b2ededb2f88d296862943a003b157bdb68ec93ed13dcd8566b2d06e47993ea6daf12013b9655658aaf6bbdb141cf65bfe400ce2870f4654b0a5b45e57c09
+    commit: daf171c6cdb54629b5f51e345a79e4dd
+    digest: shake256:4ae167d7eed10da5f83a3f5df8c670d249170f11b1f2fd19afda06be2cff4d47dcc95e9e4a15151ecc8ce2d3d3614caf9a04d3ad82fb768a3870dedfa9455f36
diff --git a/config/buf.yaml b/config/buf.yaml
index d9ea53c..53e9e32 100644
--- a/config/buf.yaml
+++ b/config/buf.yaml
@@ -15,7 +15,7 @@
 version: v1
 name: buf.build/authservice/config
 deps:
-  - buf.build/envoyproxy/protoc-gen-validate:6607b10f00ed4a3d98f906807131c44a
+  - buf.build/envoyproxy/protoc-gen-validate
 lint:
   use:
     - DEFAULT
diff --git a/config/gen/go/v1/oidc/config.pb.go b/config/gen/go/v1/oidc/config.pb.go
index abc10bc..1c51e39 100644
--- a/config/gen/go/v1/oidc/config.pb.go
+++ b/config/gen/go/v1/oidc/config.pb.go
@@ -259,6 +259,8 @@ type OIDCConfig struct {
 	// The OIDC client ID assigned to the filter to be used in the
 	// [Authentication Request](https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest).
 	// Required.
+	// The client ID is used to authenticate to the Token endpoint using HTTP Basic Auth and it
+	// must not contain a colon (":") character.
 	ClientId string `protobuf:"bytes,5,opt,name=client_id,json=clientId,proto3" json:"client_id,omitempty"`
 	// Types that are assignable to ClientSecretConfig:
 	//
@@ -786,7 +788,7 @@ var file_v1_oidc_config_proto_rawDesc = []byte{
 	0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x72,
 	0x02, 0x10, 0x01, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x21, 0x0a, 0x0c, 0x72, 0x65, 0x64,
 	0x69, 0x72, 0x65, 0x63, 0x74, 0x5f, 0x75, 0x72, 0x69, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52,
-	0x0b, 0x72, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x55, 0x72, 0x69, 0x22, 0x9e, 0x0d, 0x0a,
+	0x0b, 0x72, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x55, 0x72, 0x69, 0x22, 0xa2, 0x0d, 0x0a,
 	0x0a, 0x4f, 0x49, 0x44, 0x43, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x2b, 0x0a, 0x11, 0x63,
 	0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x75, 0x72, 0x69,
 	0x18, 0x13, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72,
@@ -805,110 +807,111 @@ var file_v1_oidc_config_proto_rawDesc = []byte{
 	0x76, 0x31, 0x2e, 0x6f, 0x69, 0x64, 0x63, 0x2e, 0x4f, 0x49, 0x44, 0x43, 0x43, 0x6f, 0x6e, 0x66,
 	0x69, 0x67, 0x2e, 0x4a, 0x77, 0x6b, 0x73, 0x46, 0x65, 0x74, 0x63, 0x68, 0x65, 0x72, 0x43, 0x6f,
 	0x6e, 0x66, 0x69, 0x67, 0x48, 0x00, 0x52, 0x0b, 0x6a, 0x77, 0x6b, 0x73, 0x46, 0x65, 0x74, 0x63,
-	0x68, 0x65, 0x72, 0x12, 0x24, 0x0a, 0x09, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64,
-	0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52,
-	0x08, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x2e, 0x0a, 0x0d, 0x63, 0x6c, 0x69,
-	0x65, 0x6e, 0x74, 0x5f, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09,
-	0x42, 0x07, 0xfa, 0x42, 0x04, 0x72, 0x02, 0x10, 0x01, 0x48, 0x01, 0x52, 0x0c, 0x63, 0x6c, 0x69,
-	0x65, 0x6e, 0x74, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x12, 0x64, 0x0a, 0x11, 0x63, 0x6c, 0x69,
-	0x65, 0x6e, 0x74, 0x5f, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x5f, 0x72, 0x65, 0x66, 0x18, 0x15,
-	0x20, 0x01, 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x61, 0x75, 0x74, 0x68, 0x73, 0x65, 0x72, 0x76, 0x69,
-	0x63, 0x65, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x6f, 0x69, 0x64,
-	0x63, 0x2e, 0x4f, 0x49, 0x44, 0x43, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x53, 0x65, 0x63,
-	0x72, 0x65, 0x74, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x48, 0x01, 0x52, 0x0f,
-	0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x52, 0x65, 0x66, 0x12,
-	0x16, 0x0a, 0x06, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x09, 0x52,
-	0x06, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x12, 0x2c, 0x0a, 0x12, 0x63, 0x6f, 0x6f, 0x6b, 0x69,
-	0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x08, 0x20,
-	0x01, 0x28, 0x09, 0x52, 0x10, 0x63, 0x6f, 0x6f, 0x6b, 0x69, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x50,
-	0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x4c, 0x0a, 0x08, 0x69, 0x64, 0x5f, 0x74, 0x6f, 0x6b, 0x65,
-	0x6e, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x61, 0x75, 0x74, 0x68, 0x73, 0x65,
-	0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x76, 0x31, 0x2e,
-	0x6f, 0x69, 0x64, 0x63, 0x2e, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
-	0x42, 0x08, 0xfa, 0x42, 0x05, 0x8a, 0x01, 0x02, 0x10, 0x01, 0x52, 0x07, 0x69, 0x64, 0x54, 0x6f,
-	0x6b, 0x65, 0x6e, 0x12, 0x4a, 0x0a, 0x0c, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x74, 0x6f,
-	0x6b, 0x65, 0x6e, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x61, 0x75, 0x74, 0x68,
-	0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x76,
-	0x31, 0x2e, 0x6f, 0x69, 0x64, 0x63, 0x2e, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x43, 0x6f, 0x6e, 0x66,
-	0x69, 0x67, 0x52, 0x0b, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12,
-	0x40, 0x0a, 0x06, 0x6c, 0x6f, 0x67, 0x6f, 0x75, 0x74, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32,
-	0x28, 0x2e, 0x61, 0x75, 0x74, 0x68, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x63, 0x6f,
-	0x6e, 0x66, 0x69, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x6f, 0x69, 0x64, 0x63, 0x2e, 0x4c, 0x6f, 0x67,
-	0x6f, 0x75, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x06, 0x6c, 0x6f, 0x67, 0x6f, 0x75,
-	0x74, 0x12, 0x38, 0x0a, 0x18, 0x61, 0x62, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x65, 0x5f, 0x73, 0x65,
-	0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x0c, 0x20,
-	0x01, 0x28, 0x0d, 0x52, 0x16, 0x61, 0x62, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x65, 0x53, 0x65, 0x73,
-	0x73, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x30, 0x0a, 0x14, 0x69,
-	0x64, 0x6c, 0x65, 0x5f, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x69, 0x6d, 0x65,
-	0x6f, 0x75, 0x74, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x12, 0x69, 0x64, 0x6c, 0x65, 0x53,
-	0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x44, 0x0a,
-	0x1d, 0x74, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x5f, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69,
-	0x63, 0x61, 0x74, 0x65, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x18, 0x0e,
-	0x20, 0x01, 0x28, 0x09, 0x48, 0x02, 0x52, 0x1b, 0x74, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x43,
-	0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72,
-	0x69, 0x74, 0x79, 0x12, 0x4d, 0x0a, 0x22, 0x74, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x5f, 0x63,
-	0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x6f,
-	0x72, 0x69, 0x74, 0x79, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x14, 0x20, 0x01, 0x28, 0x09, 0x48,
-	0x02, 0x52, 0x1f, 0x74, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66,
-	0x69, 0x63, 0x61, 0x74, 0x65, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x46, 0x69,
-	0x6c, 0x65, 0x12, 0x7d, 0x0a, 0x2e, 0x74, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x5f, 0x63, 0x65,
-	0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72,
-	0x69, 0x74, 0x79, 0x5f, 0x72, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x5f, 0x69, 0x6e, 0x74, 0x65,
-	0x72, 0x76, 0x61, 0x6c, 0x18, 0x16, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f,
-	0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72,
-	0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x2a, 0x74, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x43, 0x65,
+	0x68, 0x65, 0x72, 0x12, 0x28, 0x0a, 0x09, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64,
+	0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x42, 0x0b, 0xfa, 0x42, 0x08, 0x72, 0x06, 0x10, 0x01, 0xba,
+	0x01, 0x01, 0x3a, 0x52, 0x08, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x2e, 0x0a,
+	0x0d, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x18, 0x06,
+	0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x72, 0x02, 0x10, 0x01, 0x48, 0x01, 0x52,
+	0x0c, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x12, 0x64, 0x0a,
+	0x11, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x5f, 0x72,
+	0x65, 0x66, 0x18, 0x15, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x61, 0x75, 0x74, 0x68, 0x73,
+	0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x76, 0x31,
+	0x2e, 0x6f, 0x69, 0x64, 0x63, 0x2e, 0x4f, 0x49, 0x44, 0x43, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
+	0x2e, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65,
+	0x48, 0x01, 0x52, 0x0f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74,
+	0x52, 0x65, 0x66, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x18, 0x07, 0x20,
+	0x03, 0x28, 0x09, 0x52, 0x06, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x12, 0x2c, 0x0a, 0x12, 0x63,
+	0x6f, 0x6f, 0x6b, 0x69, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x70, 0x72, 0x65, 0x66, 0x69,
+	0x78, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x63, 0x6f, 0x6f, 0x6b, 0x69, 0x65, 0x4e,
+	0x61, 0x6d, 0x65, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x4c, 0x0a, 0x08, 0x69, 0x64, 0x5f,
+	0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x61, 0x75,
+	0x74, 0x68, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67,
+	0x2e, 0x76, 0x31, 0x2e, 0x6f, 0x69, 0x64, 0x63, 0x2e, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x43, 0x6f,
+	0x6e, 0x66, 0x69, 0x67, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x8a, 0x01, 0x02, 0x10, 0x01, 0x52, 0x07,
+	0x69, 0x64, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x4a, 0x0a, 0x0c, 0x61, 0x63, 0x63, 0x65, 0x73,
+	0x73, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e,
+	0x61, 0x75, 0x74, 0x68, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x63, 0x6f, 0x6e, 0x66,
+	0x69, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x6f, 0x69, 0x64, 0x63, 0x2e, 0x54, 0x6f, 0x6b, 0x65, 0x6e,
+	0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0b, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f,
+	0x6b, 0x65, 0x6e, 0x12, 0x40, 0x0a, 0x06, 0x6c, 0x6f, 0x67, 0x6f, 0x75, 0x74, 0x18, 0x0b, 0x20,
+	0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x61, 0x75, 0x74, 0x68, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63,
+	0x65, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x6f, 0x69, 0x64, 0x63,
+	0x2e, 0x4c, 0x6f, 0x67, 0x6f, 0x75, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x06, 0x6c,
+	0x6f, 0x67, 0x6f, 0x75, 0x74, 0x12, 0x38, 0x0a, 0x18, 0x61, 0x62, 0x73, 0x6f, 0x6c, 0x75, 0x74,
+	0x65, 0x5f, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75,
+	0x74, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x16, 0x61, 0x62, 0x73, 0x6f, 0x6c, 0x75, 0x74,
+	0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12,
+	0x30, 0x0a, 0x14, 0x69, 0x64, 0x6c, 0x65, 0x5f, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f,
+	0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x12, 0x69,
+	0x64, 0x6c, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75,
+	0x74, 0x12, 0x44, 0x0a, 0x1d, 0x74, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x5f, 0x63, 0x65, 0x72,
+	0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69,
+	0x74, 0x79, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x48, 0x02, 0x52, 0x1b, 0x74, 0x72, 0x75, 0x73,
+	0x74, 0x65, 0x64, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x41, 0x75,
+	0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x12, 0x4d, 0x0a, 0x22, 0x74, 0x72, 0x75, 0x73, 0x74,
+	0x65, 0x64, 0x5f, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x5f, 0x61,
+	0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x14, 0x20,
+	0x01, 0x28, 0x09, 0x48, 0x02, 0x52, 0x1f, 0x74, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x43, 0x65,
 	0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69,
-	0x74, 0x79, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61,
-	0x6c, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x5f, 0x75, 0x72, 0x69, 0x18, 0x0f,
-	0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x55, 0x72, 0x69, 0x12, 0x64,
-	0x0a, 0x1a, 0x72, 0x65, 0x64, 0x69, 0x73, 0x5f, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f,
-	0x73, 0x74, 0x6f, 0x72, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x10, 0x20, 0x01,
-	0x28, 0x0b, 0x32, 0x27, 0x2e, 0x61, 0x75, 0x74, 0x68, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65,
-	0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x6f, 0x69, 0x64, 0x63, 0x2e,
-	0x52, 0x65, 0x64, 0x69, 0x73, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x17, 0x72, 0x65, 0x64,
-	0x69, 0x73, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x43, 0x6f,
-	0x6e, 0x66, 0x69, 0x67, 0x12, 0x49, 0x0a, 0x15, 0x73, 0x6b, 0x69, 0x70, 0x5f, 0x76, 0x65, 0x72,
-	0x69, 0x66, 0x79, 0x5f, 0x70, 0x65, 0x65, 0x72, 0x5f, 0x63, 0x65, 0x72, 0x74, 0x18, 0x12, 0x20,
-	0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f,
-	0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x12, 0x73, 0x6b, 0x69,
-	0x70, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x50, 0x65, 0x65, 0x72, 0x43, 0x65, 0x72, 0x74, 0x1a,
-	0xbc, 0x01, 0x0a, 0x11, 0x4a, 0x77, 0x6b, 0x73, 0x46, 0x65, 0x74, 0x63, 0x68, 0x65, 0x72, 0x43,
-	0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x19, 0x0a, 0x08, 0x6a, 0x77, 0x6b, 0x73, 0x5f, 0x75, 0x72,
-	0x69, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6a, 0x77, 0x6b, 0x73, 0x55, 0x72, 0x69,
-	0x12, 0x3d, 0x0a, 0x1b, 0x70, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x69, 0x63, 0x5f, 0x66, 0x65, 0x74,
-	0x63, 0x68, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x5f, 0x73, 0x65, 0x63, 0x18,
-	0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x18, 0x70, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x69, 0x63, 0x46,
-	0x65, 0x74, 0x63, 0x68, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x53, 0x65, 0x63, 0x12,
-	0x4d, 0x0a, 0x15, 0x73, 0x6b, 0x69, 0x70, 0x5f, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x5f, 0x70,
-	0x65, 0x65, 0x72, 0x5f, 0x63, 0x65, 0x72, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16,
+	0x74, 0x79, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x7d, 0x0a, 0x2e, 0x74, 0x72, 0x75, 0x73, 0x74, 0x65,
+	0x64, 0x5f, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x5f, 0x61, 0x75,
+	0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x5f, 0x72, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x5f,
+	0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x16, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19,
 	0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66,
-	0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x02, 0x18, 0x01, 0x52, 0x12, 0x73, 0x6b, 0x69, 0x70,
-	0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x50, 0x65, 0x65, 0x72, 0x43, 0x65, 0x72, 0x74, 0x1a, 0x4c,
-	0x0a, 0x0f, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63,
-	0x65, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x01,
-	0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12,
-	0x1b, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa,
-	0x42, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x42, 0x0d, 0x0a, 0x0b,
-	0x6a, 0x77, 0x6b, 0x73, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x42, 0x1b, 0x0a, 0x14, 0x63,
-	0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x5f, 0x63, 0x6f, 0x6e,
-	0x66, 0x69, 0x67, 0x12, 0x03, 0xf8, 0x42, 0x01, 0x42, 0x13, 0x0a, 0x11, 0x74, 0x72, 0x75, 0x73,
-	0x74, 0x65, 0x64, 0x5f, 0x63, 0x61, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x42, 0xf7, 0x01,
-	0x0a, 0x1e, 0x63, 0x6f, 0x6d, 0x2e, 0x61, 0x75, 0x74, 0x68, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63,
-	0x65, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x6f, 0x69, 0x64, 0x63,
-	0x42, 0x0b, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a,
-	0x3c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x69, 0x73, 0x74, 0x69,
-	0x6f, 0x2d, 0x65, 0x63, 0x6f, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x2f, 0x61, 0x75, 0x74, 0x68,
-	0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2f, 0x67,
-	0x65, 0x6e, 0x2f, 0x67, 0x6f, 0x2f, 0x76, 0x31, 0x2f, 0x6f, 0x69, 0x64, 0x63, 0xa2, 0x02, 0x04,
-	0x41, 0x43, 0x56, 0x4f, 0xaa, 0x02, 0x1a, 0x41, 0x75, 0x74, 0x68, 0x73, 0x65, 0x72, 0x76, 0x69,
-	0x63, 0x65, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x56, 0x31, 0x2e, 0x4f, 0x69, 0x64,
-	0x63, 0xca, 0x02, 0x1a, 0x41, 0x75, 0x74, 0x68, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5c,
-	0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5c, 0x56, 0x31, 0x5c, 0x4f, 0x69, 0x64, 0x63, 0xe2, 0x02,
-	0x26, 0x41, 0x75, 0x74, 0x68, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5c, 0x43, 0x6f, 0x6e,
-	0x66, 0x69, 0x67, 0x5c, 0x56, 0x31, 0x5c, 0x4f, 0x69, 0x64, 0x63, 0x5c, 0x47, 0x50, 0x42, 0x4d,
-	0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x1d, 0x41, 0x75, 0x74, 0x68, 0x73, 0x65,
-	0x72, 0x76, 0x69, 0x63, 0x65, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x3a, 0x3a, 0x56,
-	0x31, 0x3a, 0x3a, 0x4f, 0x69, 0x64, 0x63, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
+	0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x2a, 0x74, 0x72, 0x75, 0x73, 0x74,
+	0x65, 0x64, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x41, 0x75, 0x74,
+	0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x49, 0x6e, 0x74,
+	0x65, 0x72, 0x76, 0x61, 0x6c, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x5f, 0x75,
+	0x72, 0x69, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x55,
+	0x72, 0x69, 0x12, 0x64, 0x0a, 0x1a, 0x72, 0x65, 0x64, 0x69, 0x73, 0x5f, 0x73, 0x65, 0x73, 0x73,
+	0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67,
+	0x18, 0x10, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x61, 0x75, 0x74, 0x68, 0x73, 0x65, 0x72,
+	0x76, 0x69, 0x63, 0x65, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x6f,
+	0x69, 0x64, 0x63, 0x2e, 0x52, 0x65, 0x64, 0x69, 0x73, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52,
+	0x17, 0x72, 0x65, 0x64, 0x69, 0x73, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x6f,
+	0x72, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x49, 0x0a, 0x15, 0x73, 0x6b, 0x69, 0x70,
+	0x5f, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x5f, 0x70, 0x65, 0x65, 0x72, 0x5f, 0x63, 0x65, 0x72,
+	0x74, 0x18, 0x12, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
+	0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52,
+	0x12, 0x73, 0x6b, 0x69, 0x70, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x50, 0x65, 0x65, 0x72, 0x43,
+	0x65, 0x72, 0x74, 0x1a, 0xbc, 0x01, 0x0a, 0x11, 0x4a, 0x77, 0x6b, 0x73, 0x46, 0x65, 0x74, 0x63,
+	0x68, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x19, 0x0a, 0x08, 0x6a, 0x77, 0x6b,
+	0x73, 0x5f, 0x75, 0x72, 0x69, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6a, 0x77, 0x6b,
+	0x73, 0x55, 0x72, 0x69, 0x12, 0x3d, 0x0a, 0x1b, 0x70, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x69, 0x63,
+	0x5f, 0x66, 0x65, 0x74, 0x63, 0x68, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x5f,
+	0x73, 0x65, 0x63, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x18, 0x70, 0x65, 0x72, 0x69, 0x6f,
+	0x64, 0x69, 0x63, 0x46, 0x65, 0x74, 0x63, 0x68, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c,
+	0x53, 0x65, 0x63, 0x12, 0x4d, 0x0a, 0x15, 0x73, 0x6b, 0x69, 0x70, 0x5f, 0x76, 0x65, 0x72, 0x69,
+	0x66, 0x79, 0x5f, 0x70, 0x65, 0x65, 0x72, 0x5f, 0x63, 0x65, 0x72, 0x74, 0x18, 0x03, 0x20, 0x01,
+	0x28, 0x0b, 0x32, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+	0x6f, 0x62, 0x75, 0x66, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x02, 0x18, 0x01, 0x52, 0x12,
+	0x73, 0x6b, 0x69, 0x70, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x50, 0x65, 0x65, 0x72, 0x43, 0x65,
+	0x72, 0x74, 0x1a, 0x4c, 0x0a, 0x0f, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x52, 0x65, 0x66, 0x65,
+	0x72, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61,
+	0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70,
+	0x61, 0x63, 0x65, 0x12, 0x1b, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28,
+	0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65,
+	0x42, 0x0d, 0x0a, 0x0b, 0x6a, 0x77, 0x6b, 0x73, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x42,
+	0x1b, 0x0a, 0x14, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74,
+	0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x03, 0xf8, 0x42, 0x01, 0x42, 0x13, 0x0a, 0x11,
+	0x74, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x5f, 0x63, 0x61, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69,
+	0x67, 0x42, 0xf7, 0x01, 0x0a, 0x1e, 0x63, 0x6f, 0x6d, 0x2e, 0x61, 0x75, 0x74, 0x68, 0x73, 0x65,
+	0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x76, 0x31, 0x2e,
+	0x6f, 0x69, 0x64, 0x63, 0x42, 0x0b, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x50, 0x72, 0x6f, 0x74,
+	0x6f, 0x50, 0x01, 0x5a, 0x3c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f,
+	0x69, 0x73, 0x74, 0x69, 0x6f, 0x2d, 0x65, 0x63, 0x6f, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x2f,
+	0x61, 0x75, 0x74, 0x68, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2f, 0x63, 0x6f, 0x6e, 0x66,
+	0x69, 0x67, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x67, 0x6f, 0x2f, 0x76, 0x31, 0x2f, 0x6f, 0x69, 0x64,
+	0x63, 0xa2, 0x02, 0x04, 0x41, 0x43, 0x56, 0x4f, 0xaa, 0x02, 0x1a, 0x41, 0x75, 0x74, 0x68, 0x73,
+	0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x56, 0x31,
+	0x2e, 0x4f, 0x69, 0x64, 0x63, 0xca, 0x02, 0x1a, 0x41, 0x75, 0x74, 0x68, 0x73, 0x65, 0x72, 0x76,
+	0x69, 0x63, 0x65, 0x5c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5c, 0x56, 0x31, 0x5c, 0x4f, 0x69,
+	0x64, 0x63, 0xe2, 0x02, 0x26, 0x41, 0x75, 0x74, 0x68, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65,
+	0x5c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5c, 0x56, 0x31, 0x5c, 0x4f, 0x69, 0x64, 0x63, 0x5c,
+	0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x1d, 0x41, 0x75,
+	0x74, 0x68, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x66, 0x69,
+	0x67, 0x3a, 0x3a, 0x56, 0x31, 0x3a, 0x3a, 0x4f, 0x69, 0x64, 0x63, 0x62, 0x06, 0x70, 0x72, 0x6f,
+	0x74, 0x6f, 0x33,
 }
 
 var (
diff --git a/config/gen/go/v1/oidc/config.pb.validate.go b/config/gen/go/v1/oidc/config.pb.validate.go
index 865f046..8d3e57d 100644
--- a/config/gen/go/v1/oidc/config.pb.validate.go
+++ b/config/gen/go/v1/oidc/config.pb.validate.go
@@ -419,6 +419,17 @@ func (m *OIDCConfig) validate(all bool) error {
 		errors = append(errors, err)
 	}
 
+	if strings.Contains(m.GetClientId(), ":") {
+		err := OIDCConfigValidationError{
+			field:  "ClientId",
+			reason: "value contains substring \":\"",
+		}
+		if !all {
+			return err
+		}
+		errors = append(errors, err)
+	}
+
 	// no validation rules for CookieNamePrefix
 
 	if m.GetIdToken() == nil {
diff --git a/config/v1/oidc/config.proto b/config/v1/oidc/config.proto
index 8c2070e..48ac6b6 100644
--- a/config/v1/oidc/config.proto
+++ b/config/v1/oidc/config.proto
@@ -132,7 +132,9 @@ message OIDCConfig {
   // The OIDC client ID assigned to the filter to be used in the
   // [Authentication Request](https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest).
   // Required.
-  string client_id = 5 [(validate.rules).string.min_len = 1];
+  // The client ID is used to authenticate to the Token endpoint using HTTP Basic Auth and it
+  // must not contain a colon (":") character.
+  string client_id = 5 [(validate.rules).string = {min_len: 1, not_contains: ":"}];
 
   // This message defines a reference to a Kubernetes Secret resource.
   message SecretReference {
diff --git a/env.mk b/env.mk
index 7840f99..b000dca 100644
--- a/env.mk
+++ b/env.mk
@@ -18,9 +18,9 @@ NAME      ?= authservice
 
 -include $(ROOT)/.makerc  # Pick up any local overrides.
 
-GOLANGCI_LINT ?= github.com/golangci/golangci-lint/cmd/golangci-lint@v1.60.3
+GOLANGCI_LINT ?= github.com/golangci/golangci-lint/cmd/golangci-lint@v1.61.0
 GOSIMPORTS    ?= github.com/rinchsan/gosimports/cmd/gosimports@v0.3.8
-LICENSER      ?= github.com/liamawhite/licenser@v0.6.1-0.20210729145742-be6c77bf6a1f
+SWEYES        ?= github.com/apache/skywalking-eyes/cmd/license-eye@v0.6.0
 KIND          ?= sigs.k8s.io/kind@v0.18.0
 ENVTEST       ?= sigs.k8s.io/controller-runtime/tools/setup-envtest@latest
 
diff --git a/go.mod b/go.mod
index 52839f6..ed5144e 100644
--- a/go.mod
+++ b/go.mod
@@ -15,6 +15,7 @@ require (
 	github.com/tetratelabs/run v0.3.0
 	github.com/tetratelabs/telemetry v0.8.2
 	golang.org/x/net v0.23.0
+	golang.org/x/oauth2 v0.18.0
 	google.golang.org/genproto/googleapis/rpc v0.0.0-20240304212257-790db918fca8
 	google.golang.org/grpc v1.62.1
 	google.golang.org/protobuf v1.33.0
@@ -74,7 +75,6 @@ require (
 	github.com/yuin/gopher-lua v1.1.1 // indirect
 	golang.org/x/crypto v0.21.0 // indirect
 	golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 // indirect
-	golang.org/x/oauth2 v0.18.0 // indirect
 	golang.org/x/sys v0.18.0 // indirect
 	golang.org/x/term v0.18.0 // indirect
 	golang.org/x/text v0.14.0 // indirect
diff --git a/internal/authz/oidc.go b/internal/authz/oidc.go
index d5a2d8f..ce224f3 100644
--- a/internal/authz/oidc.go
+++ b/internal/authz/oidc.go
@@ -30,6 +30,7 @@ import (
 	typev3 "github.com/envoyproxy/go-control-plane/envoy/type/v3"
 	"github.com/lestrrat-go/jwx/v2/jws"
 	"github.com/tetratelabs/telemetry"
+	"golang.org/x/oauth2"
 	"google.golang.org/genproto/googleapis/rpc/status"
 	"google.golang.org/grpc/codes"
 
@@ -237,9 +238,10 @@ func (o *oidcHandler) redirectToIDP(ctx context.Context, log telemetry.Logger,
 	}
 
 	var (
-		sessionID = o.sessionGen.GenerateSessionID()
-		nonce     = o.sessionGen.GenerateNonce()
-		state     = o.sessionGen.GenerateState()
+		sessionID    = o.sessionGen.GenerateSessionID()
+		nonce        = o.sessionGen.GenerateNonce()
+		state        = o.sessionGen.GenerateState()
+		codeVerifier = o.sessionGen.GenerateCodeVerifier()
 	)
 
 	// Store the authorization state
@@ -251,6 +253,7 @@ func (o *oidcHandler) redirectToIDP(ctx context.Context, log telemetry.Logger,
 		State:        state,
 		Nonce:        nonce,
 		RequestedURL: requestedURL,
+		CodeVerifier: codeVerifier,
 	}); err != nil {
 		log.Error("error storing the new authorization state", err)
 		setDenyResponse(resp, newSessionErrorResponse(), codes.Unauthenticated)
@@ -259,12 +262,14 @@ func (o *oidcHandler) redirectToIDP(ctx context.Context, log telemetry.Logger,
 
 	// Generate the redirect URL
 	query := url.Values{
-		"response_type": []string{"code"},
-		"client_id":     []string{o.config.GetClientId()},
-		"redirect_uri":  []string{o.config.GetCallbackUri()},
-		"scope":         []string{strings.Join(o.config.GetScopes(), " ")},
-		"state":         []string{state},
-		"nonce":         []string{nonce},
+		"response_type":         []string{"code"},
+		"client_id":             []string{o.config.GetClientId()},
+		"redirect_uri":          []string{o.config.GetCallbackUri()},
+		"scope":                 []string{strings.Join(o.config.GetScopes(), " ")},
+		"state":                 []string{state},
+		"nonce":                 []string{nonce},
+		"code_challenge":        []string{oauth2.S256ChallengeFromVerifier(codeVerifier)},
+		"code_challenge_method": []string{"S256"},
 	}
 	redirectURL := o.config.GetAuthorizationUri() + "?" + query.Encode()
 
@@ -328,9 +333,10 @@ func (o *oidcHandler) retrieveTokens(ctx context.Context, log telemetry.Logger,
 
 	// build body
 	form := url.Values{
-		"grant_type":   []string{"authorization_code"},
-		"code":         []string{codeFromReq},
-		"redirect_uri": []string{o.config.GetCallbackUri()},
+		"grant_type":    []string{"authorization_code"},
+		"code":          []string{codeFromReq},
+		"redirect_uri":  []string{o.config.GetCallbackUri()},
+		"code_verifier": []string{stateFromStore.CodeVerifier},
 	}
 
 	// build headers
diff --git a/internal/oidc/redis.go b/internal/oidc/redis.go
index 6033631..1c3a98c 100644
--- a/internal/oidc/redis.go
+++ b/internal/oidc/redis.go
@@ -40,12 +40,13 @@ const (
 	keyState             = "state"
 	keyNonce             = "nonce"
 	keyRequestedURL      = "requested_url"
+	keyCodeVerifier      = "code_verifier"
 	keyTimeAdded         = "time_added"
 )
 
 var (
 	tokenResponseKeys      = []string{keyIDToken, keyAccessToken, keyRefreshToken, keyAccessTokenExpiry, keyTimeAdded}
-	authorizationStateKeys = []string{keyState, keyNonce, keyRequestedURL, keyTimeAdded}
+	authorizationStateKeys = []string{keyState, keyNonce, keyRequestedURL, keyTimeAdded, keyCodeVerifier}
 )
 
 // redisStore is an in-memory implementation of the SessionStore interface that stores
@@ -165,6 +166,7 @@ func (r *redisStore) SetAuthorizationState(ctx context.Context, sessionID string
 		keyState:        authorizationState.State,
 		keyNonce:        authorizationState.Nonce,
 		keyRequestedURL: authorizationState.RequestedURL,
+		keyCodeVerifier: authorizationState.CodeVerifier,
 	}
 
 	if err := r.client.HMSet(ctx, sessionID, state).Err(); err != nil {
@@ -193,7 +195,7 @@ func (r *redisStore) GetAuthorizationState(ctx context.Context, sessionID string
 		return nil, err
 	}
 
-	if state.State == "" || state.Nonce == "" || state.RequestedURL == "" {
+	if state.State == "" || state.Nonce == "" || state.RequestedURL == "" || state.CodeVerifier == "" {
 		return nil, nil
 	}
 
@@ -286,6 +288,7 @@ type (
 		State        string    `redis:"state"`
 		Nonce        string    `redis:"nonce"`
 		RequestedURL string    `redis:"requested_url"`
+		CodeVerifier string    `redis:"code_verifier"`
 		TimeAdded    time.Time `redis:"time_added"`
 	}
 )
@@ -304,5 +307,6 @@ func (r redisAuthState) AuthorizationState() *AuthorizationState {
 		State:        r.State,
 		Nonce:        r.Nonce,
 		RequestedURL: r.RequestedURL,
+		CodeVerifier: r.CodeVerifier,
 	}
 }
diff --git a/internal/oidc/session.go b/internal/oidc/session.go
index 0d70276..6c9be37 100644
--- a/internal/oidc/session.go
+++ b/internal/oidc/session.go
@@ -22,6 +22,7 @@ import (
 	"github.com/redis/go-redis/v9"
 	"github.com/tetratelabs/run"
 	"github.com/tetratelabs/telemetry"
+	"golang.org/x/oauth2"
 
 	configv1 "github.com/istio-ecosystem/authservice/config/gen/go/v1"
 	oidcv1 "github.com/istio-ecosystem/authservice/config/gen/go/v1/oidc"
@@ -136,6 +137,7 @@ type SessionGenerator interface {
 	GenerateSessionID() string
 	GenerateNonce() string
 	GenerateState() string
+	GenerateCodeVerifier() string
 }
 
 var (
@@ -151,9 +153,10 @@ type (
 
 	// staticGenerator is a session generator that uses static strings.
 	staticGenerator struct {
-		sessionID string
-		nonce     string
-		state     string
+		sessionID    string
+		nonce        string
+		state        string
+		codeVerifier string
 	}
 )
 
@@ -176,6 +179,10 @@ func (r randomGenerator) GenerateState() string {
 	return r.generate(32)
 }
 
+func (r randomGenerator) GenerateCodeVerifier() string {
+	return oauth2.GenerateVerifier()
+}
+
 func (r *randomGenerator) generate(n int) string {
 	const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
 	b := make([]byte, n)
@@ -186,11 +193,12 @@ func (r *randomGenerator) generate(n int) string {
 }
 
 // NewStaticGenerator creates a new static session generator.
-func NewStaticGenerator(sessionID, nonce, state string) SessionGenerator {
+func NewStaticGenerator(sessionID, nonce, state, codeVerifier string) SessionGenerator {
 	return &staticGenerator{
-		sessionID: sessionID,
-		nonce:     nonce,
-		state:     state,
+		sessionID:    sessionID,
+		nonce:        nonce,
+		state:        state,
+		codeVerifier: codeVerifier,
 	}
 }
 
@@ -205,3 +213,7 @@ func (s staticGenerator) GenerateNonce() string {
 func (s staticGenerator) GenerateState() string {
 	return s.state
 }
+
+func (s staticGenerator) GenerateCodeVerifier() string {
+	return s.codeVerifier
+}
diff --git a/internal/oidc/state.go b/internal/oidc/state.go
index 96236e7..02b2048 100644
--- a/internal/oidc/state.go
+++ b/internal/oidc/state.go
@@ -19,4 +19,5 @@ type AuthorizationState struct {
 	State        string
 	Nonce        string
 	RequestedURL string
+	CodeVerifier string
 }


Test patch:
diff --git a/e2e/istio/cluster/istiogw-config.yaml b/e2e/istio/cluster/istiogw-config.yaml
index 3a40c90..05d3ebb 100644
--- a/e2e/istio/cluster/istiogw-config.yaml
+++ b/e2e/istio/cluster/istiogw-config.yaml
@@ -1,4 +1,4 @@
-# Copyright 2023 Tetrate
+# Copyright 2024 Tetrate
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
diff --git a/e2e/keycloak/setup-keycloak.sh b/e2e/keycloak/setup-keycloak.sh
index 7fc46af..ee3d340 100755
--- a/e2e/keycloak/setup-keycloak.sh
+++ b/e2e/keycloak/setup-keycloak.sh
@@ -51,6 +51,7 @@ set -ex
     -s clientId="${CLIENT_ID}" \
     -s secret="${CLIENT_SECRET}" \
     -s "redirectUris=[\"${REDIRECT_URL}\"]" \
+    -s "attributes={\"pkce.code.challenge.method\":\"S256\"}" \
     -s consentRequired=false \
     --server "${KEYCLOAK_SERVER}" \
     --realm "${REALM}" \
diff --git a/e2e/redis/store_test.go b/e2e/redis/store_test.go
index f77db33..88917f7 100644
--- a/e2e/redis/store_test.go
+++ b/e2e/redis/store_test.go
@@ -85,6 +85,7 @@ func TestRedisAuthorizationState(t *testing.T) {
 		State:        "state",
 		Nonce:        "nonce",
 		RequestedURL: "https://example.com",
+		CodeVerifier: "code_verifier",
 	}
 	require.NoError(t, store.SetAuthorizationState(ctx, "s1", as))
 
@@ -126,6 +127,7 @@ func TestSessionExpiration(t *testing.T) {
 			State:        "state",
 			Nonce:        "nonce",
 			RequestedURL: "https://example.com",
+			CodeVerifier: "code_verifier",
 		}
 		require.NoError(t, store.SetAuthorizationState(ctx, "s1", as))
 		require.Eventually(t, func() bool {
diff --git a/internal/authz/oidc_test.go b/internal/authz/oidc_test.go
index c16e5d3..e3d21a7 100644
--- a/internal/authz/oidc_test.go
+++ b/internal/authz/oidc_test.go
@@ -34,6 +34,7 @@ import (
 	"github.com/lestrrat-go/jwx/v2/jwt"
 	"github.com/stretchr/testify/require"
 	"github.com/tetratelabs/telemetry"
+	"golang.org/x/oauth2"
 	"google.golang.org/grpc/codes"
 	"google.golang.org/grpc/test/bufconn"
 	"google.golang.org/protobuf/proto"
@@ -125,10 +126,11 @@ var (
 	yesterday = time.Now().Add(-24 * time.Hour)
 	tomorrow  = time.Now().Add(24 * time.Hour)
 
-	sessionID    = "test-session-id"
-	newSessionID = "new-session-id"
-	newNonce     = "new-nonce"
-	newState     = "new-state"
+	sessionID       = "test-session-id"
+	newSessionID    = "new-session-id"
+	newNonce        = "new-nonce"
+	newState        = "new-state"
+	newCodeVerifier = "new-code-verifier"
 
 	basicOIDCConfig = &oidcv1.OIDCConfig{
 		IdToken: &oidcv1.TokenConfig{
@@ -190,12 +192,14 @@ var (
 }`
 
 	wantRedirectParams = url.Values{
-		"response_type": {"code"},
-		"client_id":     {"test-client-id"},
-		"redirect_uri":  {"https://localhost:443/callback"},
-		"scope":         {"openid email"},
-		"state":         {newState},
-		"nonce":         {newNonce},
+		"response_type":         {"code"},
+		"client_id":             {"test-client-id"},
+		"redirect_uri":          {"https://localhost:443/callback"},
+		"scope":                 {"openid email"},
+		"state":                 {newState},
+		"nonce":                 {newNonce},
+		"code_challenge":        {oauth2.S256ChallengeFromVerifier(newCodeVerifier)},
+		"code_challenge_method": {"S256"},
 	}
 
 	wantRedirectBaseURI = "http://idp-test-server/auth"
@@ -228,7 +232,7 @@ func TestOIDCProcess(t *testing.T) {
 	tlsPool := internal.NewTLSConfigPool(context.Background())
 	h, err := NewOIDCHandler(basicOIDCConfig, tlsPool,
 		oidc.NewJWKSProvider(newConfigFor(basicOIDCConfig), tlsPool), sessions, clock,
-		oidc.NewStaticGenerator(newSessionID, newNonce, newState))
+		oidc.NewStaticGenerator(newSessionID, newNonce, newState, newCodeVerifier))
 	require.NoError(t, err)
 
 	ctx := context.Background()
@@ -949,7 +953,7 @@ func TestOIDCProcessWithFailingSessionStore(t *testing.T) {
 	}
 
 	h, err := NewOIDCHandler(basicOIDCConfig, tlsPool, oidc.NewJWKSProvider(newConfigFor(basicOIDCConfig), tlsPool),
-		sessions, oidc.Clock{}, oidc.NewStaticGenerator(newSessionID, newNonce, newState))
+		sessions, oidc.Clock{}, oidc.NewStaticGenerator(newSessionID, newNonce, newState, newCodeVerifier))
 	require.NoError(t, err)
 
 	ctx := context.Background()
@@ -1094,7 +1098,8 @@ func TestOIDCProcessWithFailingJWKSProvider(t *testing.T) {
 	sessions := &mockSessionStoreFactory{store: oidc.NewMemoryStore(&clock, time.Hour, time.Hour)}
 	store := sessions.Get(basicOIDCConfig)
 	tlsPool := internal.NewTLSConfigPool(context.Background())
-	h, err := NewOIDCHandler(basicOIDCConfig, tlsPool, funcJWKSProvider, sessions, clock, oidc.NewStaticGenerator(newSessionID, newNonce, newState))
+	h, err := NewOIDCHandler(basicOIDCConfig, tlsPool, funcJWKSProvider, sessions, clock,
+		oidc.NewStaticGenerator(newSessionID, newNonce, newState, newCodeVerifier))
 	require.NoError(t, err)
 
 	idpServer := newServer(wellKnownURIs)
@@ -1425,7 +1430,7 @@ func TestLoadWellKnownConfigError(t *testing.T) {
 	cfg.ConfigurationUri = "http://stopped-server/.well-known/openid-configuration"
 	sessions := &mockSessionStoreFactory{store: oidc.NewMemoryStore(&clock, time.Hour, time.Hour)}
 	_, err := NewOIDCHandler(cfg, tlsPool, oidc.NewJWKSProvider(newConfigFor(basicOIDCConfig), tlsPool),
-		sessions, clock, oidc.NewStaticGenerator(newSessionID, newNonce, newState))
+		sessions, clock, oidc.NewStaticGenerator(newSessionID, newNonce, newState, newCodeVerifier))
 	require.Error(t, err) // Fail to retrieve the dynamic config since the test server is not running
 }
 
@@ -1447,7 +1452,7 @@ func TestNewOIDCHandler(t *testing.T) {
 		t.Run(tt.name, func(t *testing.T) {
 
 			_, err := NewOIDCHandler(tt.config, tlsPool, oidc.NewJWKSProvider(newConfigFor(basicOIDCConfig), tlsPool),
-				sessions, clock, oidc.NewStaticGenerator(newSessionID, newNonce, newState))
+				sessions, clock, oidc.NewStaticGenerator(newSessionID, newNonce, newState, newCodeVerifier))
 			if tt.wantErr {
 				require.Error(t, err)
 			} else {
diff --git a/internal/config_test.go b/internal/config_test.go
index e43d817..15dd00a 100644
--- a/internal/config_test.go
+++ b/internal/config_test.go
@@ -47,7 +47,10 @@ func (e errCheck) Check(t *testing.T, err error) {
 	}
 }
 
-const msgLengthValidation = "value length must be at least 1 runes"
+const (
+	msgLengthValidation = "value length must be at least 1 runes"
+	msgInvalidClientID  = `invalid OIDCConfig.ClientId: value contains substring ":"`
+)
 
 func TestValidateConfig(t *testing.T) {
 	tests := []struct {
@@ -64,6 +67,7 @@ func TestValidateConfig(t *testing.T) {
 		{"multiple-oidc", "testdata/multiple-oidc.json", errCheck{is: ErrMultipleOIDCConfig}},
 		{"invalid-redis", "testdata/invalid-redis.json", errCheck{is: ErrInvalidURL}},
 		{"invalid-oidc-uris", "testdata/invalid-oidc-uris.json", errCheck{is: ErrRequiredURL}},
+		{"invalid-oidc-client-id", "testdata/invalid-oidc-client-id.json", errCheck{msg: msgInvalidClientID}},
 		{"invalid-health-port", "testdata/invalid-health-port.json", errCheck{is: ErrHealthPortInUse}},
 		{"invalid-callback-uri", "testdata/invalid-callback.json", errCheck{is: ErrMustNotBeRootPath}},
 		{"invalid-logout-path", "testdata/invalid-logout.json", errCheck{is: ErrMustNotBeRootPath}},
diff --git a/internal/oidc/redis_test.go b/internal/oidc/redis_test.go
index 89230c8..30a5f4f 100644
--- a/internal/oidc/redis_test.go
+++ b/internal/oidc/redis_test.go
@@ -91,6 +91,7 @@ func TestRedisAuthorizationState(t *testing.T) {
 		State:        "state",
 		Nonce:        "nonce",
 		RequestedURL: "requested_url",
+		CodeVerifier: "code_verifier",
 	}
 	require.NoError(t, store.SetAuthorizationState(ctx, "s1", as))
 
diff --git a/internal/oidc/session_test.go b/internal/oidc/session_test.go
index 35abc12..f5a0add 100644
--- a/internal/oidc/session_test.go
+++ b/internal/oidc/session_test.go
@@ -131,14 +131,17 @@ func TestSessionGenerator(t *testing.T) {
 		require.NotEqual(t, sg.GenerateSessionID(), sg.GenerateSessionID())
 		require.NotEqual(t, sg.GenerateState(), sg.GenerateState())
 		require.NotEqual(t, sg.GenerateNonce(), sg.GenerateNonce())
+		require.NotEqual(t, sg.GenerateCodeVerifier(), sg.GenerateCodeVerifier())
 	})
 	t.Run("static", func(t *testing.T) {
-		sg := NewStaticGenerator("sessionid", "nonce", "state")
+		sg := NewStaticGenerator("sessionid", "nonce", "state", "codeverifier")
 		require.Equal(t, sg.GenerateSessionID(), sg.GenerateSessionID())
 		require.Equal(t, sg.GenerateState(), sg.GenerateState())
 		require.Equal(t, sg.GenerateNonce(), sg.GenerateNonce())
+		require.Equal(t, sg.GenerateCodeVerifier(), sg.GenerateCodeVerifier())
 		require.Equal(t, "sessionid", sg.GenerateSessionID())
 		require.Equal(t, "state", sg.GenerateState())
 		require.Equal(t, "nonce", sg.GenerateNonce())
+		require.Equal(t, "codeverifier", sg.GenerateCodeVerifier())
 	})
 }
diff --git a/internal/testdata/invalid-oidc-client-id.json b/internal/testdata/invalid-oidc-client-id.json
new file mode 100644
index 0000000..b84fddb
--- /dev/null
+++ b/internal/testdata/invalid-oidc-client-id.json
@@ -0,0 +1,30 @@
+{
+  "listen_address": "0.0.0.0",
+  "listen_port": 8080,
+  "log_level": "debug",
+  "chains": [
+    {
+      "name": "oidc",
+      "filters": [
+        {
+          "oidc": {
+            "configuration_uri": "http://fake",
+            "callback_uri": "http://fake/callback",
+            "proxy_uri": "http://fake",
+            "jwks": "fake-jwks",
+            "client_id": "invalid:clientId",
+            "client_secret": "fake-client-secret",
+            "id_token": {
+              "preamble": "Bearer",
+              "header": "authorization"
+            },
+            "redis_session_store_config": {
+              "server_uri": "redis://localhost:6379/0"
+            },
+            "skip_verify_peer_cert": true
+          }
+        }
+      ]
+    }
+  ]
+}