diff --git a/examples/README.md b/examples/README.md index e2c2963a..de618ced 100644 --- a/examples/README.md +++ b/examples/README.md @@ -346,7 +346,7 @@ In the case of running zot with openid enabled behind a proxy/load balancer http "http": { "address": "0.0.0.0", "port": "8080", - "externalUrl: "https://zot.example.com", + "externalUrl": "https://zot.example.com", "auth": { "openid": { "providers": { @@ -362,6 +362,40 @@ In the case of running zot with openid enabled behind a proxy/load balancer http ``` This config value will be used by oauth2/openid clients to redirect back to zot. +### OpenID/OAuth2 Social Login with Custom URLs (Self-Hosted Providers) + +#### Use Cases +- GitHub Enterprise Server (on-premises GitHub) +- GitLab Self-Managed instances +- Custom corporate OAuth2/OIDC providers + +When integrating zot with self-hosted OAuth2 providers like GitHub Enterprise Server, GitLab Self-Managed, +or custom OIDC implementations, you must specify custom authentication and token endpoints since +the default public endpoints won't work. + +``` + "http": { + "address": "0.0.0.0", + "port": "8080", + "externalUrl": "https://zot.example.com", + "auth": { + "openid": { + "providers": { + "github": { + "clientid": , + "clientsecret": , + "authurl": "https://github.company.com/login/oauth/authorize", // Custom GHE authorization endpoint + "tokenurl": "https://github.company.com/login/oauth/access_token", // Custom GHE token endpoint + "scopes": ["read:org", "user", "repo"] + } + } + } + } + } +``` + +Without `authurl`/`tokenurl`, zot assumes public GitHub.com endpoints. + ### Session based login Whenever a user logs in zot using any of the auth options available(basic auth/openid) zot will set a 'session' cookie on its response. diff --git a/pkg/api/authn.go b/pkg/api/authn.go index bf47b011..a9976698 100644 --- a/pkg/api/authn.go +++ b/pkg/api/authn.go @@ -615,12 +615,24 @@ func NewRelyingPartyGithub(config *config.Config, provider string, hashKey, encr _, clientID, clientSecret, redirectURI, scopes, options := getRelyingPartyArgs(config, provider, hashKey, encryptKey, log) + var endpoint oauth2.Endpoint + + // Use custom endpoints if provided, otherwise fallback to GitHub's endpoints + if provider := config.HTTP.Auth.OpenID.Providers[provider]; provider.AuthURL != "" && provider.TokenURL != "" { + endpoint = oauth2.Endpoint{ + AuthURL: provider.AuthURL, + TokenURL: provider.TokenURL, + } + } else { + endpoint = githubOAuth.Endpoint + } + rpConfig := &oauth2.Config{ ClientID: clientID, ClientSecret: clientSecret, RedirectURL: redirectURI, Scopes: scopes, - Endpoint: githubOAuth.Endpoint, + Endpoint: endpoint, } relyingParty, err := rp.NewRelyingPartyOAuth(rpConfig, options...) diff --git a/pkg/api/config/config.go b/pkg/api/config/config.go index e7cea046..3a12ac93 100644 --- a/pkg/api/config/config.go +++ b/pkg/api/config/config.go @@ -167,6 +167,8 @@ type OpenIDProviderConfig struct { ClientSecret string KeyPath string Issuer string + AuthURL string + TokenURL string Scopes []string } @@ -606,6 +608,8 @@ func (c *Config) Sanitize() *Config { ClientSecret: "******", KeyPath: config.KeyPath, Issuer: config.Issuer, + AuthURL: config.AuthURL, + TokenURL: config.TokenURL, Scopes: config.Scopes, } } diff --git a/pkg/api/config/config_test.go b/pkg/api/config/config_test.go index 41d375da..2712935f 100644 --- a/pkg/api/config/config_test.go +++ b/pkg/api/config/config_test.go @@ -119,6 +119,8 @@ func TestConfig(t *testing.T) { Name: "GitHub", ClientID: "github-client-id", ClientSecret: "github-client-secret", + AuthURL: "github-auth-url", + TokenURL: "github-token-url", Scopes: []string{"user:email"}, }, }, @@ -143,6 +145,8 @@ func TestConfig(t *testing.T) { // Verify original config is not modified So(conf.HTTP.Auth.OpenID.Providers["google"].ClientSecret, ShouldEqual, "google-client-secret") So(conf.HTTP.Auth.OpenID.Providers["github"].ClientSecret, ShouldEqual, "github-client-secret") + So(conf.HTTP.Auth.OpenID.Providers["github"].AuthURL, ShouldEqual, "github-auth-url") + So(conf.HTTP.Auth.OpenID.Providers["github"].TokenURL, ShouldEqual, "github-token-url") }) Convey("Test Sanitize() with Event sink credentials", func() {