diff --git a/pkg/validation/options.go b/pkg/validation/options.go index e541e159..f5e5e4a8 100644 --- a/pkg/validation/options.go +++ b/pkg/validation/options.go @@ -268,6 +268,19 @@ func parseProviderInfo(o *options.Options, msgs []string) []string { if len(o.KeycloakGroups) > 0 { p.SetAllowedGroups(o.KeycloakGroups) } + case *providers.KeycloakOIDCProvider: + if p.Verifier == nil { + msgs = append(msgs, "keycloak-oidc provider requires an oidc issuer URL") + } + + // Backwards compatibility with `--keycloak-group` option + if len(o.KeycloakGroups) > 0 { + // Maybe already added with proper `--allowed-group` flag + if !strings.Contains(o.Scope, " groups") { + o.Scope += " groups" + } + p.SetAllowedGroups(o.KeycloakGroups) + } case *providers.GoogleProvider: if o.GoogleServiceAccountJSON != "" { file, err := os.Open(o.GoogleServiceAccountJSON) @@ -286,10 +299,6 @@ func parseProviderInfo(o *options.Options, msgs []string) []string { case *providers.BitbucketProvider: p.SetTeam(o.BitbucketTeam) p.SetRepository(o.BitbucketRepository) - case *providers.OIDCProvider: - if p.Verifier == nil { - msgs = append(msgs, "oidc provider requires an oidc issuer URL") - } case *providers.GitLabProvider: p.Groups = o.GitLabGroup err := p.AddProjects(o.GitlabProjects) @@ -345,6 +354,10 @@ func parseProviderInfo(o *options.Options, msgs []string) []string { p.JWTKey = signKey } } + case *providers.OIDCProvider: + if p.Verifier == nil { + msgs = append(msgs, "oidc provider requires an oidc issuer URL") + } } return msgs } 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 d4f05e2c..146a13fc 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 "gitlab":