Extract Supervisor IDP discovery endpoint types into apis package

This commit is contained in:
Ryan Richard 2021-08-17 15:23:03 -07:00
parent 964d16110e
commit 96474b3d99
11 changed files with 236 additions and 100 deletions

View File

@ -0,0 +1,29 @@
// Copyright 2021 the Pinniped contributors. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package v1alpha1
// SupervisorOIDCDiscoveryResponse is part of the response from a FederationDomain's OpenID Provider Configuration
// Document returned by the .well-known/openid-configuration endpoint. It ignores all the standard OpenID Provider
// configuration metadata and only picks out the portion related to Supervisor identity provider discovery.
type SupervisorOIDCDiscoveryResponse struct {
SupervisorDiscovery SupervisorOIDCDiscoveryResponseIDPEndpoint `json:"discovery.supervisor.pinniped.dev/v1alpha1"`
}
// SupervisorOIDCDiscoveryResponseIDPEndpoint contains the URL for the identity provider discovery endpoint.
type SupervisorOIDCDiscoveryResponseIDPEndpoint struct {
PinnipedIDPsEndpoint string `json:"pinniped_identity_providers_endpoint"`
}
// SupervisorIDPDiscoveryResponse is the response of a FederationDomain's identity provider discovery endpoint.
type SupervisorIDPDiscoveryResponse struct {
PinnipedIDPs []SupervisorPinnipedIDP `json:"pinniped_identity_providers"`
}
// SupervisorPinnipedIDP describes a single identity provider as included in the response of a FederationDomain's
// identity provider discovery endpoint.
type SupervisorPinnipedIDP struct {
Name string `json:"name"`
Type string `json:"type"`
Flows []string `json:"flows,omitempty"`
}

View File

@ -32,6 +32,7 @@ import (
conciergev1alpha1 "go.pinniped.dev/generated/latest/apis/concierge/authentication/v1alpha1"
configv1alpha1 "go.pinniped.dev/generated/latest/apis/concierge/config/v1alpha1"
idpdiscoveryv1alpha1 "go.pinniped.dev/generated/latest/apis/supervisor/idpdiscovery/v1alpha1"
conciergeclientset "go.pinniped.dev/generated/latest/client/concierge/clientset/versioned"
"go.pinniped.dev/internal/groupsuffix"
)
@ -98,24 +99,6 @@ type getKubeconfigParams struct {
credentialCachePathSet bool
}
type supervisorOIDCDiscoveryResponseWithV1Alpha1 struct {
SupervisorDiscovery SupervisorDiscoveryResponseV1Alpha1 `json:"discovery.supervisor.pinniped.dev/v1alpha1"`
}
type SupervisorDiscoveryResponseV1Alpha1 struct {
PinnipedIDPsEndpoint string `json:"pinniped_identity_providers_endpoint"`
}
type supervisorIDPsDiscoveryResponseV1Alpha1 struct {
PinnipedIDPs []pinnipedIDPResponse `json:"pinniped_identity_providers"`
}
type pinnipedIDPResponse struct {
Name string `json:"name"`
Type string `json:"type"`
Flows []string `json:"flows,omitempty"`
}
func kubeconfigCommand(deps kubeconfigDeps) *cobra.Command {
var (
cmd = &cobra.Command{
@ -818,7 +801,7 @@ func discoverIDPsDiscoveryEndpointURL(ctx context.Context, issuer string, httpCl
return "", fmt.Errorf("while fetching OIDC discovery data from issuer: %w", err)
}
var body supervisorOIDCDiscoveryResponseWithV1Alpha1
var body idpdiscoveryv1alpha1.SupervisorOIDCDiscoveryResponse
err = discoveredProvider.Claims(&body)
if err != nil {
return "", fmt.Errorf("while fetching OIDC discovery data from issuer: %w", err)
@ -827,7 +810,7 @@ func discoverIDPsDiscoveryEndpointURL(ctx context.Context, issuer string, httpCl
return body.SupervisorDiscovery.PinnipedIDPsEndpoint, nil
}
func discoverAllAvailableSupervisorUpstreamIDPs(ctx context.Context, pinnipedIDPsEndpoint string, httpClient *http.Client) ([]pinnipedIDPResponse, error) {
func discoverAllAvailableSupervisorUpstreamIDPs(ctx context.Context, pinnipedIDPsEndpoint string, httpClient *http.Client) ([]idpdiscoveryv1alpha1.SupervisorPinnipedIDP, error) {
request, err := http.NewRequestWithContext(ctx, http.MethodGet, pinnipedIDPsEndpoint, nil)
if err != nil {
return nil, fmt.Errorf("while forming request to IDP discovery URL: %w", err)
@ -849,7 +832,7 @@ func discoverAllAvailableSupervisorUpstreamIDPs(ctx context.Context, pinnipedIDP
return nil, fmt.Errorf("unable to fetch IDP discovery data from issuer: could not read response body: %w", err)
}
var body supervisorIDPsDiscoveryResponseV1Alpha1
var body idpdiscoveryv1alpha1.SupervisorIDPDiscoveryResponse
err = json.Unmarshal(rawBody, &body)
if err != nil {
return nil, fmt.Errorf("unable to fetch IDP discovery data from issuer: could not parse response JSON: %w", err)
@ -858,7 +841,7 @@ func discoverAllAvailableSupervisorUpstreamIDPs(ctx context.Context, pinnipedIDP
return body.PinnipedIDPs, nil
}
func selectUpstreamIDPNameAndType(pinnipedIDPs []pinnipedIDPResponse, specifiedIDPName, specifiedIDPType string) (string, string, []string, error) {
func selectUpstreamIDPNameAndType(pinnipedIDPs []idpdiscoveryv1alpha1.SupervisorPinnipedIDP, specifiedIDPName, specifiedIDPType string) (string, string, []string, error) {
pinnipedIDPsString, _ := json.Marshal(pinnipedIDPs)
var discoveredFlows []string
switch {

View File

@ -0,0 +1,29 @@
// Copyright 2021 the Pinniped contributors. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package v1alpha1
// SupervisorOIDCDiscoveryResponse is part of the response from a FederationDomain's OpenID Provider Configuration
// Document returned by the .well-known/openid-configuration endpoint. It ignores all the standard OpenID Provider
// configuration metadata and only picks out the portion related to Supervisor identity provider discovery.
type SupervisorOIDCDiscoveryResponse struct {
SupervisorDiscovery SupervisorOIDCDiscoveryResponseIDPEndpoint `json:"discovery.supervisor.pinniped.dev/v1alpha1"`
}
// SupervisorOIDCDiscoveryResponseIDPEndpoint contains the URL for the identity provider discovery endpoint.
type SupervisorOIDCDiscoveryResponseIDPEndpoint struct {
PinnipedIDPsEndpoint string `json:"pinniped_identity_providers_endpoint"`
}
// SupervisorIDPDiscoveryResponse is the response of a FederationDomain's identity provider discovery endpoint.
type SupervisorIDPDiscoveryResponse struct {
PinnipedIDPs []SupervisorPinnipedIDP `json:"pinniped_identity_providers"`
}
// SupervisorPinnipedIDP describes a single identity provider as included in the response of a FederationDomain's
// identity provider discovery endpoint.
type SupervisorPinnipedIDP struct {
Name string `json:"name"`
Type string `json:"type"`
Flows []string `json:"flows,omitempty"`
}

View File

@ -0,0 +1,29 @@
// Copyright 2021 the Pinniped contributors. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package v1alpha1
// SupervisorOIDCDiscoveryResponse is part of the response from a FederationDomain's OpenID Provider Configuration
// Document returned by the .well-known/openid-configuration endpoint. It ignores all the standard OpenID Provider
// configuration metadata and only picks out the portion related to Supervisor identity provider discovery.
type SupervisorOIDCDiscoveryResponse struct {
SupervisorDiscovery SupervisorOIDCDiscoveryResponseIDPEndpoint `json:"discovery.supervisor.pinniped.dev/v1alpha1"`
}
// SupervisorOIDCDiscoveryResponseIDPEndpoint contains the URL for the identity provider discovery endpoint.
type SupervisorOIDCDiscoveryResponseIDPEndpoint struct {
PinnipedIDPsEndpoint string `json:"pinniped_identity_providers_endpoint"`
}
// SupervisorIDPDiscoveryResponse is the response of a FederationDomain's identity provider discovery endpoint.
type SupervisorIDPDiscoveryResponse struct {
PinnipedIDPs []SupervisorPinnipedIDP `json:"pinniped_identity_providers"`
}
// SupervisorPinnipedIDP describes a single identity provider as included in the response of a FederationDomain's
// identity provider discovery endpoint.
type SupervisorPinnipedIDP struct {
Name string `json:"name"`
Type string `json:"type"`
Flows []string `json:"flows,omitempty"`
}

View File

@ -0,0 +1,29 @@
// Copyright 2021 the Pinniped contributors. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package v1alpha1
// SupervisorOIDCDiscoveryResponse is part of the response from a FederationDomain's OpenID Provider Configuration
// Document returned by the .well-known/openid-configuration endpoint. It ignores all the standard OpenID Provider
// configuration metadata and only picks out the portion related to Supervisor identity provider discovery.
type SupervisorOIDCDiscoveryResponse struct {
SupervisorDiscovery SupervisorOIDCDiscoveryResponseIDPEndpoint `json:"discovery.supervisor.pinniped.dev/v1alpha1"`
}
// SupervisorOIDCDiscoveryResponseIDPEndpoint contains the URL for the identity provider discovery endpoint.
type SupervisorOIDCDiscoveryResponseIDPEndpoint struct {
PinnipedIDPsEndpoint string `json:"pinniped_identity_providers_endpoint"`
}
// SupervisorIDPDiscoveryResponse is the response of a FederationDomain's identity provider discovery endpoint.
type SupervisorIDPDiscoveryResponse struct {
PinnipedIDPs []SupervisorPinnipedIDP `json:"pinniped_identity_providers"`
}
// SupervisorPinnipedIDP describes a single identity provider as included in the response of a FederationDomain's
// identity provider discovery endpoint.
type SupervisorPinnipedIDP struct {
Name string `json:"name"`
Type string `json:"type"`
Flows []string `json:"flows,omitempty"`
}

View File

@ -0,0 +1,29 @@
// Copyright 2021 the Pinniped contributors. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package v1alpha1
// SupervisorOIDCDiscoveryResponse is part of the response from a FederationDomain's OpenID Provider Configuration
// Document returned by the .well-known/openid-configuration endpoint. It ignores all the standard OpenID Provider
// configuration metadata and only picks out the portion related to Supervisor identity provider discovery.
type SupervisorOIDCDiscoveryResponse struct {
SupervisorDiscovery SupervisorOIDCDiscoveryResponseIDPEndpoint `json:"discovery.supervisor.pinniped.dev/v1alpha1"`
}
// SupervisorOIDCDiscoveryResponseIDPEndpoint contains the URL for the identity provider discovery endpoint.
type SupervisorOIDCDiscoveryResponseIDPEndpoint struct {
PinnipedIDPsEndpoint string `json:"pinniped_identity_providers_endpoint"`
}
// SupervisorIDPDiscoveryResponse is the response of a FederationDomain's identity provider discovery endpoint.
type SupervisorIDPDiscoveryResponse struct {
PinnipedIDPs []SupervisorPinnipedIDP `json:"pinniped_identity_providers"`
}
// SupervisorPinnipedIDP describes a single identity provider as included in the response of a FederationDomain's
// identity provider discovery endpoint.
type SupervisorPinnipedIDP struct {
Name string `json:"name"`
Type string `json:"type"`
Flows []string `json:"flows,omitempty"`
}

View File

@ -0,0 +1,29 @@
// Copyright 2021 the Pinniped contributors. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package v1alpha1
// SupervisorOIDCDiscoveryResponse is part of the response from a FederationDomain's OpenID Provider Configuration
// Document returned by the .well-known/openid-configuration endpoint. It ignores all the standard OpenID Provider
// configuration metadata and only picks out the portion related to Supervisor identity provider discovery.
type SupervisorOIDCDiscoveryResponse struct {
SupervisorDiscovery SupervisorOIDCDiscoveryResponseIDPEndpoint `json:"discovery.supervisor.pinniped.dev/v1alpha1"`
}
// SupervisorOIDCDiscoveryResponseIDPEndpoint contains the URL for the identity provider discovery endpoint.
type SupervisorOIDCDiscoveryResponseIDPEndpoint struct {
PinnipedIDPsEndpoint string `json:"pinniped_identity_providers_endpoint"`
}
// SupervisorIDPDiscoveryResponse is the response of a FederationDomain's identity provider discovery endpoint.
type SupervisorIDPDiscoveryResponse struct {
PinnipedIDPs []SupervisorPinnipedIDP `json:"pinniped_identity_providers"`
}
// SupervisorPinnipedIDP describes a single identity provider as included in the response of a FederationDomain's
// identity provider discovery endpoint.
type SupervisorPinnipedIDP struct {
Name string `json:"name"`
Type string `json:"type"`
Flows []string `json:"flows,omitempty"`
}

View File

@ -9,6 +9,7 @@ import (
"encoding/json"
"net/http"
"go.pinniped.dev/generated/latest/apis/supervisor/idpdiscovery/v1alpha1"
"go.pinniped.dev/internal/oidc"
)
@ -41,20 +42,11 @@ type Metadata struct {
// vvv Custom vvv
SupervisorDiscovery SupervisorDiscoveryMetadataV1Alpha1 `json:"discovery.supervisor.pinniped.dev/v1alpha1"`
SupervisorDiscovery v1alpha1.SupervisorOIDCDiscoveryResponseIDPEndpoint `json:"discovery.supervisor.pinniped.dev/v1alpha1"`
// ^^^ Custom ^^^
}
type SupervisorDiscoveryMetadataV1Alpha1 struct {
PinnipedIDPsEndpoint string `json:"pinniped_identity_providers_endpoint"`
}
type IdentityProviderMetadata struct {
Name string `json:"name"`
Type string `json:"type"`
}
// NewHandler returns an http.Handler that serves an OIDC discovery endpoint.
func NewHandler(issuerURL string) http.Handler {
oidcConfig := Metadata{
@ -62,7 +54,7 @@ func NewHandler(issuerURL string) http.Handler {
AuthorizationEndpoint: issuerURL + oidc.AuthorizationEndpointPath,
TokenEndpoint: issuerURL + oidc.TokenEndpointPath,
JWKSURI: issuerURL + oidc.JWKSEndpointPath,
SupervisorDiscovery: SupervisorDiscoveryMetadataV1Alpha1{PinnipedIDPsEndpoint: issuerURL + oidc.PinnipedIDPsPathV1Alpha1},
SupervisorDiscovery: v1alpha1.SupervisorOIDCDiscoveryResponseIDPEndpoint{PinnipedIDPsEndpoint: issuerURL + oidc.PinnipedIDPsPathV1Alpha1},
ResponseTypesSupported: []string{"code"},
ResponseModesSupported: []string{"query", "form_post"},
SubjectTypesSupported: []string{"public"},

View File

@ -4,13 +4,13 @@
package discovery
import (
"encoding/json"
"net/http"
"net/http/httptest"
"testing"
"github.com/stretchr/testify/require"
"go.pinniped.dev/internal/here"
"go.pinniped.dev/internal/oidc"
)
@ -24,7 +24,7 @@ func TestDiscovery(t *testing.T) {
wantStatus int
wantContentType string
wantBodyJSON interface{}
wantBodyJSON string
wantBodyString string
}{
{
@ -34,22 +34,24 @@ func TestDiscovery(t *testing.T) {
path: "/some/path" + oidc.WellKnownEndpointPath,
wantStatus: http.StatusOK,
wantContentType: "application/json",
wantBodyJSON: &Metadata{
Issuer: "https://some-issuer.com/some/path",
AuthorizationEndpoint: "https://some-issuer.com/some/path/oauth2/authorize",
TokenEndpoint: "https://some-issuer.com/some/path/oauth2/token",
JWKSURI: "https://some-issuer.com/some/path/jwks.json",
SupervisorDiscovery: SupervisorDiscoveryMetadataV1Alpha1{
PinnipedIDPsEndpoint: "https://some-issuer.com/some/path/v1alpha1/pinniped_identity_providers",
},
ResponseTypesSupported: []string{"code"},
ResponseModesSupported: []string{"query", "form_post"},
SubjectTypesSupported: []string{"public"},
IDTokenSigningAlgValuesSupported: []string{"ES256"},
TokenEndpointAuthMethodsSupported: []string{"client_secret_basic"},
ScopesSupported: []string{"openid", "offline"},
ClaimsSupported: []string{"groups"},
},
wantBodyJSON: here.Doc(`
{
"issuer": "https://some-issuer.com/some/path",
"authorization_endpoint": "https://some-issuer.com/some/path/oauth2/authorize",
"token_endpoint": "https://some-issuer.com/some/path/oauth2/token",
"jwks_uri": "https://some-issuer.com/some/path/jwks.json",
"response_types_supported": ["code"],
"response_modes_supported": ["query", "form_post"],
"subject_types_supported": ["public"],
"id_token_signing_alg_values_supported": ["ES256"],
"token_endpoint_auth_methods_supported": ["client_secret_basic"],
"scopes_supported": ["openid", "offline"],
"claims_supported": ["groups"],
"discovery.supervisor.pinniped.dev/v1alpha1": {
"pinniped_identity_providers_endpoint": "https://some-issuer.com/some/path/v1alpha1/pinniped_identity_providers"
}
}
`),
},
{
name: "bad method",
@ -73,10 +75,8 @@ func TestDiscovery(t *testing.T) {
require.Equal(t, test.wantContentType, rsp.Header().Get("Content-Type"))
if test.wantBodyJSON != nil {
wantJSON, err := json.Marshal(test.wantBodyJSON)
require.NoError(t, err)
require.JSONEq(t, string(wantJSON), rsp.Body.String())
if test.wantBodyJSON != "" {
require.JSONEq(t, test.wantBodyJSON, rsp.Body.String())
}
if test.wantBodyString != "" {

View File

@ -10,6 +10,7 @@ import (
"net/http"
"sort"
"go.pinniped.dev/generated/latest/apis/supervisor/idpdiscovery/v1alpha1"
"go.pinniped.dev/internal/oidc"
)
@ -21,16 +22,6 @@ const (
flowCLIPassword = "cli_password"
)
type response struct {
IDPs []identityProviderResponse `json:"pinniped_identity_providers"`
}
type identityProviderResponse struct {
Name string `json:"name"`
Type string `json:"type"`
Flows []string `json:"flows"`
}
// NewHandler returns an http.Handler that serves the upstream IDP discovery endpoint.
func NewHandler(upstreamIDPs oidc.UpstreamIdentityProvidersLister) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
@ -54,13 +45,13 @@ func NewHandler(upstreamIDPs oidc.UpstreamIdentityProvidersLister) http.Handler
}
func responseAsJSON(upstreamIDPs oidc.UpstreamIdentityProvidersLister) ([]byte, error) {
r := response{
IDPs: []identityProviderResponse{},
r := v1alpha1.SupervisorIDPDiscoveryResponse{
PinnipedIDPs: []v1alpha1.SupervisorPinnipedIDP{},
}
// The cache of IDPs could change at any time, so always recalculate the list.
for _, provider := range upstreamIDPs.GetLDAPIdentityProviders() {
r.IDPs = append(r.IDPs, identityProviderResponse{
r.PinnipedIDPs = append(r.PinnipedIDPs, v1alpha1.SupervisorPinnipedIDP{
Name: provider.GetName(),
Type: idpDiscoveryTypeLDAP,
Flows: []string{flowCLIPassword},
@ -71,7 +62,7 @@ func responseAsJSON(upstreamIDPs oidc.UpstreamIdentityProvidersLister) ([]byte,
if provider.AllowsPasswordGrant() {
flows = append(flows, flowCLIPassword)
}
r.IDPs = append(r.IDPs, identityProviderResponse{
r.PinnipedIDPs = append(r.PinnipedIDPs, v1alpha1.SupervisorPinnipedIDP{
Name: provider.GetName(),
Type: idpDiscoveryTypeOIDC,
Flows: flows,
@ -79,8 +70,8 @@ func responseAsJSON(upstreamIDPs oidc.UpstreamIdentityProvidersLister) ([]byte,
}
// Nobody like an API that changes the results unnecessarily. :)
sort.SliceStable(r.IDPs, func(i, j int) bool {
return r.IDPs[i].Name < r.IDPs[j].Name
sort.SliceStable(r.PinnipedIDPs, func(i, j int) bool {
return r.PinnipedIDPs[i].Name < r.PinnipedIDPs[j].Name
})
var b bytes.Buffer

View File

@ -4,13 +4,13 @@
package idpdiscovery
import (
"encoding/json"
"net/http"
"net/http/httptest"
"testing"
"github.com/stretchr/testify/require"
"go.pinniped.dev/internal/here"
"go.pinniped.dev/internal/oidc"
"go.pinniped.dev/internal/oidc/provider"
"go.pinniped.dev/internal/testutil/oidctestutil"
@ -25,8 +25,8 @@ func TestIDPDiscovery(t *testing.T) {
wantStatus int
wantContentType string
wantFirstResponseBodyJSON interface{}
wantSecondResponseBodyJSON interface{}
wantFirstResponseBodyJSON string
wantSecondResponseBodyJSON string
wantBodyString string
}{
{
@ -35,24 +35,24 @@ func TestIDPDiscovery(t *testing.T) {
path: "/some/path" + oidc.WellKnownEndpointPath,
wantStatus: http.StatusOK,
wantContentType: "application/json",
wantFirstResponseBodyJSON: &response{
IDPs: []identityProviderResponse{
{Name: "a-some-ldap-idp", Type: "ldap", Flows: []string{"cli_password"}},
{Name: "a-some-oidc-idp", Type: "oidc", Flows: []string{"browser_authcode"}},
{Name: "x-some-idp", Type: "ldap", Flows: []string{"cli_password"}},
{Name: "x-some-idp", Type: "oidc", Flows: []string{"browser_authcode"}},
{Name: "z-some-ldap-idp", Type: "ldap", Flows: []string{"cli_password"}},
{Name: "z-some-oidc-idp", Type: "oidc", Flows: []string{"browser_authcode", "cli_password"}},
},
},
wantSecondResponseBodyJSON: &response{
IDPs: []identityProviderResponse{
{Name: "some-other-ldap-idp-1", Type: "ldap", Flows: []string{"cli_password"}},
{Name: "some-other-ldap-idp-2", Type: "ldap", Flows: []string{"cli_password"}},
{Name: "some-other-oidc-idp-1", Type: "oidc", Flows: []string{"browser_authcode", "cli_password"}},
{Name: "some-other-oidc-idp-2", Type: "oidc", Flows: []string{"browser_authcode"}},
},
},
wantFirstResponseBodyJSON: here.Doc(`{
"pinniped_identity_providers": [
{"name": "a-some-ldap-idp", "type": "ldap", "flows": ["cli_password"]},
{"name": "a-some-oidc-idp", "type": "oidc", "flows": ["browser_authcode"]},
{"name": "x-some-idp", "type": "ldap", "flows": ["cli_password"]},
{"name": "x-some-idp", "type": "oidc", "flows": ["browser_authcode"]},
{"name": "z-some-ldap-idp", "type": "ldap", "flows": ["cli_password"]},
{"name": "z-some-oidc-idp", "type": "oidc", "flows": ["browser_authcode", "cli_password"]}
]
}`),
wantSecondResponseBodyJSON: here.Doc(`{
"pinniped_identity_providers": [
{"name": "some-other-ldap-idp-1", "type": "ldap", "flows": ["cli_password"]},
{"name": "some-other-ldap-idp-2", "type": "ldap", "flows": ["cli_password"]},
{"name": "some-other-oidc-idp-1", "type": "oidc", "flows": ["browser_authcode", "cli_password"]},
{"name": "some-other-oidc-idp-2", "type": "oidc", "flows": ["browser_authcode"]}
]
}`),
},
{
name: "bad method",
@ -84,10 +84,8 @@ func TestIDPDiscovery(t *testing.T) {
require.Equal(t, test.wantContentType, rsp.Header().Get("Content-Type"))
if test.wantFirstResponseBodyJSON != nil {
wantJSON, err := json.Marshal(test.wantFirstResponseBodyJSON)
require.NoError(t, err)
require.JSONEq(t, string(wantJSON), rsp.Body.String())
if test.wantFirstResponseBodyJSON != "" {
require.JSONEq(t, test.wantFirstResponseBodyJSON, rsp.Body.String())
}
if test.wantBodyString != "" {
@ -112,10 +110,8 @@ func TestIDPDiscovery(t *testing.T) {
require.Equal(t, test.wantContentType, rsp.Header().Get("Content-Type"))
if test.wantFirstResponseBodyJSON != nil {
wantJSON, err := json.Marshal(test.wantSecondResponseBodyJSON)
require.NoError(t, err)
require.JSONEq(t, string(wantJSON), rsp.Body.String())
if test.wantFirstResponseBodyJSON != "" {
require.JSONEq(t, test.wantSecondResponseBodyJSON, rsp.Body.String())
}
if test.wantBodyString != "" {