mirror of
https://github.com/nais/wonderwall.git
synced 2026-08-20 11:36:14 +00:00
fix(openid): bound and validate the provider metadata fetch
The metadata document was fetched with http.Get, which has no deadline, so a hung connection blocked startup indefinitely. The response status was never checked either, leaving an error page to surface as a JSON decoding error. The fetch now runs with a 10s deadline derived from the context passed in from main, goes through the shared transport so it is traced and pooled, and rejects any non-200 response.
This commit is contained in:
@@ -85,7 +85,7 @@ func run() error {
|
||||
}
|
||||
|
||||
func standalone(ctx context.Context, cfg *config.Config, crypt crypto.Crypter) (*handler.Standalone, error) {
|
||||
openidConfig, err := openidconfig.NewConfig(cfg)
|
||||
openidConfig, err := openidconfig.NewConfig(ctx, cfg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
wonderwallconfig "github.com/nais/wonderwall/pkg/config"
|
||||
)
|
||||
|
||||
@@ -22,13 +24,13 @@ func (c *openidconfig) Provider() Provider {
|
||||
return c.providerConfig
|
||||
}
|
||||
|
||||
func NewConfig(cfg *wonderwallconfig.Config) (Config, error) {
|
||||
func NewConfig(ctx context.Context, cfg *wonderwallconfig.Config) (Config, error) {
|
||||
clientCfg, err := NewClientConfig(cfg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
providerCfg, err := NewProviderConfig(cfg)
|
||||
providerCfg, err := NewProviderConfig(ctx, cfg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -1,15 +1,18 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"slices"
|
||||
"time"
|
||||
|
||||
"github.com/lestrrat-go/jwx/v3/jwa"
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
httpinternal "github.com/nais/wonderwall/internal/http"
|
||||
"github.com/nais/wonderwall/pkg/config"
|
||||
"github.com/nais/wonderwall/pkg/openid/acr"
|
||||
)
|
||||
@@ -83,13 +86,30 @@ func (p *provider) SidClaimRequired() bool {
|
||||
return p.metadata.FrontchannelLogoutSupported && p.metadata.FrontchannelLogoutSessionSupported
|
||||
}
|
||||
|
||||
func NewProviderConfig(cfg *config.Config) (Provider, error) {
|
||||
response, err := http.Get(cfg.OpenID.WellKnownURL)
|
||||
// wellKnownTimeout bounds the fetch of the provider's metadata document at startup.
|
||||
const wellKnownTimeout = 10 * time.Second
|
||||
|
||||
func NewProviderConfig(ctx context.Context, cfg *config.Config) (Provider, error) {
|
||||
ctx, cancel := context.WithTimeout(ctx, wellKnownTimeout)
|
||||
defer cancel()
|
||||
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, cfg.OpenID.WellKnownURL, nil)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("creating request for well known configuration: %w", err)
|
||||
}
|
||||
|
||||
client := &http.Client{Transport: httpinternal.Transport()}
|
||||
|
||||
response, err := client.Do(req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("fetching well known configuration: %w", err)
|
||||
}
|
||||
defer func() { _ = response.Body.Close() }()
|
||||
|
||||
if response.StatusCode != http.StatusOK {
|
||||
return nil, fmt.Errorf("fetching well known configuration: %s responded with HTTP %d", cfg.OpenID.WellKnownURL, response.StatusCode)
|
||||
}
|
||||
|
||||
providerCfg := new(ProviderMetadata)
|
||||
if err := json.NewDecoder(response.Body).Decode(providerCfg); err != nil {
|
||||
return nil, fmt.Errorf("decoding well known configuration: %w", err)
|
||||
|
||||
Reference in New Issue
Block a user