@@ -2,17 +2,12 @@ package providers
22
33import (
44 "context"
5− "errors"
65 "fmt"
76 "net/url"
8− "strings"
97
10− "github.com/coreos/go-oidc/v3/oidc"
118 "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/options"
129 "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/sessions"
13− "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/logger"
1410 internaloidc "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/providers/oidc"
15− "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/requests"
1611 k8serrors "k8s.io/apimachinery/pkg/util/errors"
1712)
1813
@@ -86,16 +81,27 @@ func newProviderDataFromConfig(providerConfig options.Provider) (*ProviderData,
8681 }
8782
8883 if needsVerifier {
89− oidcProvider, verifier, err := newOIDCProviderVerifier(providerConfig)
84+ pv, err := internaloidc.NewProviderVerifier(context.TODO(), internaloidc.ProviderVerifierOptions{
85+ AudienceClaims: providerConfig.OIDCConfig.AudienceClaims,
86+ ClientID: providerConfig.ClientID,
87+ ExtraAudiences: providerConfig.OIDCConfig.ExtraAudiences,
88+ IssuerURL: providerConfig.OIDCConfig.IssuerURL,
89+ JWKsURL: providerConfig.OIDCConfig.JwksURL,
90+ SkipDiscovery: providerConfig.OIDCConfig.SkipDiscovery,
91+ SkipIssuerVerification: providerConfig.OIDCConfig.InsecureSkipIssuerVerification,
92+ })
9093 if err != nil {
91− return nil, fmt.Errorf("error setting OIDC configuration: %v", err)
94+ return nil, fmt.Errorf("error building OIDC ProviderVerifier: %v", err)
9295 }
9396
94− p.Verifier = verifier
95− if oidcProvider != nil {
97+ p.Verifier = pv.Verifier()
98+ if pv.DiscoveryEnabled() {
9699 // Use the discovered values rather than any specified values
97− providerConfig.LoginURL = oidcProvider.Endpoint().AuthURL
98− providerConfig.RedeemURL = oidcProvider.Endpoint().TokenURL
100+ endpoints := pv.Provider().Endpoints()
101+ providerConfig.LoginURL = endpoints.AuthURL
102+ providerConfig.RedeemURL = endpoints.TokenURL
103+ providerConfig.ProfileURL = endpoints.UserInfoURL
104+ providerConfig.OIDCConfig.JwksURL = endpoints.JWKsURL
99105 }
100106 }
101107
@@ -159,118 +165,3 @@ func providerRequiresOIDCProviderVerifier(providerType options.ProviderType) (bo
159165 return false, fmt.Errorf("unknown provider type: %s", providerType)
160166 }
161167}
162−
163−func newOIDCProviderVerifier(providerConfig options.Provider) (*oidc.Provider, internaloidc.IDTokenVerifier, error) {
164− // If the issuer isn't set, default it for platforms where it makes sense
165− if providerConfig.OIDCConfig.IssuerURL == "" {
166− switch providerConfig.Type {
167− case "gitlab":
168− providerConfig.OIDCConfig.IssuerURL = "https://gitlab.com"
169− case "oidc":
170− return nil, nil, errors.New("missing required setting: OIDC Issuer URL cannot be empty")
171− }
172− }
173−
174− switch {
175− case providerConfig.OIDCConfig.InsecureSkipIssuerVerification && !providerConfig.OIDCConfig.SkipDiscovery:
176− verifier, err := newInsecureSkipIssuerVerificationOIDCVerifier(providerConfig)
177− return nil, verifier, err
178− case providerConfig.OIDCConfig.SkipDiscovery:
179− verifier, err := newSkipDiscoveryOIDCVerifier(providerConfig)
180− return nil, verifier, err
181− default:
182− return newDiscoveryOIDCProviderVerifier(providerConfig)
183− }
184−}
185−
186−func newDiscoveryOIDCProviderVerifier(providerConfig options.Provider) (*oidc.Provider, internaloidc.IDTokenVerifier, error) {
187− // Configure discoverable provider data.
188− provider, err := oidc.NewProvider(context.TODO(), providerConfig.OIDCConfig.IssuerURL)
189− if err != nil {
190− return nil, nil, err
191− }
192− verificationOptions := internaloidc.IDTokenVerificationOptions{
193− AudienceClaims: providerConfig.OIDCConfig.AudienceClaims,
194− ClientID: providerConfig.ClientID,
195− ExtraAudiences: providerConfig.OIDCConfig.ExtraAudiences,
196− }
197− verifier := internaloidc.NewVerifier(provider.Verifier(&oidc.Config{
198− ClientID: providerConfig.ClientID,
199− SkipIssuerCheck: providerConfig.OIDCConfig.InsecureSkipIssuerVerification,
200− SkipClientIDCheck: true, // client id check is done within oauth2-proxy: IDTokenVerifier.Verify
201− }), verificationOptions)
202−
203− return provider, verifier, nil
204−}
205−
206−func newInsecureSkipIssuerVerificationOIDCVerifier(providerConfig options.Provider) (internaloidc.IDTokenVerifier, error) {
207− // go-oidc doesn't let us pass bypass the issuer check this in the oidc.NewProvider call
208− // (which uses discovery to get the URLs), so we'll do a quick check ourselves and if
209− // we get the URLs, we'll just use the non-discovery path.
210−
211− logger.Printf("Performing OIDC Discovery...")
212−
213− requestURL := strings.TrimSuffix(providerConfig.OIDCConfig.IssuerURL, "/") + "/.well-known/openid-configuration"
214− body, err := requests.New(requestURL).
215− Do().
216− UnmarshalJSON()
217− if err != nil {
218− return nil, fmt.Errorf("failed to discover OIDC configuration: %v", err)
219− }
220−
221− // Prefer manually configured URLs. It's a bit unclear
222− // why you'd be doing discovery and also providing the URLs
223− // explicitly though...
224− if providerConfig.LoginURL == "" {
225− providerConfig.LoginURL = body.Get("authorization_endpoint").MustString()
226− }
227−
228− if providerConfig.RedeemURL == "" {
229− providerConfig.RedeemURL = body.Get("token_endpoint").MustString()
230− }
231−
232− if providerConfig.OIDCConfig.JwksURL == "" {
233− providerConfig.OIDCConfig.JwksURL = body.Get("jwks_uri").MustString()
234− }
235−
236− if providerConfig.ProfileURL == "" {
237− providerConfig.ProfileURL = body.Get("userinfo_endpoint").MustString()
238− }
239−
240− // Now we have performed the discovery, construct the verifier manually
241− return newSkipDiscoveryOIDCVerifier(providerConfig)
242−}
243−
244−func newSkipDiscoveryOIDCVerifier(providerConfig options.Provider) (internaloidc.IDTokenVerifier, error) {
245− var errs []error
246−
247− // Construct a manual IDTokenVerifier from issuer URL & JWKS URI
248− // instead of metadata discovery if we enable -skip-oidc-discovery.
249− // In this case we need to make sure the required endpoints for
250− // the provider are configured.
251− if providerConfig.LoginURL == "" {
252− errs = append(errs, errors.New("missing required setting: login-url"))
253− }
254− if providerConfig.RedeemURL == "" {
255− errs = append(errs, errors.New("missing required setting: redeem-url"))
256− }
257− if providerConfig.OIDCConfig.JwksURL == "" {
258− errs = append(errs, errors.New("missing required setting: oidc-jwks-url"))
259− }
260− if len(errs) > 0 {
261− return nil, k8serrors.NewAggregate(errs)
262− }
263−
264− keySet := oidc.NewRemoteKeySet(context.TODO(), providerConfig.OIDCConfig.JwksURL)
265− verificationOptions := internaloidc.IDTokenVerificationOptions{
266− AudienceClaims: providerConfig.OIDCConfig.AudienceClaims,
267− ClientID: providerConfig.ClientID,
268− ExtraAudiences: providerConfig.OIDCConfig.ExtraAudiences,
269− }
270− verifier := internaloidc.NewVerifier(oidc.NewVerifier(providerConfig.OIDCConfig.IssuerURL, keySet, &oidc.Config{
271− ClientID: providerConfig.ClientID,
272− SkipIssuerCheck: providerConfig.OIDCConfig.InsecureSkipIssuerVerification,
273− SkipClientIDCheck: true, // client id check is done within oauth2-proxy: IDTokenVerifier.Verify
274− }), verificationOptions)
275− return verifier, nil
276−}