diff --git a/pkg/validation/options.go b/pkg/validation/options.go index 1962185d..6d53ab43 100644 --- a/pkg/validation/options.go +++ b/pkg/validation/options.go @@ -247,6 +247,10 @@ func parseProviderInfo(o *options.Options, msgs []string) []string { if len(o.Providers[0].KeycloakConfig.Groups) > 0 { p.SetAllowedGroups(o.Providers[0].KeycloakConfig.Groups) } + case *providers.KeycloakOIDCProvider: + if p.Verifier == nil { + msgs = append(msgs, "keycloak-oidc provider requires an oidc issuer URL") + } case *providers.GoogleProvider: if o.Providers[0].GoogleConfig.ServiceAccountJSON != "" { file, err := os.Open(o.Providers[0].GoogleConfig.ServiceAccountJSON) diff --git a/providers/keycloak_oidc.go b/providers/keycloak_oidc.go new file mode 100644 index 00000000..553438b7 --- /dev/null +++ b/providers/keycloak_oidc.go @@ -0,0 +1,41 @@ +package providers + +import ( + "context" + + "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/sessions" +) + +const keycloakOIDCProviderName = "Keycloak OIDC" + +// KeycloakOIDCProvider creates a Keycloak provider based on OIDCProvider +type KeycloakOIDCProvider struct { + *OIDCProvider +} + +// NewKeycloakOIDCProvider makes a KeycloakOIDCProvider using the ProviderData +func NewKeycloakOIDCProvider(p *ProviderData) *KeycloakOIDCProvider { + p.ProviderName = keycloakOIDCProviderName + return &KeycloakOIDCProvider{ + OIDCProvider: &OIDCProvider{ + ProviderData: p, + }, + } +} + +var _ Provider = (*KeycloakOIDCProvider)(nil) + +// EnrichSession is called after Redeem to allow providers to enrich session fields +// such as User, Email, Groups with provider specific API calls. +func (p *KeycloakOIDCProvider) EnrichSession(ctx context.Context, s *sessions.SessionState) error { + err := p.OIDCProvider.EnrichSession(ctx, s) + if err != nil { + return err + } + return p.extractRoles(ctx, s) +} + +func (p *KeycloakOIDCProvider) extractRoles(ctx context.Context, s *sessions.SessionState) error { + // TODO: Implement me with Access Token Role claim extraction logic + return ErrNotImplemented +} diff --git a/providers/keycloak_oidc_test.go b/providers/keycloak_oidc_test.go new file mode 100644 index 00000000..8e9ef07f --- /dev/null +++ b/providers/keycloak_oidc_test.go @@ -0,0 +1,42 @@ +package providers + +import ( + "net/url" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" +) + +var _ = Describe("Keycloak OIDC Provider Tests", func() { + Context("New Provider Init", func() { + It("uses the passed ProviderData", func() { + p := NewKeycloakOIDCProvider( + &ProviderData{ + LoginURL: &url.URL{ + Scheme: "https", + Host: "keycloak-oidc.com", + Path: "/oauth/auth"}, + RedeemURL: &url.URL{ + Scheme: "https", + Host: "keycloak-oidc.com", + Path: "/oauth/token"}, + ProfileURL: &url.URL{ + Scheme: "https", + Host: "keycloak-oidc.com", + Path: "/api/v3/user"}, + ValidateURL: &url.URL{ + Scheme: "https", + Host: "keycloak-oidc.com", + Path: "/api/v3/user"}, + Scope: "openid email profile"}) + providerData := p.Data() + + Expect(providerData.ProviderName).To(Equal(keycloakOIDCProviderName)) + Expect(providerData.LoginURL.String()).To(Equal("https://keycloak-oidc.com/oauth/auth")) + Expect(providerData.RedeemURL.String()).To(Equal("https://keycloak-oidc.com/oauth/token")) + Expect(providerData.ProfileURL.String()).To(Equal("https://keycloak-oidc.com/api/v3/user")) + Expect(providerData.ValidateURL.String()).To(Equal("https://keycloak-oidc.com/api/v3/user")) + Expect(providerData.Scope).To(Equal("openid email profile")) + }) + }) +}) diff --git a/providers/providers.go b/providers/providers.go index d21409c2..a192f220 100644 --- a/providers/providers.go +++ b/providers/providers.go @@ -31,6 +31,8 @@ func New(provider string, p *ProviderData) Provider { return NewGitHubProvider(p) case "keycloak": return NewKeycloakProvider(p) + case "keycloak-oidc": + return NewKeycloakOIDCProvider(p) case "azure": return NewAzureProvider(p) case "adfs":