feat(connector): add compile-time checks for connector interfaces (#4591)

Signed-off-by: maksim.nabokikh <max.nabokih@gmail.com>
This commit is contained in:
Maksim Nabokikh
2026-02-26 16:43:17 +01:00
committed by GitHub
parent 44e27490be
commit 47e84dba69
9 changed files with 40 additions and 31 deletions
+5 -5
View File
@@ -87,16 +87,16 @@ func (c *Config) Open(id string, logger *slog.Logger) (connector.Connector, erro
return &crowdConnector{Config: *c, logger: logger.With(slog.Group("connector", "type", "atlassiancrowd", "id", id))}, nil
}
type crowdConnector struct {
Config
logger *slog.Logger
}
var (
_ connector.PasswordConnector = (*crowdConnector)(nil)
_ connector.RefreshConnector = (*crowdConnector)(nil)
)
type crowdConnector struct {
Config
logger *slog.Logger
}
type refreshData struct {
Username string `json:"username"`
}
+2
View File
@@ -68,6 +68,8 @@ func (c *Config) Open(id string, logger *slog.Logger) (connector.Connector, erro
}, nil
}
var _ connector.CallbackConnector = (*callback)(nil)
// Callback is a connector which returns an identity with the HTTP header
// X-Remote-User as verified email.
type callback struct {
+5 -5
View File
@@ -15,6 +15,11 @@ import (
"github.com/dexidp/dex/connector"
)
var (
_ connector.PasswordConnector = (*conn)(nil)
_ connector.RefreshConnector = (*conn)(nil)
)
type conn struct {
Domain domainKeystone
Host string
@@ -103,11 +108,6 @@ type userResponse struct {
} `json:"user"`
}
var (
_ connector.PasswordConnector = &conn{}
_ connector.RefreshConnector = &conn{}
)
// Open returns an authentication strategy using Keystone.
func (c *Config) Open(id string, logger *slog.Logger) (connector.Connector, error) {
_, err := uuid.Parse(c.Domain)
+5 -5
View File
@@ -301,6 +301,11 @@ func (c *Config) openConnector(logger *slog.Logger) (*ldapConnector, error) {
return &ldapConnector{*c, userSearchScope, groupSearchScope, tlsConfig, logger}, nil
}
var (
_ connector.PasswordConnector = (*ldapConnector)(nil)
_ connector.RefreshConnector = (*ldapConnector)(nil)
)
type ldapConnector struct {
Config
@@ -312,11 +317,6 @@ type ldapConnector struct {
logger *slog.Logger
}
var (
_ connector.PasswordConnector = (*ldapConnector)(nil)
_ connector.RefreshConnector = (*ldapConnector)(nil)
)
// do initializes a connection to the LDAP directory and passes it to the
// provided function. It then performs appropriate teardown or reuse before
// returning.
+5 -7
View File
@@ -49,18 +49,16 @@ type connectorData struct {
AccessToken string `json:"accessToken"`
}
type linkedInConnector struct {
oauth2Config *oauth2.Config
logger *slog.Logger
}
// LinkedIn doesn't provide refresh tokens, so refresh tokens issued by Dex
// will expire in 60 days (default LinkedIn token lifetime).
var (
_ connector.CallbackConnector = (*linkedInConnector)(nil)
_ connector.RefreshConnector = (*linkedInConnector)(nil)
)
type linkedInConnector struct {
oauth2Config *oauth2.Config
logger *slog.Logger
}
// LoginURL returns an access token request URL
func (c *linkedInConnector) LoginURL(scopes connector.Scopes, callbackURL, state string) (string, []byte, error) {
if c.oauth2Config.RedirectURL != callbackURL {
+8 -4
View File
@@ -29,10 +29,9 @@ func NewCallbackConnector(logger *slog.Logger) connector.Connector {
}
var (
_ connector.CallbackConnector = &Callback{}
_ connector.PasswordConnector = passwordConnector{}
_ connector.RefreshConnector = passwordConnector{}
_ connector.CallbackConnector = &Callback{}
_ connector.RefreshConnector = &Callback{}
_ connector.TokenIdentityConnector = &Callback{}
)
// Callback is a connector that requires no user interaction and always returns the same identity.
@@ -97,6 +96,11 @@ func (c *PasswordConfig) Open(id string, logger *slog.Logger) (connector.Connect
return &passwordConnector{c.Username, c.Password, logger}, nil
}
var (
_ connector.PasswordConnector = passwordConnector{}
_ connector.RefreshConnector = passwordConnector{}
)
type passwordConnector struct {
username string
password string
+2
View File
@@ -16,6 +16,8 @@ import (
"github.com/dexidp/dex/pkg/httpclient"
)
var _ connector.CallbackConnector = (*oauthConnector)(nil)
type oauthConnector struct {
clientID string
clientSecret string
+3 -2
View File
@@ -379,8 +379,9 @@ func (c *Config) Open(id string, logger *slog.Logger) (conn connector.Connector,
}
var (
_ connector.CallbackConnector = (*oidcConnector)(nil)
_ connector.RefreshConnector = (*oidcConnector)(nil)
_ connector.CallbackConnector = (*oidcConnector)(nil)
_ connector.RefreshConnector = (*oidcConnector)(nil)
_ connector.TokenIdentityConnector = (*oidcConnector)(nil)
)
type oidcConnector struct {
+5 -3
View File
@@ -232,6 +232,11 @@ func (c *Config) openConnector(logger *slog.Logger) (*provider, error) {
return p, nil
}
var (
_ connector.SAMLConnector = (*provider)(nil)
_ connector.RefreshConnector = (*provider)(nil)
)
type provider struct {
entityIssuer string
ssoIssuer string
@@ -257,9 +262,6 @@ type provider struct {
logger *slog.Logger
}
// Compile-time check that provider implements RefreshConnector
var _ connector.RefreshConnector = (*provider)(nil)
// cachedIdentity stores the identity from SAML assertion for refresh token support.
// Since SAML has no native refresh mechanism, we cache the identity obtained during
// the initial authentication and return it on subsequent refresh requests.