Files
coder/coderd/oauth2provider/pkce_test.go
T
Ehab Younes 6683d807ac refactor: add RFC-compliant enum types and use SDK as source of truth (#21468)
Add comprehensive OAuth2 enum types to codersdk following RFC specifications:
- OAuth2ProviderGrantType (RFC 6749)
- OAuth2ProviderResponseType (RFC 6749)
- OAuth2TokenEndpointAuthMethod (RFC 7591)
- OAuth2PKCECodeChallengeMethod (RFC 7636)
- OAuth2TokenType (RFC 6749, RFC 9449)
- OAuth2RevocationTokenTypeHint (RFC 7009)
- OAuth2ErrorCode (RFC 6749, RFC 7009, RFC 8707)

Add OAuth2TokenRequest, OAuth2TokenResponse, OAuth2TokenRevocationRequest,
and OAuth2Error structs to the SDK. Update OAuth2ClientRegistrationRequest,
OAuth2ClientRegistrationResponse, OAuth2ClientConfiguration, and
OAuth2AuthorizationServerMetadata to use typed enums instead of raw strings.

This makes codersdk the single source of truth for OAuth2 types, eliminating
duplication between SDK and server-side structs.

Closes #21476
2026-01-15 12:41:28 +03:00

128 lines
2.8 KiB
Go

package oauth2provider_test
import (
"crypto/sha256"
"encoding/base64"
"testing"
"github.com/stretchr/testify/require"
"github.com/coder/coder/v2/coderd/oauth2provider"
"github.com/coder/coder/v2/codersdk"
)
func TestVerifyPKCE(t *testing.T) {
t.Parallel()
tests := []struct {
name string
verifier string
challenge string
expectValid bool
}{
{
name: "ValidPKCE",
verifier: "dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk",
challenge: "E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM",
expectValid: true,
},
{
name: "InvalidPKCE",
verifier: "dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk",
challenge: "wrong_challenge",
expectValid: false,
},
{
name: "EmptyChallenge",
verifier: "dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk",
challenge: "",
expectValid: false,
},
{
name: "EmptyVerifier",
verifier: "",
challenge: "E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM",
expectValid: false,
},
{
name: "BothEmpty",
verifier: "",
challenge: "",
expectValid: false,
},
}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
result := oauth2provider.VerifyPKCE(tt.challenge, tt.verifier)
require.Equal(t, tt.expectValid, result)
})
}
}
func TestPKCES256Generation(t *testing.T) {
t.Parallel()
// Test that we can generate a valid S256 challenge from a verifier
verifier := "dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk"
expectedChallenge := "E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM"
// Generate challenge using S256 method
h := sha256.Sum256([]byte(verifier))
challenge := base64.RawURLEncoding.EncodeToString(h[:])
require.Equal(t, expectedChallenge, challenge)
require.True(t, oauth2provider.VerifyPKCE(challenge, verifier))
}
func TestValidatePKCECodeChallengeMethod(t *testing.T) {
t.Parallel()
tests := []struct {
name string
method string
expectError bool
errorContains string
}{
{
name: "EmptyIsValid",
method: "",
expectError: false,
},
{
name: "S256IsValid",
method: string(codersdk.OAuth2PKCECodeChallengeMethodS256),
expectError: false,
},
{
name: "PlainIsRejected",
method: string(codersdk.OAuth2PKCECodeChallengeMethodPlain),
expectError: true,
errorContains: "plain",
},
{
name: "UnknownIsRejected",
method: "unknown_method",
expectError: true,
errorContains: "unsupported",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
err := codersdk.ValidatePKCECodeChallengeMethod(tt.method)
if tt.expectError {
require.Error(t, err)
if tt.errorContains != "" {
require.Contains(t, err.Error(), tt.errorContains)
}
} else {
require.NoError(t, err)
}
})
}
}