Add test for OIDC auto discovery configuration

pull/1691/head
Herman Slatman 5 months ago
parent 138c1013f6
commit 745017cf9a
No known key found for this signature in database
GPG Key ID: F4D8A44EA0A75A4F

@ -15,13 +15,13 @@ import (
) )
type Provider struct { type Provider struct {
DiscoveryBaseURL string `json:"discoveryBaseUrl,omitempty"` // TODO: probably safe to change to our usual configuration style DiscoveryBaseURL string `json:"discoveryBaseUrl,omitempty"`
IssuerURL string `json:"issuer,omitempty"` IssuerURL string `json:"issuerUrl,omitempty"`
AuthURL string `json:"authorization_endpoint,omitempty"` AuthURL string `json:"authorizationUrl,omitempty"`
TokenURL string `json:"token_endpoint,omitempty"` TokenURL string `json:"tokenUrl,omitempty"`
JWKSURL string `json:"jwks_uri,omitempty"` JWKSURL string `json:"jwksUrl,omitempty"`
UserInfoURL string `json:"userinfo_endpoint,omitempty"` UserInfoURL string `json:"userInfoUrl,omitempty"`
Algorithms []string `json:"id_token_signing_alg_values_supported,omitempty"` Algorithms []string `json:"signatureAlgorithms,omitempty"`
} }
type Config struct { type Config struct {
@ -94,13 +94,15 @@ func (o *OIDCOptions) validateAndInitialize() (err error) {
if o.Provider == nil { if o.Provider == nil {
return errors.New("provider not set") return errors.New("provider not set")
} }
if o.Provider.IssuerURL == "" { if o.Provider.IssuerURL == "" && o.Provider.DiscoveryBaseURL == "" {
return errors.New("issuer URL must not be empty") return errors.New("either OIDC discovery or issuer URL must be set")
} }
o.oidcProviderConfig, err = toOIDCProviderConfig(o.Provider) if o.Provider.DiscoveryBaseURL == "" {
if err != nil { o.oidcProviderConfig, err = toOIDCProviderConfig(o.Provider)
return fmt.Errorf("failed creationg OIDC provider config: %w", err) if err != nil {
return fmt.Errorf("failed creationg OIDC provider config: %w", err)
}
} }
o.target, err = template.New("DeviceID").Parse(o.Provider.IssuerURL) o.target, err = template.New("DeviceID").Parse(o.Provider.IssuerURL)

@ -1,12 +1,20 @@
package wire package wire
import ( import (
"context"
"encoding/json"
"errors" "errors"
"fmt"
"io"
"net/http"
"net/http/httptest"
"testing" "testing"
"text/template" "text/template"
"github.com/coreos/go-oidc/v3/oidc"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"go.step.sm/crypto/jose"
) )
func TestOIDCOptions_Transform(t *testing.T) { func TestOIDCOptions_Transform(t *testing.T) {
@ -171,3 +179,127 @@ func TestOIDCOptions_EvaluateTarget(t *testing.T) {
}) })
} }
} }
func TestOIDCOptions_GetVerifier(t *testing.T) {
signerJWK, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0)
require.NoError(t, err)
require.NoError(t, err)
srv := mustDiscoveryServer(t, signerJWK.Public())
defer srv.Close()
type fields struct {
Provider *Provider
Config *Config
TransformTemplate string
}
tests := []struct {
name string
fields fields
ctx context.Context
want *oidc.IDTokenVerifier
wantErr bool
}{
{
name: "fail/invalid-discovery-url",
fields: fields{
Provider: &Provider{
DiscoveryBaseURL: "http://invalid.example.com",
},
Config: &Config{
ClientID: "client-id",
},
TransformTemplate: "http://target.example.com/{{.DeviceID}}",
},
ctx: context.Background(),
wantErr: true,
},
{
name: "ok/auto",
fields: fields{
Provider: &Provider{
DiscoveryBaseURL: srv.URL,
},
Config: &Config{
ClientID: "client-id",
},
TransformTemplate: "http://target.example.com/{{.DeviceID}}",
},
ctx: context.Background(),
},
{
name: "ok/fixed",
fields: fields{
Provider: &Provider{
IssuerURL: "http://issuer.example.com",
},
Config: &Config{
ClientID: "client-id",
},
TransformTemplate: "http://target.example.com/{{.DeviceID}}",
},
ctx: context.Background(),
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
o := &OIDCOptions{
Provider: tt.fields.Provider,
Config: tt.fields.Config,
TransformTemplate: tt.fields.TransformTemplate,
}
err := o.validateAndInitialize()
require.NoError(t, err)
verifier, err := o.GetVerifier(tt.ctx)
if tt.wantErr {
assert.Error(t, err)
assert.Nil(t, verifier)
return
}
assert.NoError(t, err)
assert.NotNil(t, verifier)
if assert.NotNil(t, o.provider) {
assert.NotNil(t, o.provider.Endpoint())
}
})
}
}
func mustDiscoveryServer(t *testing.T, pub jose.JSONWebKey) *httptest.Server {
t.Helper()
mux := http.NewServeMux()
server := httptest.NewServer(mux)
b, err := json.Marshal(struct {
Keys []jose.JSONWebKey `json:"keys,omitempty"`
}{
Keys: []jose.JSONWebKey{pub},
})
require.NoError(t, err)
jwks := string(b)
wellKnown := fmt.Sprintf(`{
"issuer": "%[1]s",
"authorization_endpoint": "%[1]s/auth",
"token_endpoint": "%[1]s/token",
"jwks_uri": "%[1]s/keys",
"userinfo_endpoint": "%[1]s/userinfo",
"id_token_signing_alg_values_supported": ["ES256"]
}`, server.URL)
mux.HandleFunc("/.well-known/openid-configuration", func(w http.ResponseWriter, req *http.Request) {
_, err := io.WriteString(w, wellKnown)
if err != nil {
w.WriteHeader(500)
}
})
mux.HandleFunc("/keys", func(w http.ResponseWriter, req *http.Request) {
_, err := io.WriteString(w, jwks)
if err != nil {
w.WriteHeader(500)
}
})
t.Cleanup(server.Close)
return server
}

@ -55,7 +55,7 @@ MCowBQYDK2VwAyEA5c+4NKZSNQcR1T8qN6SjwgdPZQ0Ge12Ylx/YeGAJ35k=
}, },
DPOP: &DPOPOptions{}, DPOP: &DPOPOptions{},
}, },
expectedErr: errors.New("failed initializing OIDC options: issuer URL must not be empty"), expectedErr: errors.New("failed initializing OIDC options: either OIDC discovery or issuer URL must be set"),
}, },
{ {
name: "fail/invalid-issuer-url", name: "fail/invalid-issuer-url",

Loading…
Cancel
Save