mirror of
https://github.com/lukaszraczylo/traefikoidc.git
synced 2026-10-20 04:57:02 +00:00
R83: DCR require client_secret for confidential auth, validate redirect_uri scheme; reject callback query/fragment
This commit is contained in:
@@ -0,0 +1,97 @@
|
||||
package traefikoidc
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// TestDCR_MissingClientSecretRejected is a regression: a registration
|
||||
// response carrying client_id but no client_secret was accepted and adopted,
|
||||
// although the plugin's client-auth default is client_secret_post (RFC 7591
|
||||
// confidential client) — every subsequent token exchange would fail. The fix
|
||||
// rejects a secret-less response for secret-based auth methods.
|
||||
func TestDCR_MissingClientSecretRejected(t *testing.T) {
|
||||
server := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.WriteHeader(http.StatusCreated)
|
||||
_ = json.NewEncoder(w).Encode(ClientRegistrationResponse{ClientID: "client-123"})
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
registrar := NewDynamicClientRegistrar(
|
||||
server.Client(),
|
||||
NewLogger("DEBUG"),
|
||||
&DynamicClientRegistrationConfig{
|
||||
Enabled: true,
|
||||
ClientMetadata: &ClientRegistrationMetadata{
|
||||
RedirectURIs: []string{"https://example.com/callback"},
|
||||
},
|
||||
},
|
||||
server.URL,
|
||||
)
|
||||
|
||||
_, err := registrar.RegisterClient(context.Background(), server.URL+"/register")
|
||||
if err == nil {
|
||||
t.Fatalf("expected registration to fail when the response lacks a client_secret for client_secret_post")
|
||||
}
|
||||
}
|
||||
|
||||
// TestConfig_RejectsCallbackQueryOrFragment is a regression: a callbackURL
|
||||
// containing a query string or fragment passed config validation but can
|
||||
// never match the request path (req.URL.Path == redirURLPath) and breaks
|
||||
// redirect_uri, causing an endless re-auth loop. The fix rejects it.
|
||||
func TestConfig_RejectsCallbackQueryOrFragment(t *testing.T) {
|
||||
tests := []string{
|
||||
"/callback?from=idp",
|
||||
"/callback#frag",
|
||||
}
|
||||
for _, cb := range tests {
|
||||
cfg := &Config{
|
||||
ProviderURL: "https://issuer.example.com",
|
||||
CallbackURL: cb,
|
||||
ClientID: "client-id",
|
||||
ClientSecret: "client-secret",
|
||||
SessionEncryptionKey: "0123456789abcdef0123456789abcdef",
|
||||
ClientAuthMethod: "client_secret_post",
|
||||
RateLimit: 100,
|
||||
}
|
||||
if err := cfg.Validate(); err == nil {
|
||||
t.Errorf("expected Validate to reject callbackURL %q with query/fragment", cb)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TestDCR_InvalidRedirectURIScheme is a regression: redirect_uris entries
|
||||
// were sent to the IdP without validating scheme/host, so a malformed or
|
||||
// wrong-scheme URI reached the provider and corrupted the registered
|
||||
// callback. The fix rejects non-absolute http(s) entries before the POST.
|
||||
func TestDCR_InvalidRedirectURIScheme(t *testing.T) {
|
||||
server := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.WriteHeader(http.StatusCreated)
|
||||
_ = json.NewEncoder(w).Encode(ClientRegistrationResponse{
|
||||
ClientID: "client-123",
|
||||
ClientSecret: "secret-456",
|
||||
})
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
registrar := NewDynamicClientRegistrar(
|
||||
server.Client(),
|
||||
NewLogger("DEBUG"),
|
||||
&DynamicClientRegistrationConfig{
|
||||
Enabled: true,
|
||||
ClientMetadata: &ClientRegistrationMetadata{
|
||||
RedirectURIs: []string{"ftp://example.com/not-a-web-callback"},
|
||||
},
|
||||
},
|
||||
server.URL,
|
||||
)
|
||||
|
||||
if _, err := registrar.RegisterClient(context.Background(), server.URL+"/register"); err == nil {
|
||||
t.Fatalf("expected registration to reject a non-http(s) redirect_uri")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user