mirror of
https://github.com/vmware-tanzu/pinniped.git
synced 2026-09-06 16:17:08 +00:00
More unit tests for dynamic clients
- Add dynamic client unit tests for the upstream OIDC callback and POST login endpoints. - Enhance a few log statements to print the full fosite error messages into the logs where they were previously only printing the name of the error type.
This commit is contained in:
@@ -54,7 +54,9 @@ const (
|
||||
|
||||
downstreamIssuer = "https://my-downstream-issuer.com/path"
|
||||
downstreamRedirectURI = "http://127.0.0.1/callback"
|
||||
downstreamClientID = "pinniped-cli"
|
||||
downstreamPinnipedClientID = "pinniped-cli"
|
||||
downstreamDynamicClientID = "client.oauth.pinniped.dev-test-name"
|
||||
downstreamDynamicClientUID = "fake-client-uid"
|
||||
downstreamNonce = "some-nonce-value"
|
||||
downstreamPKCEChallenge = "some-challenge"
|
||||
downstreamPKCEChallengeMethod = "S256"
|
||||
@@ -70,14 +72,19 @@ var (
|
||||
happyDownstreamRequestParamsQuery = url.Values{
|
||||
"response_type": []string{"code"},
|
||||
"scope": []string{strings.Join(happyDownstreamScopesRequested, " ")},
|
||||
"client_id": []string{downstreamClientID},
|
||||
"client_id": []string{downstreamPinnipedClientID},
|
||||
"state": []string{happyDownstreamState},
|
||||
"nonce": []string{downstreamNonce},
|
||||
"code_challenge": []string{downstreamPKCEChallenge},
|
||||
"code_challenge_method": []string{downstreamPKCEChallengeMethod},
|
||||
"redirect_uri": []string{downstreamRedirectURI},
|
||||
}
|
||||
happyDownstreamRequestParams = happyDownstreamRequestParamsQuery.Encode()
|
||||
happyDownstreamRequestParams = happyDownstreamRequestParamsQuery.Encode()
|
||||
|
||||
happyDownstreamRequestParamsForDynamicClient = shallowCopyAndModifyQuery(happyDownstreamRequestParamsQuery,
|
||||
map[string]string{"client_id": downstreamDynamicClientID},
|
||||
).Encode()
|
||||
|
||||
happyDownstreamCustomSessionData = &psession.CustomSessionData{
|
||||
ProviderUID: happyUpstreamIDPResourceUID,
|
||||
ProviderName: happyUpstreamIDPName,
|
||||
@@ -122,6 +129,7 @@ func TestCallbackEndpoint(t *testing.T) {
|
||||
happyCookieCodec.SetSerializer(securecookie.JSONEncoder{})
|
||||
|
||||
happyState := happyUpstreamStateParam().Build(t, happyStateCodec)
|
||||
happyStateForDynamicClient := happyUpstreamStateParamForDynamicClient().Build(t, happyStateCodec)
|
||||
|
||||
encodedIncomingCookieCSRFValue, err := happyCookieCodec.Encode("csrf", happyDownstreamCSRF)
|
||||
require.NoError(t, err)
|
||||
@@ -137,6 +145,13 @@ func TestCallbackEndpoint(t *testing.T) {
|
||||
// Note that fosite puts the granted scopes as a param in the redirect URI even though the spec doesn't seem to require it
|
||||
happyDownstreamRedirectLocationRegexp := downstreamRedirectURI + `\?code=([^&]+)&scope=openid\+groups&state=` + happyDownstreamState
|
||||
|
||||
addFullyCapableDynamicClientAndSecretToKubeResources := func(t *testing.T, supervisorClient *supervisorfake.Clientset, kubeClient *fake.Clientset) {
|
||||
oidcClient, secret := testutil.FullyCapableOIDCClientAndStorageSecret(t,
|
||||
"some-namespace", downstreamDynamicClientID, downstreamDynamicClientUID, downstreamRedirectURI, []string{testutil.HashedPassword1AtGoMinCost})
|
||||
require.NoError(t, supervisorClient.Tracker().Add(oidcClient))
|
||||
require.NoError(t, kubeClient.Tracker().Add(secret))
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
|
||||
@@ -157,6 +172,7 @@ func TestCallbackEndpoint(t *testing.T) {
|
||||
wantDownstreamIDTokenGroups []string
|
||||
wantDownstreamRequestedScopes []string
|
||||
wantDownstreamNonce string
|
||||
wantDownstreamClientID string
|
||||
wantDownstreamPKCEChallenge string
|
||||
wantDownstreamPKCEChallengeMethod string
|
||||
wantDownstreamCustomSessionData *psession.CustomSessionData
|
||||
@@ -185,6 +201,7 @@ func TestCallbackEndpoint(t *testing.T) {
|
||||
wantDownstreamRequestedScopes: happyDownstreamScopesRequested,
|
||||
wantDownstreamGrantedScopes: happyDownstreamScopesGranted,
|
||||
wantDownstreamNonce: downstreamNonce,
|
||||
wantDownstreamClientID: downstreamPinnipedClientID,
|
||||
wantDownstreamPKCEChallenge: downstreamPKCEChallenge,
|
||||
wantDownstreamPKCEChallengeMethod: downstreamPKCEChallengeMethod,
|
||||
wantDownstreamCustomSessionData: happyDownstreamCustomSessionData,
|
||||
@@ -208,6 +225,32 @@ func TestCallbackEndpoint(t *testing.T) {
|
||||
wantDownstreamRequestedScopes: happyDownstreamScopesRequested,
|
||||
wantDownstreamGrantedScopes: happyDownstreamScopesGranted,
|
||||
wantDownstreamNonce: downstreamNonce,
|
||||
wantDownstreamClientID: downstreamPinnipedClientID,
|
||||
wantDownstreamPKCEChallenge: downstreamPKCEChallenge,
|
||||
wantDownstreamPKCEChallengeMethod: downstreamPKCEChallengeMethod,
|
||||
wantDownstreamCustomSessionData: happyDownstreamCustomSessionData,
|
||||
wantAuthcodeExchangeCall: &expectedAuthcodeExchange{
|
||||
performedByUpstreamName: happyUpstreamIDPName,
|
||||
args: happyExchangeAndValidateTokensArgs,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "GET with good state and cookie and successful upstream token exchange returns 303 to downstream client callback with its state and code when using dynamic client",
|
||||
idps: oidctestutil.NewUpstreamIDPListerBuilder().WithOIDC(happyUpstream().Build()),
|
||||
kubeResources: addFullyCapableDynamicClientAndSecretToKubeResources,
|
||||
method: http.MethodGet,
|
||||
path: newRequestPath().WithState(happyStateForDynamicClient).String(),
|
||||
csrfCookie: happyCSRFCookie,
|
||||
wantStatus: http.StatusSeeOther,
|
||||
wantRedirectLocationRegexp: happyDownstreamRedirectLocationRegexp,
|
||||
wantBody: "",
|
||||
wantDownstreamIDTokenSubject: oidcUpstreamIssuer + "?sub=" + oidcUpstreamSubjectQueryEscaped,
|
||||
wantDownstreamIDTokenUsername: oidcUpstreamUsername,
|
||||
wantDownstreamIDTokenGroups: oidcUpstreamGroupMembership,
|
||||
wantDownstreamRequestedScopes: happyDownstreamScopesRequested,
|
||||
wantDownstreamGrantedScopes: happyDownstreamScopesGranted,
|
||||
wantDownstreamNonce: downstreamNonce,
|
||||
wantDownstreamClientID: downstreamDynamicClientID,
|
||||
wantDownstreamPKCEChallenge: downstreamPKCEChallenge,
|
||||
wantDownstreamPKCEChallengeMethod: downstreamPKCEChallengeMethod,
|
||||
wantDownstreamCustomSessionData: happyDownstreamCustomSessionData,
|
||||
@@ -231,6 +274,7 @@ func TestCallbackEndpoint(t *testing.T) {
|
||||
wantDownstreamRequestedScopes: happyDownstreamScopesRequested,
|
||||
wantDownstreamGrantedScopes: happyDownstreamScopesGranted,
|
||||
wantDownstreamNonce: downstreamNonce,
|
||||
wantDownstreamClientID: downstreamPinnipedClientID,
|
||||
wantDownstreamPKCEChallenge: downstreamPKCEChallenge,
|
||||
wantDownstreamPKCEChallengeMethod: downstreamPKCEChallengeMethod,
|
||||
wantDownstreamCustomSessionData: happyDownstreamAccessTokenCustomSessionData,
|
||||
@@ -263,6 +307,7 @@ func TestCallbackEndpoint(t *testing.T) {
|
||||
wantDownstreamRequestedScopes: []string{"openid"},
|
||||
wantDownstreamGrantedScopes: []string{"openid"},
|
||||
wantDownstreamNonce: downstreamNonce,
|
||||
wantDownstreamClientID: downstreamPinnipedClientID,
|
||||
wantDownstreamPKCEChallenge: downstreamPKCEChallenge,
|
||||
wantDownstreamPKCEChallengeMethod: downstreamPKCEChallengeMethod,
|
||||
wantDownstreamCustomSessionData: happyDownstreamCustomSessionData,
|
||||
@@ -286,6 +331,7 @@ func TestCallbackEndpoint(t *testing.T) {
|
||||
wantDownstreamRequestedScopes: happyDownstreamScopesRequested,
|
||||
wantDownstreamGrantedScopes: happyDownstreamScopesGranted,
|
||||
wantDownstreamNonce: downstreamNonce,
|
||||
wantDownstreamClientID: downstreamPinnipedClientID,
|
||||
wantDownstreamPKCEChallenge: downstreamPKCEChallenge,
|
||||
wantDownstreamPKCEChallengeMethod: downstreamPKCEChallengeMethod,
|
||||
wantDownstreamCustomSessionData: &psession.CustomSessionData{
|
||||
@@ -321,6 +367,7 @@ func TestCallbackEndpoint(t *testing.T) {
|
||||
wantDownstreamRequestedScopes: happyDownstreamScopesRequested,
|
||||
wantDownstreamGrantedScopes: happyDownstreamScopesGranted,
|
||||
wantDownstreamNonce: downstreamNonce,
|
||||
wantDownstreamClientID: downstreamPinnipedClientID,
|
||||
wantDownstreamPKCEChallenge: downstreamPKCEChallenge,
|
||||
wantDownstreamPKCEChallengeMethod: downstreamPKCEChallengeMethod,
|
||||
wantDownstreamCustomSessionData: happyDownstreamCustomSessionData,
|
||||
@@ -346,6 +393,7 @@ func TestCallbackEndpoint(t *testing.T) {
|
||||
wantDownstreamRequestedScopes: happyDownstreamScopesRequested,
|
||||
wantDownstreamGrantedScopes: happyDownstreamScopesGranted,
|
||||
wantDownstreamNonce: downstreamNonce,
|
||||
wantDownstreamClientID: downstreamPinnipedClientID,
|
||||
wantDownstreamPKCEChallenge: downstreamPKCEChallenge,
|
||||
wantDownstreamPKCEChallengeMethod: downstreamPKCEChallengeMethod,
|
||||
wantDownstreamCustomSessionData: happyDownstreamCustomSessionData,
|
||||
@@ -373,6 +421,7 @@ func TestCallbackEndpoint(t *testing.T) {
|
||||
wantDownstreamRequestedScopes: happyDownstreamScopesRequested,
|
||||
wantDownstreamGrantedScopes: happyDownstreamScopesGranted,
|
||||
wantDownstreamNonce: downstreamNonce,
|
||||
wantDownstreamClientID: downstreamPinnipedClientID,
|
||||
wantDownstreamPKCEChallenge: downstreamPKCEChallenge,
|
||||
wantDownstreamPKCEChallengeMethod: downstreamPKCEChallengeMethod,
|
||||
wantDownstreamCustomSessionData: happyDownstreamCustomSessionData,
|
||||
@@ -401,6 +450,7 @@ func TestCallbackEndpoint(t *testing.T) {
|
||||
wantDownstreamRequestedScopes: happyDownstreamScopesRequested,
|
||||
wantDownstreamGrantedScopes: happyDownstreamScopesGranted,
|
||||
wantDownstreamNonce: downstreamNonce,
|
||||
wantDownstreamClientID: downstreamPinnipedClientID,
|
||||
wantDownstreamPKCEChallenge: downstreamPKCEChallenge,
|
||||
wantDownstreamPKCEChallengeMethod: downstreamPKCEChallengeMethod,
|
||||
wantDownstreamCustomSessionData: happyDownstreamCustomSessionData,
|
||||
@@ -531,6 +581,7 @@ func TestCallbackEndpoint(t *testing.T) {
|
||||
wantDownstreamRequestedScopes: happyDownstreamScopesRequested,
|
||||
wantDownstreamGrantedScopes: happyDownstreamScopesGranted,
|
||||
wantDownstreamNonce: downstreamNonce,
|
||||
wantDownstreamClientID: downstreamPinnipedClientID,
|
||||
wantDownstreamPKCEChallenge: downstreamPKCEChallenge,
|
||||
wantDownstreamPKCEChallengeMethod: downstreamPKCEChallengeMethod,
|
||||
wantDownstreamCustomSessionData: happyDownstreamCustomSessionData,
|
||||
@@ -556,6 +607,7 @@ func TestCallbackEndpoint(t *testing.T) {
|
||||
wantDownstreamRequestedScopes: happyDownstreamScopesRequested,
|
||||
wantDownstreamGrantedScopes: happyDownstreamScopesGranted,
|
||||
wantDownstreamNonce: downstreamNonce,
|
||||
wantDownstreamClientID: downstreamPinnipedClientID,
|
||||
wantDownstreamPKCEChallenge: downstreamPKCEChallenge,
|
||||
wantDownstreamPKCEChallengeMethod: downstreamPKCEChallengeMethod,
|
||||
wantDownstreamCustomSessionData: happyDownstreamCustomSessionData,
|
||||
@@ -581,6 +633,7 @@ func TestCallbackEndpoint(t *testing.T) {
|
||||
wantDownstreamRequestedScopes: happyDownstreamScopesRequested,
|
||||
wantDownstreamGrantedScopes: happyDownstreamScopesGranted,
|
||||
wantDownstreamNonce: downstreamNonce,
|
||||
wantDownstreamClientID: downstreamPinnipedClientID,
|
||||
wantDownstreamPKCEChallenge: downstreamPKCEChallenge,
|
||||
wantDownstreamPKCEChallengeMethod: downstreamPKCEChallengeMethod,
|
||||
wantDownstreamCustomSessionData: happyDownstreamCustomSessionData,
|
||||
@@ -714,6 +767,42 @@ func TestCallbackEndpoint(t *testing.T) {
|
||||
wantContentType: htmlContentType,
|
||||
wantBody: "Bad Request: error using state downstream auth params\n",
|
||||
},
|
||||
{
|
||||
name: "state's downstream auth params have invalid client_id",
|
||||
idps: oidctestutil.NewUpstreamIDPListerBuilder().WithOIDC(happyUpstream().Build()),
|
||||
method: http.MethodGet,
|
||||
path: newRequestPath().WithState(
|
||||
happyUpstreamStateParam().
|
||||
WithAuthorizeRequestParams(shallowCopyAndModifyQuery(happyDownstreamRequestParamsQuery, map[string]string{"client_id": "bogus"}).Encode()).
|
||||
Build(t, happyStateCodec),
|
||||
).String(),
|
||||
csrfCookie: happyCSRFCookie,
|
||||
wantStatus: http.StatusBadRequest,
|
||||
wantContentType: htmlContentType,
|
||||
wantBody: "Bad Request: error using state downstream auth params\n",
|
||||
},
|
||||
{
|
||||
name: "dynamic clients do not allow response_mode=form_post",
|
||||
idps: oidctestutil.NewUpstreamIDPListerBuilder().WithOIDC(happyUpstream().Build()),
|
||||
kubeResources: addFullyCapableDynamicClientAndSecretToKubeResources,
|
||||
method: http.MethodGet,
|
||||
path: newRequestPath().WithState(
|
||||
happyUpstreamStateParam().WithAuthorizeRequestParams(
|
||||
shallowCopyAndModifyQuery(
|
||||
happyDownstreamRequestParamsQuery,
|
||||
map[string]string{
|
||||
"client_id": downstreamDynamicClientID,
|
||||
"response_mode": "form_post",
|
||||
"scope": "openid",
|
||||
},
|
||||
).Encode(),
|
||||
).Build(t, happyStateCodec),
|
||||
).String(),
|
||||
csrfCookie: happyCSRFCookie,
|
||||
wantStatus: http.StatusBadRequest,
|
||||
wantContentType: htmlContentType,
|
||||
wantBody: "Bad Request: error using state downstream auth params\n",
|
||||
},
|
||||
{
|
||||
name: "state's downstream auth params does not contain openid scope",
|
||||
idps: oidctestutil.NewUpstreamIDPListerBuilder().WithOIDC(happyUpstream().Build()),
|
||||
@@ -733,6 +822,7 @@ func TestCallbackEndpoint(t *testing.T) {
|
||||
wantDownstreamGrantedScopes: []string{"groups"},
|
||||
wantDownstreamIDTokenGroups: oidcUpstreamGroupMembership,
|
||||
wantDownstreamNonce: downstreamNonce,
|
||||
wantDownstreamClientID: downstreamPinnipedClientID,
|
||||
wantDownstreamPKCEChallenge: downstreamPKCEChallenge,
|
||||
wantDownstreamPKCEChallengeMethod: downstreamPKCEChallengeMethod,
|
||||
wantDownstreamCustomSessionData: happyDownstreamCustomSessionData,
|
||||
@@ -759,6 +849,7 @@ func TestCallbackEndpoint(t *testing.T) {
|
||||
wantDownstreamRequestedScopes: []string{"profile", "email"},
|
||||
wantDownstreamGrantedScopes: []string{},
|
||||
wantDownstreamNonce: downstreamNonce,
|
||||
wantDownstreamClientID: downstreamPinnipedClientID,
|
||||
wantDownstreamPKCEChallenge: downstreamPKCEChallenge,
|
||||
wantDownstreamPKCEChallengeMethod: downstreamPKCEChallengeMethod,
|
||||
wantDownstreamCustomSessionData: happyDownstreamCustomSessionData,
|
||||
@@ -786,6 +877,7 @@ func TestCallbackEndpoint(t *testing.T) {
|
||||
wantDownstreamGrantedScopes: []string{"openid", "offline_access", "groups"},
|
||||
wantDownstreamIDTokenGroups: oidcUpstreamGroupMembership,
|
||||
wantDownstreamNonce: downstreamNonce,
|
||||
wantDownstreamClientID: downstreamPinnipedClientID,
|
||||
wantDownstreamPKCEChallenge: downstreamPKCEChallenge,
|
||||
wantDownstreamPKCEChallengeMethod: downstreamPKCEChallengeMethod,
|
||||
wantDownstreamCustomSessionData: happyDownstreamCustomSessionData,
|
||||
@@ -884,6 +976,7 @@ func TestCallbackEndpoint(t *testing.T) {
|
||||
wantDownstreamGrantedScopes: happyDownstreamScopesGranted,
|
||||
wantDownstreamIDTokenGroups: []string{},
|
||||
wantDownstreamNonce: downstreamNonce,
|
||||
wantDownstreamClientID: downstreamPinnipedClientID,
|
||||
wantDownstreamPKCEChallenge: downstreamPKCEChallenge,
|
||||
wantDownstreamPKCEChallengeMethod: downstreamPKCEChallengeMethod,
|
||||
wantDownstreamCustomSessionData: happyDownstreamCustomSessionData,
|
||||
@@ -1139,7 +1232,7 @@ func TestCallbackEndpoint(t *testing.T) {
|
||||
test.wantDownstreamPKCEChallenge,
|
||||
test.wantDownstreamPKCEChallengeMethod,
|
||||
test.wantDownstreamNonce,
|
||||
downstreamClientID,
|
||||
test.wantDownstreamClientID,
|
||||
downstreamRedirectURI,
|
||||
test.wantDownstreamCustomSessionData,
|
||||
)
|
||||
@@ -1166,7 +1259,7 @@ func TestCallbackEndpoint(t *testing.T) {
|
||||
test.wantDownstreamPKCEChallenge,
|
||||
test.wantDownstreamPKCEChallengeMethod,
|
||||
test.wantDownstreamNonce,
|
||||
downstreamClientID,
|
||||
test.wantDownstreamClientID,
|
||||
downstreamRedirectURI,
|
||||
test.wantDownstreamCustomSessionData,
|
||||
)
|
||||
@@ -1237,6 +1330,12 @@ func happyUpstreamStateParam() *oidctestutil.UpstreamStateParamBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
func happyUpstreamStateParamForDynamicClient() *oidctestutil.UpstreamStateParamBuilder {
|
||||
p := happyUpstreamStateParam()
|
||||
p.P = happyDownstreamRequestParamsForDynamicClient
|
||||
return p
|
||||
}
|
||||
|
||||
func happyUpstream() *oidctestutil.TestUpstreamOIDCIdentityProviderBuilder {
|
||||
return oidctestutil.NewTestUpstreamOIDCIdentityProviderBuilder().
|
||||
WithName(happyUpstreamIDPName).
|
||||
|
||||
Reference in New Issue
Block a user