@@ -1417,7 +1417,7 @@ func (t *Translator) buildOIDCProvider(policy *egv1a1.SecurityPolicy, resources
14171417 if provider .TokenEndpoint == nil || provider .AuthorizationEndpoint == nil {
14181418 discoveredConfig , err := fetchEndpointsFromIssuer (provider .Issuer , providerTLS )
14191419 if err != nil {
1420- return nil , fmt . Errorf ( "error fetching endpoints from issuer: %w" , err )
1420+ return nil , err
14211421 }
14221422 tokenEndpoint = discoveredConfig .TokenEndpoint
14231423 authorizationEndpoint = discoveredConfig .AuthorizationEndpoint
@@ -1493,6 +1493,16 @@ type OpenIDConfig struct {
14931493 EndSessionEndpoint * string `json:"end_session_endpoint,omitempty"`
14941494}
14951495
1496+ func (o * OpenIDConfig ) validate () error {
1497+ if o .TokenEndpoint == "" {
1498+ return errors .New ("token_endpoint not found in OpenID configuration" )
1499+ }
1500+ if o .AuthorizationEndpoint == "" {
1501+ return errors .New ("authorization_endpoint not found in OpenID configuration" )
1502+ }
1503+ return nil
1504+ }
1505+
14961506func fetchEndpointsFromIssuer (issuerURL string , providerTLS * ir.TLSUpstreamConfig ) (* OpenIDConfig , error ) {
14971507 var (
14981508 tlsConfig * tls.Config
@@ -1516,21 +1526,47 @@ func fetchEndpointsFromIssuer(issuerURL string, providerTLS *ir.TLSUpstreamConfi
15161526 var config OpenIDConfig
15171527 if err = backoff .Retry (func () error {
15181528 resp , err := client .Get (fmt .Sprintf ("%s/.well-known/openid-configuration" , issuerURL ))
1529+ // Retry on transport errors
15191530 if err != nil {
15201531 return err
15211532 }
1533+
15221534 defer resp .Body .Close ()
1523- if err = json .NewDecoder (resp .Body ).Decode (& config ); err != nil {
1524- return err
1535+ switch {
1536+ // Retry on transient errors
1537+ case retryable (resp .StatusCode ):
1538+ return fmt .Errorf ("transient error fetching openid-configuration from issuer URL: %s, status code: %d" , issuerURL , resp .StatusCode )
1539+ // Do not retry on client errors
1540+ case resp .StatusCode == http .StatusNotFound || resp .StatusCode == http .StatusBadRequest :
1541+ return & backoff.PermanentError {Err : fmt .Errorf ("failed fetching openid-configuration from issuer URL: %s, status code: %d" , issuerURL , resp .StatusCode )}
1542+ case resp .StatusCode == http .StatusOK :
1543+ // Do not retry if decoding fails
1544+ if err = json .NewDecoder (resp .Body ).Decode (& config ); err != nil {
1545+ return & backoff.PermanentError {Err : fmt .Errorf ("error decoding openid-configuration response: %w" , err )}
1546+ }
1547+ default :
1548+ // Do not retry on other status codes
1549+ return & backoff.PermanentError {Err : fmt .Errorf ("unexpected status code %d when fetching openid-configuration from issuer URL: %s" , resp .StatusCode , issuerURL )}
15251550 }
15261551 return nil
15271552 }, backoff .NewExponentialBackOff (backoff .WithMaxElapsedTime (5 * time .Second ))); err != nil {
15281553 return nil , err
15291554 }
15301555
1556+ if err = config .validate (); err != nil {
1557+ return nil , fmt .Errorf ("invalid openid-configuration from issuer URL %s: %w" , issuerURL , err )
1558+ }
1559+
15311560 return & config , nil
15321561}
15331562
1563+ func retryable (code int ) bool {
1564+ return code >= 500 &&
1565+ (code != http .StatusNotImplemented &&
1566+ code != http .StatusHTTPVersionNotSupported &&
1567+ code != http .StatusNetworkAuthenticationRequired )
1568+ }
1569+
15341570// validateTokenEndpoint validates the token endpoint URL
15351571func validateTokenEndpoint (tokenEndpoint string ) error {
15361572 parsedURL , err := url .Parse (tokenEndpoint )
0 commit comments