diff --git a/internal/federationdomain/endpoints/callback/callback_handler_test.go b/internal/federationdomain/endpoints/callback/callback_handler_test.go
index 4968f41bd..aee21533b 100644
--- a/internal/federationdomain/endpoints/callback/callback_handler_test.go
+++ b/internal/federationdomain/endpoints/callback/callback_handler_test.go
@@ -18,7 +18,6 @@ import (
"github.com/stretchr/testify/require"
"golang.org/x/crypto/bcrypt"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
- "k8s.io/apimachinery/pkg/types"
"k8s.io/client-go/kubernetes/fake"
configv1alpha1 "go.pinniped.dev/generated/latest/apis/supervisor/config/v1alpha1"
@@ -39,8 +38,9 @@ import (
)
const (
- happyUpstreamIDPName = "upstream-idp-name"
- happyUpstreamIDPResourceUID = "upstream-uid"
+ // Upstream OIDC
+ happyOIDCUpstreamIDPName = "upstream-oidc-idp-name"
+ happyOIDCUpstreamIDPResourceUID = "upstream-oidc-resource-uid"
oidcUpstreamIssuer = "https://my-upstream-issuer.com"
oidcUpstreamRefreshToken = "test-refresh-token"
@@ -52,12 +52,18 @@ const (
oidcUpstreamUsernameClaim = "the-user-claim"
oidcUpstreamGroupsClaim = "the-groups-claim"
+ // Upstream GitHub
+ happyGithubIDPName = "upstream-github-idp-name"
+ happyGithubIDPResourceUID = "upstream-github-idp-resource-uid"
+
+ // Upstream OAuth2 (OIDC or GitHub)
happyUpstreamAuthcode = "upstream-auth-code"
happyUpstreamRedirectURI = "https://example.com/callback"
+ // Downstream parameters
happyDownstreamState = "8b-state"
happyDownstreamCSRF = "test-csrf"
- happyDownstreamPKCE = "test-pkce"
+ happyDownstreamPKCEVerifier = "test-pkce"
happyDownstreamNonce = "test-nonce"
happyDownstreamStateVersion = "2"
@@ -77,11 +83,9 @@ const (
)
var (
- githubIDPName = "upstream-github-idp-name"
- githubIDPResourceUID = types.UID("upstream-github-idp-resource-uid")
githubUpstreamUsername = "some-github-login"
githubUpstreamGroups = []string{"org1/team1", "org2/team2"}
- githubDownstreamSubject = fmt.Sprintf("https://github.com?idpName=%s&sub=%s", githubIDPName, githubUpstreamUsername)
+ githubDownstreamSubject = fmt.Sprintf("https://github.com?idpName=%s&sub=%s", happyGithubIDPName, githubUpstreamUsername)
githubUpstreamAccessToken = "some-opaque-access-token-from-github" //nolint:gosec // this is not a credential
oidcUpstreamGroupMembership = []string{"test-pinniped-group-0", "test-pinniped-group-1"}
@@ -109,8 +113,8 @@ var (
Username: oidcUpstreamUsername,
UpstreamUsername: oidcUpstreamUsername,
UpstreamGroups: oidcUpstreamGroupMembership,
- ProviderUID: happyUpstreamIDPResourceUID,
- ProviderName: happyUpstreamIDPName,
+ ProviderUID: happyOIDCUpstreamIDPResourceUID,
+ ProviderName: happyOIDCUpstreamIDPName,
ProviderType: psession.ProviderTypeOIDC,
OIDC: &psession.OIDCSessionData{
UpstreamRefreshToken: oidcUpstreamRefreshToken,
@@ -131,8 +135,8 @@ var (
Username: oidcUpstreamUsername,
UpstreamUsername: oidcUpstreamUsername,
UpstreamGroups: oidcUpstreamGroupMembership,
- ProviderUID: happyUpstreamIDPResourceUID,
- ProviderName: happyUpstreamIDPName,
+ ProviderUID: happyOIDCUpstreamIDPResourceUID,
+ ProviderName: happyOIDCUpstreamIDPName,
ProviderType: psession.ProviderTypeOIDC,
OIDC: &psession.OIDCSessionData{
UpstreamAccessToken: oidcUpstreamAccessToken,
@@ -144,8 +148,8 @@ var (
Username: githubUpstreamUsername,
UpstreamUsername: githubUpstreamUsername,
UpstreamGroups: githubUpstreamGroups,
- ProviderUID: githubIDPResourceUID,
- ProviderName: githubIDPName,
+ ProviderUID: happyGithubIDPResourceUID,
+ ProviderName: happyGithubIDPName,
ProviderType: psession.ProviderTypeGitHub,
GitHub: &psession.GitHubSessionData{
UpstreamAccessToken: githubUpstreamAccessToken,
@@ -153,14 +157,6 @@ var (
}
)
-func happyGitHubUpstream() *oidctestutil.TestUpstreamGitHubIdentityProviderBuilder {
- return oidctestutil.NewTestUpstreamGitHubIdentityProviderBuilder().
- WithName(githubIDPName).
- WithResourceUID(githubIDPResourceUID).
- WithClientID("some-client-id").
- WithScopes([]string{"these", "scopes", "appear", "unused"})
-}
-
func TestCallbackEndpoint(t *testing.T) {
require.Len(t, happyDownstreamState, 8, "we expect fosite to allow 8 byte state params, so we want to test that boundary case")
@@ -182,21 +178,21 @@ func TestCallbackEndpoint(t *testing.T) {
var happyCookieCodec = securecookie.New(cookieEncoderHashKey, cookieEncoderBlockKey)
happyCookieCodec.SetSerializer(securecookie.JSONEncoder{})
- happyState := happyUpstreamStateParam().Build(t, happyStateCodec)
- happyStateForDynamicClient := happyUpstreamStateParamForDynamicClient().Build(t, happyStateCodec)
+ happyState := happyOIDCUpstreamStateParam().Build(t, happyStateCodec)
+ happyStateForDynamicClient := happyOIDCUpstreamStateParamForDynamicClient().Build(t, happyStateCodec)
encodedIncomingCookieCSRFValue, err := happyCookieCodec.Encode("csrf", happyDownstreamCSRF)
require.NoError(t, err)
happyCSRFCookie := "__Host-pinniped-csrf=" + encodedIncomingCookieCSRFValue
- happyExchangeAndValidateTokensArgs := &oidctestutil.ExchangeAuthcodeAndValidateTokenArgs{
+ happyOIDCUpstreamExchangeAuthcodeAndValidateTokenArgs := &oidctestutil.ExchangeAuthcodeAndValidateTokenArgs{
Authcode: happyUpstreamAuthcode,
- PKCECodeVerifier: oidcpkce.Code(happyDownstreamPKCE),
- ExpectedIDTokenNonce: nonce.Nonce(happyDownstreamNonce),
RedirectURI: happyUpstreamRedirectURI,
+ PKCECodeVerifier: oidcpkce.Code(happyDownstreamPKCEVerifier),
+ ExpectedIDTokenNonce: nonce.Nonce(happyDownstreamNonce),
}
- happyGitHubExchangeAuthcodeArgs := &oidctestutil.ExchangeAuthcodeArgs{
+ happyGitHubUpstreamExchangeAuthcodeArgs := &oidctestutil.ExchangeAuthcodeArgs{
Authcode: happyUpstreamAuthcode,
RedirectURI: happyUpstreamRedirectURI,
}
@@ -245,10 +241,10 @@ func TestCallbackEndpoint(t *testing.T) {
}{
{
name: "GET with good state and cookie and successful upstream token exchange with response_mode=form_post returns 200 with HTML+JS form",
- idps: testidplister.NewUpstreamIDPListerBuilder().WithOIDC(happyUpstream().Build()),
+ idps: testidplister.NewUpstreamIDPListerBuilder().WithOIDC(happyOIDCUpstream().Build()),
method: http.MethodGet,
path: newRequestPath().WithState(
- happyUpstreamStateParam().WithAuthorizeRequestParams(
+ happyOIDCUpstreamStateParam().WithAuthorizeRequestParams(
shallowCopyAndModifyQuery(
happyDownstreamRequestParamsQuery,
map[string]string{"response_mode": "form_post"},
@@ -259,7 +255,7 @@ func TestCallbackEndpoint(t *testing.T) {
wantStatus: http.StatusOK,
wantContentType: "text/html;charset=UTF-8",
wantBodyFormResponseRegexp: `(.+)`,
- wantDownstreamIDTokenSubject: oidcUpstreamIssuer + "?idpName=" + happyUpstreamIDPName + "&sub=" + oidcUpstreamSubjectQueryEscaped,
+ wantDownstreamIDTokenSubject: oidcUpstreamIssuer + "?idpName=" + happyOIDCUpstreamIDPName + "&sub=" + oidcUpstreamSubjectQueryEscaped,
wantDownstreamIDTokenUsername: oidcUpstreamUsername,
wantDownstreamIDTokenGroups: oidcUpstreamGroupMembership,
wantDownstreamRequestedScopes: happyDownstreamScopesRequested,
@@ -270,13 +266,13 @@ func TestCallbackEndpoint(t *testing.T) {
wantDownstreamPKCEChallengeMethod: downstreamPKCEChallengeMethod,
wantDownstreamCustomSessionData: happyDownstreamCustomSessionData,
wantOIDCAuthcodeExchangeCall: &expectedOIDCAuthcodeExchange{
- performedByUpstreamName: happyUpstreamIDPName,
- args: happyExchangeAndValidateTokensArgs,
+ performedByUpstreamName: happyOIDCUpstreamIDPName,
+ args: happyOIDCUpstreamExchangeAuthcodeAndValidateTokenArgs,
},
},
{
name: "GET with good state and cookie with additional params",
- idps: testidplister.NewUpstreamIDPListerBuilder().WithOIDC(happyUpstream().
+ idps: testidplister.NewUpstreamIDPListerBuilder().WithOIDC(happyOIDCUpstream().
WithAdditionalClaimMappings(map[string]string{
"downstreamCustomClaim": "upstreamCustomClaim",
"downstreamOtherClaim": "upstreamOtherClaim",
@@ -287,7 +283,7 @@ func TestCallbackEndpoint(t *testing.T) {
Build()),
method: http.MethodGet,
path: newRequestPath().WithState(
- happyUpstreamStateParam().WithAuthorizeRequestParams(
+ happyOIDCUpstreamStateParam().WithAuthorizeRequestParams(
shallowCopyAndModifyQuery(
happyDownstreamRequestParamsQuery,
map[string]string{"response_mode": "form_post"},
@@ -298,7 +294,7 @@ func TestCallbackEndpoint(t *testing.T) {
wantStatus: http.StatusOK,
wantContentType: "text/html;charset=UTF-8",
wantBodyFormResponseRegexp: `(.+)`,
- wantDownstreamIDTokenSubject: oidcUpstreamIssuer + "?idpName=" + happyUpstreamIDPName + "&sub=" + oidcUpstreamSubjectQueryEscaped,
+ wantDownstreamIDTokenSubject: oidcUpstreamIssuer + "?idpName=" + happyOIDCUpstreamIDPName + "&sub=" + oidcUpstreamSubjectQueryEscaped,
wantDownstreamIDTokenUsername: oidcUpstreamUsername,
wantDownstreamIDTokenGroups: oidcUpstreamGroupMembership,
wantDownstreamRequestedScopes: happyDownstreamScopesRequested,
@@ -309,8 +305,8 @@ func TestCallbackEndpoint(t *testing.T) {
wantDownstreamPKCEChallengeMethod: downstreamPKCEChallengeMethod,
wantDownstreamCustomSessionData: happyDownstreamCustomSessionData,
wantOIDCAuthcodeExchangeCall: &expectedOIDCAuthcodeExchange{
- performedByUpstreamName: happyUpstreamIDPName,
- args: happyExchangeAndValidateTokensArgs,
+ performedByUpstreamName: happyOIDCUpstreamIDPName,
+ args: happyOIDCUpstreamExchangeAuthcodeAndValidateTokenArgs,
},
wantDownstreamAdditionalClaims: map[string]interface{}{
"downstreamCustomClaim": "i am a claim value",
@@ -319,14 +315,14 @@ func TestCallbackEndpoint(t *testing.T) {
},
{
name: "GET with good state and cookie and successful upstream token exchange returns 303 to downstream client callback with its state and code",
- idps: testidplister.NewUpstreamIDPListerBuilder().WithOIDC(happyUpstream().Build()),
+ idps: testidplister.NewUpstreamIDPListerBuilder().WithOIDC(happyOIDCUpstream().Build()),
method: http.MethodGet,
path: newRequestPath().WithState(happyState).String(),
csrfCookie: happyCSRFCookie,
wantStatus: http.StatusSeeOther,
wantRedirectLocationRegexp: happyDownstreamRedirectLocationRegexp,
wantBody: "",
- wantDownstreamIDTokenSubject: oidcUpstreamIssuer + "?idpName=" + happyUpstreamIDPName + "&sub=" + oidcUpstreamSubjectQueryEscaped,
+ wantDownstreamIDTokenSubject: oidcUpstreamIssuer + "?idpName=" + happyOIDCUpstreamIDPName + "&sub=" + oidcUpstreamSubjectQueryEscaped,
wantDownstreamIDTokenUsername: oidcUpstreamUsername,
wantDownstreamIDTokenGroups: oidcUpstreamGroupMembership,
wantDownstreamRequestedScopes: happyDownstreamScopesRequested,
@@ -337,13 +333,13 @@ func TestCallbackEndpoint(t *testing.T) {
wantDownstreamPKCEChallengeMethod: downstreamPKCEChallengeMethod,
wantDownstreamCustomSessionData: happyDownstreamCustomSessionData,
wantOIDCAuthcodeExchangeCall: &expectedOIDCAuthcodeExchange{
- performedByUpstreamName: happyUpstreamIDPName,
- args: happyExchangeAndValidateTokensArgs,
+ performedByUpstreamName: happyOIDCUpstreamIDPName,
+ args: happyOIDCUpstreamExchangeAuthcodeAndValidateTokenArgs,
},
},
{
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: testidplister.NewUpstreamIDPListerBuilder().WithOIDC(happyUpstream().Build()),
+ idps: testidplister.NewUpstreamIDPListerBuilder().WithOIDC(happyOIDCUpstream().Build()),
kubeResources: addFullyCapableDynamicClientAndSecretToKubeResources,
method: http.MethodGet,
path: newRequestPath().WithState(happyStateForDynamicClient).String(),
@@ -351,7 +347,7 @@ func TestCallbackEndpoint(t *testing.T) {
wantStatus: http.StatusSeeOther,
wantRedirectLocationRegexp: happyDownstreamRedirectLocationRegexp,
wantBody: "",
- wantDownstreamIDTokenSubject: oidcUpstreamIssuer + "?idpName=" + happyUpstreamIDPName + "&sub=" + oidcUpstreamSubjectQueryEscaped,
+ wantDownstreamIDTokenSubject: oidcUpstreamIssuer + "?idpName=" + happyOIDCUpstreamIDPName + "&sub=" + oidcUpstreamSubjectQueryEscaped,
wantDownstreamIDTokenUsername: oidcUpstreamUsername,
wantDownstreamIDTokenGroups: oidcUpstreamGroupMembership,
wantDownstreamRequestedScopes: happyDownstreamScopesRequested,
@@ -362,20 +358,20 @@ func TestCallbackEndpoint(t *testing.T) {
wantDownstreamPKCEChallengeMethod: downstreamPKCEChallengeMethod,
wantDownstreamCustomSessionData: happyDownstreamCustomSessionData,
wantOIDCAuthcodeExchangeCall: &expectedOIDCAuthcodeExchange{
- performedByUpstreamName: happyUpstreamIDPName,
- args: happyExchangeAndValidateTokensArgs,
+ performedByUpstreamName: happyOIDCUpstreamIDPName,
+ args: happyOIDCUpstreamExchangeAuthcodeAndValidateTokenArgs,
},
},
{
name: "GET with authcode exchange that returns an access token but no refresh token when there is a userinfo endpoint returns 303 to downstream client callback with its state and code",
- idps: testidplister.NewUpstreamIDPListerBuilder().WithOIDC(happyUpstream().WithEmptyRefreshToken().WithAccessToken(oidcUpstreamAccessToken, metav1.NewTime(time.Now().Add(9*time.Hour))).WithUserInfoURL().Build()),
+ idps: testidplister.NewUpstreamIDPListerBuilder().WithOIDC(happyOIDCUpstream().WithEmptyRefreshToken().WithAccessToken(oidcUpstreamAccessToken, metav1.NewTime(time.Now().Add(9*time.Hour))).WithUserInfoURL().Build()),
method: http.MethodGet,
path: newRequestPath().WithState(happyState).String(),
csrfCookie: happyCSRFCookie,
wantStatus: http.StatusSeeOther,
wantRedirectLocationRegexp: happyDownstreamRedirectLocationRegexp,
wantBody: "",
- wantDownstreamIDTokenSubject: oidcUpstreamIssuer + "?idpName=" + happyUpstreamIDPName + "&sub=" + oidcUpstreamSubjectQueryEscaped,
+ wantDownstreamIDTokenSubject: oidcUpstreamIssuer + "?idpName=" + happyOIDCUpstreamIDPName + "&sub=" + oidcUpstreamSubjectQueryEscaped,
wantDownstreamIDTokenUsername: oidcUpstreamUsername,
wantDownstreamIDTokenGroups: oidcUpstreamGroupMembership,
wantDownstreamRequestedScopes: happyDownstreamScopesRequested,
@@ -386,16 +382,16 @@ func TestCallbackEndpoint(t *testing.T) {
wantDownstreamPKCEChallengeMethod: downstreamPKCEChallengeMethod,
wantDownstreamCustomSessionData: happyDownstreamAccessTokenCustomSessionData,
wantOIDCAuthcodeExchangeCall: &expectedOIDCAuthcodeExchange{
- performedByUpstreamName: happyUpstreamIDPName,
- args: happyExchangeAndValidateTokensArgs,
+ performedByUpstreamName: happyOIDCUpstreamIDPName,
+ args: happyOIDCUpstreamExchangeAuthcodeAndValidateTokenArgs,
},
},
{
name: "form_post happy path without username or groups scopes requested",
- idps: testidplister.NewUpstreamIDPListerBuilder().WithOIDC(happyUpstream().Build()),
+ idps: testidplister.NewUpstreamIDPListerBuilder().WithOIDC(happyOIDCUpstream().Build()),
method: http.MethodGet,
path: newRequestPath().WithState(
- happyUpstreamStateParam().WithAuthorizeRequestParams(
+ happyOIDCUpstreamStateParam().WithAuthorizeRequestParams(
shallowCopyAndModifyQuery(
happyDownstreamRequestParamsQuery,
map[string]string{
@@ -409,7 +405,7 @@ func TestCallbackEndpoint(t *testing.T) {
wantStatus: http.StatusOK,
wantContentType: "text/html;charset=UTF-8",
wantBodyFormResponseRegexp: `(.+)`,
- wantDownstreamIDTokenSubject: oidcUpstreamIssuer + "?idpName=" + happyUpstreamIDPName + "&sub=" + oidcUpstreamSubjectQueryEscaped,
+ wantDownstreamIDTokenSubject: oidcUpstreamIssuer + "?idpName=" + happyOIDCUpstreamIDPName + "&sub=" + oidcUpstreamSubjectQueryEscaped,
wantDownstreamIDTokenUsername: oidcUpstreamUsername,
wantDownstreamRequestedScopes: []string{"openid"},
wantDownstreamIDTokenGroups: oidcUpstreamGroupMembership,
@@ -421,20 +417,20 @@ func TestCallbackEndpoint(t *testing.T) {
wantDownstreamPKCEChallengeMethod: downstreamPKCEChallengeMethod,
wantDownstreamCustomSessionData: happyDownstreamCustomSessionData,
wantOIDCAuthcodeExchangeCall: &expectedOIDCAuthcodeExchange{
- performedByUpstreamName: happyUpstreamIDPName,
- args: happyExchangeAndValidateTokensArgs,
+ performedByUpstreamName: happyOIDCUpstreamIDPName,
+ args: happyOIDCUpstreamExchangeAuthcodeAndValidateTokenArgs,
},
},
{
name: "GET with authcode exchange that returns an access token but no refresh token but has a short token lifetime which is stored as a warning in the session",
- idps: testidplister.NewUpstreamIDPListerBuilder().WithOIDC(happyUpstream().WithEmptyRefreshToken().WithAccessToken(oidcUpstreamAccessToken, metav1.NewTime(time.Now().Add(1*time.Hour))).WithUserInfoURL().Build()),
+ idps: testidplister.NewUpstreamIDPListerBuilder().WithOIDC(happyOIDCUpstream().WithEmptyRefreshToken().WithAccessToken(oidcUpstreamAccessToken, metav1.NewTime(time.Now().Add(1*time.Hour))).WithUserInfoURL().Build()),
method: http.MethodGet,
path: newRequestPath().WithState(happyState).String(),
csrfCookie: happyCSRFCookie,
wantStatus: http.StatusSeeOther,
wantRedirectLocationRegexp: happyDownstreamRedirectLocationRegexp,
wantBody: "",
- wantDownstreamIDTokenSubject: oidcUpstreamIssuer + "?idpName=" + happyUpstreamIDPName + "&sub=" + oidcUpstreamSubjectQueryEscaped,
+ wantDownstreamIDTokenSubject: oidcUpstreamIssuer + "?idpName=" + happyOIDCUpstreamIDPName + "&sub=" + oidcUpstreamSubjectQueryEscaped,
wantDownstreamIDTokenUsername: oidcUpstreamUsername,
wantDownstreamIDTokenGroups: oidcUpstreamGroupMembership,
wantDownstreamRequestedScopes: happyDownstreamScopesRequested,
@@ -447,8 +443,8 @@ func TestCallbackEndpoint(t *testing.T) {
Username: oidcUpstreamUsername,
UpstreamUsername: oidcUpstreamUsername,
UpstreamGroups: oidcUpstreamGroupMembership,
- ProviderUID: happyUpstreamIDPResourceUID,
- ProviderName: happyUpstreamIDPName,
+ ProviderUID: happyOIDCUpstreamIDPResourceUID,
+ ProviderName: happyOIDCUpstreamIDPName,
ProviderType: psession.ProviderTypeOIDC,
Warnings: []string{"Access token from identity provider has lifetime of less than 3 hours. Expect frequent prompts to log in."},
OIDC: &psession.OIDCSessionData{
@@ -458,14 +454,14 @@ func TestCallbackEndpoint(t *testing.T) {
},
},
wantOIDCAuthcodeExchangeCall: &expectedOIDCAuthcodeExchange{
- performedByUpstreamName: happyUpstreamIDPName,
- args: happyExchangeAndValidateTokensArgs,
+ performedByUpstreamName: happyOIDCUpstreamIDPName,
+ args: happyOIDCUpstreamExchangeAuthcodeAndValidateTokenArgs,
},
},
{
name: "upstream IDP provides no username or group claim configuration, so we use default username claim and skip groups",
idps: testidplister.NewUpstreamIDPListerBuilder().WithOIDC(
- happyUpstream().WithoutUsernameClaim().WithoutGroupsClaim().Build(),
+ happyOIDCUpstream().WithoutUsernameClaim().WithoutGroupsClaim().Build(),
),
method: http.MethodGet,
path: newRequestPath().WithState(happyState).String(),
@@ -473,7 +469,7 @@ func TestCallbackEndpoint(t *testing.T) {
wantStatus: http.StatusSeeOther,
wantRedirectLocationRegexp: happyDownstreamRedirectLocationRegexp,
wantBody: "",
- wantDownstreamIDTokenSubject: oidcUpstreamIssuer + "?idpName=" + happyUpstreamIDPName + "&sub=" + oidcUpstreamSubjectQueryEscaped,
+ wantDownstreamIDTokenSubject: oidcUpstreamIssuer + "?idpName=" + happyOIDCUpstreamIDPName + "&sub=" + oidcUpstreamSubjectQueryEscaped,
wantDownstreamIDTokenUsername: oidcUpstreamIssuer + "?sub=" + oidcUpstreamSubjectQueryEscaped,
wantDownstreamIDTokenGroups: []string{},
wantDownstreamRequestedScopes: happyDownstreamScopesRequested,
@@ -488,14 +484,14 @@ func TestCallbackEndpoint(t *testing.T) {
nil,
),
wantOIDCAuthcodeExchangeCall: &expectedOIDCAuthcodeExchange{
- performedByUpstreamName: happyUpstreamIDPName,
- args: happyExchangeAndValidateTokensArgs,
+ performedByUpstreamName: happyOIDCUpstreamIDPName,
+ args: happyOIDCUpstreamExchangeAuthcodeAndValidateTokenArgs,
},
},
{
name: "upstream IDP configures username claim as special claim `email` and `email_verified` upstream claim is missing",
idps: testidplister.NewUpstreamIDPListerBuilder().WithOIDC(
- happyUpstream().WithUsernameClaim("email").WithIDTokenClaim("email", "joe@whitehouse.gov").Build(),
+ happyOIDCUpstream().WithUsernameClaim("email").WithIDTokenClaim("email", "joe@whitehouse.gov").Build(),
),
method: http.MethodGet,
path: newRequestPath().WithState(happyState).String(),
@@ -503,7 +499,7 @@ func TestCallbackEndpoint(t *testing.T) {
wantStatus: http.StatusSeeOther,
wantRedirectLocationRegexp: happyDownstreamRedirectLocationRegexp,
wantBody: "",
- wantDownstreamIDTokenSubject: oidcUpstreamIssuer + "?idpName=" + happyUpstreamIDPName + "&sub=" + oidcUpstreamSubjectQueryEscaped,
+ wantDownstreamIDTokenSubject: oidcUpstreamIssuer + "?idpName=" + happyOIDCUpstreamIDPName + "&sub=" + oidcUpstreamSubjectQueryEscaped,
wantDownstreamIDTokenUsername: "joe@whitehouse.gov",
wantDownstreamIDTokenGroups: oidcUpstreamGroupMembership,
wantDownstreamRequestedScopes: happyDownstreamScopesRequested,
@@ -518,14 +514,14 @@ func TestCallbackEndpoint(t *testing.T) {
oidcUpstreamGroupMembership,
),
wantOIDCAuthcodeExchangeCall: &expectedOIDCAuthcodeExchange{
- performedByUpstreamName: happyUpstreamIDPName,
- args: happyExchangeAndValidateTokensArgs,
+ performedByUpstreamName: happyOIDCUpstreamIDPName,
+ args: happyOIDCUpstreamExchangeAuthcodeAndValidateTokenArgs,
},
},
{
name: "upstream IDP configures username claim as special claim `email` and `email_verified` upstream claim is present with true value",
idps: testidplister.NewUpstreamIDPListerBuilder().WithOIDC(
- happyUpstream().WithUsernameClaim("email").
+ happyOIDCUpstream().WithUsernameClaim("email").
WithIDTokenClaim("email", "joe@whitehouse.gov").
WithIDTokenClaim("email_verified", true).Build(),
),
@@ -535,7 +531,7 @@ func TestCallbackEndpoint(t *testing.T) {
wantStatus: http.StatusSeeOther,
wantRedirectLocationRegexp: happyDownstreamRedirectLocationRegexp,
wantBody: "",
- wantDownstreamIDTokenSubject: oidcUpstreamIssuer + "?idpName=" + happyUpstreamIDPName + "&sub=" + oidcUpstreamSubjectQueryEscaped,
+ wantDownstreamIDTokenSubject: oidcUpstreamIssuer + "?idpName=" + happyOIDCUpstreamIDPName + "&sub=" + oidcUpstreamSubjectQueryEscaped,
wantDownstreamIDTokenUsername: "joe@whitehouse.gov",
wantDownstreamIDTokenGroups: oidcUpstreamGroupMembership,
wantDownstreamRequestedScopes: happyDownstreamScopesRequested,
@@ -550,14 +546,14 @@ func TestCallbackEndpoint(t *testing.T) {
oidcUpstreamGroupMembership,
),
wantOIDCAuthcodeExchangeCall: &expectedOIDCAuthcodeExchange{
- performedByUpstreamName: happyUpstreamIDPName,
- args: happyExchangeAndValidateTokensArgs,
+ performedByUpstreamName: happyOIDCUpstreamIDPName,
+ args: happyOIDCUpstreamExchangeAuthcodeAndValidateTokenArgs,
},
},
{
name: "upstream IDP configures username claim as anything other than special claim `email` and `email_verified` upstream claim is present with false value",
idps: testidplister.NewUpstreamIDPListerBuilder().WithOIDC(
- happyUpstream().WithUsernameClaim("some-claim").
+ happyOIDCUpstream().WithUsernameClaim("some-claim").
WithIDTokenClaim("some-claim", "joe").
WithIDTokenClaim("email", "joe@whitehouse.gov").
WithIDTokenClaim("email_verified", false).Build(),
@@ -568,7 +564,7 @@ func TestCallbackEndpoint(t *testing.T) {
wantStatus: http.StatusSeeOther, // succeed despite `email_verified=false` because we're not using the email claim for anything
wantRedirectLocationRegexp: happyDownstreamRedirectLocationRegexp,
wantBody: "",
- wantDownstreamIDTokenSubject: oidcUpstreamIssuer + "?idpName=" + happyUpstreamIDPName + "&sub=" + oidcUpstreamSubjectQueryEscaped,
+ wantDownstreamIDTokenSubject: oidcUpstreamIssuer + "?idpName=" + happyOIDCUpstreamIDPName + "&sub=" + oidcUpstreamSubjectQueryEscaped,
wantDownstreamIDTokenUsername: "joe",
wantDownstreamIDTokenGroups: oidcUpstreamGroupMembership,
wantDownstreamRequestedScopes: happyDownstreamScopesRequested,
@@ -583,13 +579,13 @@ func TestCallbackEndpoint(t *testing.T) {
oidcUpstreamGroupMembership,
),
wantOIDCAuthcodeExchangeCall: &expectedOIDCAuthcodeExchange{
- performedByUpstreamName: happyUpstreamIDPName,
- args: happyExchangeAndValidateTokensArgs,
+ performedByUpstreamName: happyOIDCUpstreamIDPName,
+ args: happyOIDCUpstreamExchangeAuthcodeAndValidateTokenArgs,
},
},
{
name: "upstream IDP configures username claim as special claim `email` and `email_verified` upstream claim is present with illegal value",
- idps: testidplister.NewUpstreamIDPListerBuilder().WithOIDC(happyUpstream().WithUsernameClaim("email").
+ idps: testidplister.NewUpstreamIDPListerBuilder().WithOIDC(happyOIDCUpstream().WithUsernameClaim("email").
WithIDTokenClaim("email", "joe@whitehouse.gov").
WithIDTokenClaim("email_verified", "supposed to be boolean").Build(),
),
@@ -600,13 +596,13 @@ func TestCallbackEndpoint(t *testing.T) {
wantContentType: htmlContentType,
wantBody: "Unprocessable Entity: email_verified claim in upstream ID token has invalid format\n",
wantOIDCAuthcodeExchangeCall: &expectedOIDCAuthcodeExchange{
- performedByUpstreamName: happyUpstreamIDPName,
- args: happyExchangeAndValidateTokensArgs,
+ performedByUpstreamName: happyOIDCUpstreamIDPName,
+ args: happyOIDCUpstreamExchangeAuthcodeAndValidateTokenArgs,
},
},
{
name: "return an error when upstream IDP returned no refresh token with an access token when there is no userinfo endpoint",
- idps: testidplister.NewUpstreamIDPListerBuilder().WithOIDC(happyUpstream().WithoutRefreshToken().WithAccessToken(oidcUpstreamAccessToken, metav1.NewTime(time.Now().Add(9*time.Hour))).WithoutUserInfoURL().Build()),
+ idps: testidplister.NewUpstreamIDPListerBuilder().WithOIDC(happyOIDCUpstream().WithoutRefreshToken().WithAccessToken(oidcUpstreamAccessToken, metav1.NewTime(time.Now().Add(9*time.Hour))).WithoutUserInfoURL().Build()),
method: http.MethodGet,
path: newRequestPath().WithState(happyState).String(),
csrfCookie: happyCSRFCookie,
@@ -614,13 +610,13 @@ func TestCallbackEndpoint(t *testing.T) {
wantContentType: htmlContentType,
wantBody: "Unprocessable Entity: access token was returned by upstream provider but there was no userinfo endpoint\n",
wantOIDCAuthcodeExchangeCall: &expectedOIDCAuthcodeExchange{
- performedByUpstreamName: happyUpstreamIDPName,
- args: happyExchangeAndValidateTokensArgs,
+ performedByUpstreamName: happyOIDCUpstreamIDPName,
+ args: happyOIDCUpstreamExchangeAuthcodeAndValidateTokenArgs,
},
},
{
name: "return an error when upstream IDP returned no refresh token and no access token",
- idps: testidplister.NewUpstreamIDPListerBuilder().WithOIDC(happyUpstream().WithoutRefreshToken().WithoutAccessToken().Build()),
+ idps: testidplister.NewUpstreamIDPListerBuilder().WithOIDC(happyOIDCUpstream().WithoutRefreshToken().WithoutAccessToken().Build()),
method: http.MethodGet,
path: newRequestPath().WithState(happyState).String(),
csrfCookie: happyCSRFCookie,
@@ -628,13 +624,13 @@ func TestCallbackEndpoint(t *testing.T) {
wantContentType: htmlContentType,
wantBody: "Unprocessable Entity: neither access token nor refresh token returned by upstream provider\n",
wantOIDCAuthcodeExchangeCall: &expectedOIDCAuthcodeExchange{
- performedByUpstreamName: happyUpstreamIDPName,
- args: happyExchangeAndValidateTokensArgs,
+ performedByUpstreamName: happyOIDCUpstreamIDPName,
+ args: happyOIDCUpstreamExchangeAuthcodeAndValidateTokenArgs,
},
},
{
name: "return an error when upstream IDP returned an empty refresh token and empty access token",
- idps: testidplister.NewUpstreamIDPListerBuilder().WithOIDC(happyUpstream().WithEmptyRefreshToken().WithEmptyAccessToken().Build()),
+ idps: testidplister.NewUpstreamIDPListerBuilder().WithOIDC(happyOIDCUpstream().WithEmptyRefreshToken().WithEmptyAccessToken().Build()),
method: http.MethodGet,
path: newRequestPath().WithState(happyState).String(),
csrfCookie: happyCSRFCookie,
@@ -642,13 +638,13 @@ func TestCallbackEndpoint(t *testing.T) {
wantContentType: htmlContentType,
wantBody: "Unprocessable Entity: neither access token nor refresh token returned by upstream provider\n",
wantOIDCAuthcodeExchangeCall: &expectedOIDCAuthcodeExchange{
- performedByUpstreamName: happyUpstreamIDPName,
- args: happyExchangeAndValidateTokensArgs,
+ performedByUpstreamName: happyOIDCUpstreamIDPName,
+ args: happyOIDCUpstreamExchangeAuthcodeAndValidateTokenArgs,
},
},
{
name: "return an error when upstream IDP returned no refresh token and empty access token",
- idps: testidplister.NewUpstreamIDPListerBuilder().WithOIDC(happyUpstream().WithoutRefreshToken().WithEmptyAccessToken().Build()),
+ idps: testidplister.NewUpstreamIDPListerBuilder().WithOIDC(happyOIDCUpstream().WithoutRefreshToken().WithEmptyAccessToken().Build()),
method: http.MethodGet,
path: newRequestPath().WithState(happyState).String(),
csrfCookie: happyCSRFCookie,
@@ -656,13 +652,13 @@ func TestCallbackEndpoint(t *testing.T) {
wantContentType: htmlContentType,
wantBody: "Unprocessable Entity: neither access token nor refresh token returned by upstream provider\n",
wantOIDCAuthcodeExchangeCall: &expectedOIDCAuthcodeExchange{
- performedByUpstreamName: happyUpstreamIDPName,
- args: happyExchangeAndValidateTokensArgs,
+ performedByUpstreamName: happyOIDCUpstreamIDPName,
+ args: happyOIDCUpstreamExchangeAuthcodeAndValidateTokenArgs,
},
},
{
name: "return an error when upstream IDP returned an empty refresh token and no access token",
- idps: testidplister.NewUpstreamIDPListerBuilder().WithOIDC(happyUpstream().WithEmptyRefreshToken().WithoutAccessToken().Build()),
+ idps: testidplister.NewUpstreamIDPListerBuilder().WithOIDC(happyOIDCUpstream().WithEmptyRefreshToken().WithoutAccessToken().Build()),
method: http.MethodGet,
path: newRequestPath().WithState(happyState).String(),
csrfCookie: happyCSRFCookie,
@@ -670,14 +666,14 @@ func TestCallbackEndpoint(t *testing.T) {
wantContentType: htmlContentType,
wantBody: "Unprocessable Entity: neither access token nor refresh token returned by upstream provider\n",
wantOIDCAuthcodeExchangeCall: &expectedOIDCAuthcodeExchange{
- performedByUpstreamName: happyUpstreamIDPName,
- args: happyExchangeAndValidateTokensArgs,
+ performedByUpstreamName: happyOIDCUpstreamIDPName,
+ args: happyOIDCUpstreamExchangeAuthcodeAndValidateTokenArgs,
},
},
{
name: "upstream IDP configures username claim as special claim `email` and `email_verified` upstream claim is present with false value",
idps: testidplister.NewUpstreamIDPListerBuilder().WithOIDC(
- happyUpstream().WithUsernameClaim("email").
+ happyOIDCUpstream().WithUsernameClaim("email").
WithIDTokenClaim("email", "joe@whitehouse.gov").
WithIDTokenClaim("email_verified", false).Build(),
),
@@ -688,14 +684,14 @@ func TestCallbackEndpoint(t *testing.T) {
wantContentType: htmlContentType,
wantBody: "Unprocessable Entity: email_verified claim in upstream ID token has false value\n",
wantOIDCAuthcodeExchangeCall: &expectedOIDCAuthcodeExchange{
- performedByUpstreamName: happyUpstreamIDPName,
- args: happyExchangeAndValidateTokensArgs,
+ performedByUpstreamName: happyOIDCUpstreamIDPName,
+ args: happyOIDCUpstreamExchangeAuthcodeAndValidateTokenArgs,
},
},
{
name: "upstream IDP provides username claim configuration as `sub`, so the downstream token subject should be exactly what they asked for",
idps: testidplister.NewUpstreamIDPListerBuilder().WithOIDC(
- happyUpstream().WithUsernameClaim("sub").Build(),
+ happyOIDCUpstream().WithUsernameClaim("sub").Build(),
),
method: http.MethodGet,
path: newRequestPath().WithState(happyState).String(),
@@ -703,7 +699,7 @@ func TestCallbackEndpoint(t *testing.T) {
wantStatus: http.StatusSeeOther,
wantRedirectLocationRegexp: happyDownstreamRedirectLocationRegexp,
wantBody: "",
- wantDownstreamIDTokenSubject: oidcUpstreamIssuer + "?idpName=" + happyUpstreamIDPName + "&sub=" + oidcUpstreamSubjectQueryEscaped,
+ wantDownstreamIDTokenSubject: oidcUpstreamIssuer + "?idpName=" + happyOIDCUpstreamIDPName + "&sub=" + oidcUpstreamSubjectQueryEscaped,
wantDownstreamIDTokenUsername: oidcUpstreamSubject,
wantDownstreamIDTokenGroups: oidcUpstreamGroupMembership,
wantDownstreamRequestedScopes: happyDownstreamScopesRequested,
@@ -718,14 +714,14 @@ func TestCallbackEndpoint(t *testing.T) {
oidcUpstreamGroupMembership,
),
wantOIDCAuthcodeExchangeCall: &expectedOIDCAuthcodeExchange{
- performedByUpstreamName: happyUpstreamIDPName,
- args: happyExchangeAndValidateTokensArgs,
+ performedByUpstreamName: happyOIDCUpstreamIDPName,
+ args: happyOIDCUpstreamExchangeAuthcodeAndValidateTokenArgs,
},
},
{
name: "upstream IDP's configured groups claim in the ID token has a non-array value",
idps: testidplister.NewUpstreamIDPListerBuilder().WithOIDC(
- happyUpstream().WithIDTokenClaim(oidcUpstreamGroupsClaim, "notAnArrayGroup1 notAnArrayGroup2").Build(),
+ happyOIDCUpstream().WithIDTokenClaim(oidcUpstreamGroupsClaim, "notAnArrayGroup1 notAnArrayGroup2").Build(),
),
method: http.MethodGet,
path: newRequestPath().WithState(happyState).String(),
@@ -733,7 +729,7 @@ func TestCallbackEndpoint(t *testing.T) {
wantStatus: http.StatusSeeOther,
wantRedirectLocationRegexp: happyDownstreamRedirectLocationRegexp,
wantBody: "",
- wantDownstreamIDTokenSubject: oidcUpstreamIssuer + "?idpName=" + happyUpstreamIDPName + "&sub=" + oidcUpstreamSubjectQueryEscaped,
+ wantDownstreamIDTokenSubject: oidcUpstreamIssuer + "?idpName=" + happyOIDCUpstreamIDPName + "&sub=" + oidcUpstreamSubjectQueryEscaped,
wantDownstreamIDTokenUsername: oidcUpstreamUsername,
wantDownstreamIDTokenGroups: []string{"notAnArrayGroup1 notAnArrayGroup2"},
wantDownstreamRequestedScopes: happyDownstreamScopesRequested,
@@ -748,14 +744,14 @@ func TestCallbackEndpoint(t *testing.T) {
[]string{"notAnArrayGroup1 notAnArrayGroup2"},
),
wantOIDCAuthcodeExchangeCall: &expectedOIDCAuthcodeExchange{
- performedByUpstreamName: happyUpstreamIDPName,
- args: happyExchangeAndValidateTokensArgs,
+ performedByUpstreamName: happyOIDCUpstreamIDPName,
+ args: happyOIDCUpstreamExchangeAuthcodeAndValidateTokenArgs,
},
},
{
name: "upstream IDP's configured groups claim in the ID token is a slice of interfaces",
idps: testidplister.NewUpstreamIDPListerBuilder().WithOIDC(
- happyUpstream().WithIDTokenClaim(oidcUpstreamGroupsClaim, []interface{}{"group1", "group2"}).Build(),
+ happyOIDCUpstream().WithIDTokenClaim(oidcUpstreamGroupsClaim, []interface{}{"group1", "group2"}).Build(),
),
method: http.MethodGet,
path: newRequestPath().WithState(happyState).String(),
@@ -763,7 +759,7 @@ func TestCallbackEndpoint(t *testing.T) {
wantStatus: http.StatusSeeOther,
wantRedirectLocationRegexp: happyDownstreamRedirectLocationRegexp,
wantBody: "",
- wantDownstreamIDTokenSubject: oidcUpstreamIssuer + "?idpName=" + happyUpstreamIDPName + "&sub=" + oidcUpstreamSubjectQueryEscaped,
+ wantDownstreamIDTokenSubject: oidcUpstreamIssuer + "?idpName=" + happyOIDCUpstreamIDPName + "&sub=" + oidcUpstreamSubjectQueryEscaped,
wantDownstreamIDTokenUsername: oidcUpstreamUsername,
wantDownstreamIDTokenGroups: []string{"group1", "group2"},
wantDownstreamRequestedScopes: happyDownstreamScopesRequested,
@@ -778,17 +774,17 @@ func TestCallbackEndpoint(t *testing.T) {
[]string{"group1", "group2"},
),
wantOIDCAuthcodeExchangeCall: &expectedOIDCAuthcodeExchange{
- performedByUpstreamName: happyUpstreamIDPName,
- args: happyExchangeAndValidateTokensArgs,
+ performedByUpstreamName: happyOIDCUpstreamIDPName,
+ args: happyOIDCUpstreamExchangeAuthcodeAndValidateTokenArgs,
},
},
{
name: "using dynamic client which is allowed to request username scope, but does not actually request username scope in authorize request, does not get username in ID token",
- idps: testidplister.NewUpstreamIDPListerBuilder().WithOIDC(happyUpstream().Build()),
+ idps: testidplister.NewUpstreamIDPListerBuilder().WithOIDC(happyOIDCUpstream().Build()),
kubeResources: addFullyCapableDynamicClientAndSecretToKubeResources,
method: http.MethodGet,
path: newRequestPath().WithState(
- happyUpstreamStateParamForDynamicClient().
+ happyOIDCUpstreamStateParamForDynamicClient().
WithAuthorizeRequestParams(shallowCopyAndModifyQuery(happyDownstreamRequestParamsQueryForDynamicClient,
map[string]string{"scope": "openid groups offline_access"}).Encode()).
Build(t, happyStateCodec),
@@ -797,7 +793,7 @@ func TestCallbackEndpoint(t *testing.T) {
wantStatus: http.StatusSeeOther,
wantRedirectLocationRegexp: downstreamRedirectURI + `\?code=([^&]+)&scope=openid\+offline_access\+groups&state=` + happyDownstreamState,
wantBody: "",
- wantDownstreamIDTokenSubject: oidcUpstreamIssuer + "?idpName=" + happyUpstreamIDPName + "&sub=" + oidcUpstreamSubjectQueryEscaped,
+ wantDownstreamIDTokenSubject: oidcUpstreamIssuer + "?idpName=" + happyOIDCUpstreamIDPName + "&sub=" + oidcUpstreamSubjectQueryEscaped,
wantDownstreamIDTokenUsername: "", // username scope was not requested
wantDownstreamIDTokenGroups: oidcUpstreamGroupMembership,
wantDownstreamRequestedScopes: []string{"openid", "groups", "offline_access"},
@@ -808,17 +804,17 @@ func TestCallbackEndpoint(t *testing.T) {
wantDownstreamPKCEChallengeMethod: downstreamPKCEChallengeMethod,
wantDownstreamCustomSessionData: happyDownstreamCustomSessionData,
wantOIDCAuthcodeExchangeCall: &expectedOIDCAuthcodeExchange{
- performedByUpstreamName: happyUpstreamIDPName,
- args: happyExchangeAndValidateTokensArgs,
+ performedByUpstreamName: happyOIDCUpstreamIDPName,
+ args: happyOIDCUpstreamExchangeAuthcodeAndValidateTokenArgs,
},
},
{
name: "using dynamic client which is allowed to request groups scope, but does not actually request groups scope in authorize request, does not get groups in ID token",
- idps: testidplister.NewUpstreamIDPListerBuilder().WithOIDC(happyUpstream().Build()),
+ idps: testidplister.NewUpstreamIDPListerBuilder().WithOIDC(happyOIDCUpstream().Build()),
kubeResources: addFullyCapableDynamicClientAndSecretToKubeResources,
method: http.MethodGet,
path: newRequestPath().WithState(
- happyUpstreamStateParamForDynamicClient().
+ happyOIDCUpstreamStateParamForDynamicClient().
WithAuthorizeRequestParams(shallowCopyAndModifyQuery(happyDownstreamRequestParamsQueryForDynamicClient,
map[string]string{"scope": "openid username offline_access"}).Encode()).
Build(t, happyStateCodec),
@@ -827,7 +823,7 @@ func TestCallbackEndpoint(t *testing.T) {
wantStatus: http.StatusSeeOther,
wantRedirectLocationRegexp: downstreamRedirectURI + `\?code=([^&]+)&scope=openid\+offline_access\+username&state=` + happyDownstreamState,
wantBody: "",
- wantDownstreamIDTokenSubject: oidcUpstreamIssuer + "?idpName=" + happyUpstreamIDPName + "&sub=" + oidcUpstreamSubjectQueryEscaped,
+ wantDownstreamIDTokenSubject: oidcUpstreamIssuer + "?idpName=" + happyOIDCUpstreamIDPName + "&sub=" + oidcUpstreamSubjectQueryEscaped,
wantDownstreamIDTokenUsername: oidcUpstreamUsername,
wantDownstreamIDTokenGroups: nil, // groups scope was not requested
wantDownstreamRequestedScopes: []string{"openid", "username", "offline_access"},
@@ -838,13 +834,13 @@ func TestCallbackEndpoint(t *testing.T) {
wantDownstreamPKCEChallengeMethod: downstreamPKCEChallengeMethod,
wantDownstreamCustomSessionData: happyDownstreamCustomSessionData,
wantOIDCAuthcodeExchangeCall: &expectedOIDCAuthcodeExchange{
- performedByUpstreamName: happyUpstreamIDPName,
- args: happyExchangeAndValidateTokensArgs,
+ performedByUpstreamName: happyOIDCUpstreamIDPName,
+ args: happyOIDCUpstreamExchangeAuthcodeAndValidateTokenArgs,
},
},
{
name: "using dynamic client which is not allowed to request username scope, and does not actually request username scope in authorize request, does not get username in ID token",
- idps: testidplister.NewUpstreamIDPListerBuilder().WithOIDC(happyUpstream().Build()),
+ idps: testidplister.NewUpstreamIDPListerBuilder().WithOIDC(happyOIDCUpstream().Build()),
kubeResources: func(t *testing.T, supervisorClient *supervisorfake.Clientset, kubeClient *fake.Clientset) {
oidcClient, secret := testutil.OIDCClientAndStorageSecret(t,
"some-namespace", downstreamDynamicClientID, downstreamDynamicClientUID,
@@ -856,7 +852,7 @@ func TestCallbackEndpoint(t *testing.T) {
},
method: http.MethodGet,
path: newRequestPath().WithState(
- happyUpstreamStateParam().WithAuthorizeRequestParams(
+ happyOIDCUpstreamStateParam().WithAuthorizeRequestParams(
shallowCopyAndModifyQuery(
happyDownstreamRequestParamsQuery,
map[string]string{
@@ -870,7 +866,7 @@ func TestCallbackEndpoint(t *testing.T) {
wantStatus: http.StatusSeeOther,
wantRedirectLocationRegexp: downstreamRedirectURI + `\?code=([^&]+)&scope=openid\+offline_access\+groups&state=` + happyDownstreamState,
wantBody: "",
- wantDownstreamIDTokenSubject: oidcUpstreamIssuer + "?idpName=" + happyUpstreamIDPName + "&sub=" + oidcUpstreamSubjectQueryEscaped,
+ wantDownstreamIDTokenSubject: oidcUpstreamIssuer + "?idpName=" + happyOIDCUpstreamIDPName + "&sub=" + oidcUpstreamSubjectQueryEscaped,
wantDownstreamIDTokenUsername: "", // username scope was not requested
wantDownstreamIDTokenGroups: oidcUpstreamGroupMembership,
wantDownstreamRequestedScopes: []string{"openid", "groups", "offline_access"},
@@ -881,13 +877,13 @@ func TestCallbackEndpoint(t *testing.T) {
wantDownstreamPKCEChallengeMethod: downstreamPKCEChallengeMethod,
wantDownstreamCustomSessionData: happyDownstreamCustomSessionData,
wantOIDCAuthcodeExchangeCall: &expectedOIDCAuthcodeExchange{
- performedByUpstreamName: happyUpstreamIDPName,
- args: happyExchangeAndValidateTokensArgs,
+ performedByUpstreamName: happyOIDCUpstreamIDPName,
+ args: happyOIDCUpstreamExchangeAuthcodeAndValidateTokenArgs,
},
},
{
name: "using dynamic client which is not allowed to request groups scope, and does not actually request groups scope in authorize request, does not get groups in ID token",
- idps: testidplister.NewUpstreamIDPListerBuilder().WithOIDC(happyUpstream().Build()),
+ idps: testidplister.NewUpstreamIDPListerBuilder().WithOIDC(happyOIDCUpstream().Build()),
kubeResources: func(t *testing.T, supervisorClient *supervisorfake.Clientset, kubeClient *fake.Clientset) {
oidcClient, secret := testutil.OIDCClientAndStorageSecret(t,
"some-namespace", downstreamDynamicClientID, downstreamDynamicClientUID,
@@ -899,7 +895,7 @@ func TestCallbackEndpoint(t *testing.T) {
},
method: http.MethodGet,
path: newRequestPath().WithState(
- happyUpstreamStateParam().WithAuthorizeRequestParams(
+ happyOIDCUpstreamStateParam().WithAuthorizeRequestParams(
shallowCopyAndModifyQuery(
happyDownstreamRequestParamsQuery,
map[string]string{
@@ -913,7 +909,7 @@ func TestCallbackEndpoint(t *testing.T) {
wantStatus: http.StatusSeeOther,
wantRedirectLocationRegexp: downstreamRedirectURI + `\?code=([^&]+)&scope=openid\+offline_access\+username&state=` + happyDownstreamState,
wantBody: "",
- wantDownstreamIDTokenSubject: oidcUpstreamIssuer + "?idpName=" + happyUpstreamIDPName + "&sub=" + oidcUpstreamSubjectQueryEscaped,
+ wantDownstreamIDTokenSubject: oidcUpstreamIssuer + "?idpName=" + happyOIDCUpstreamIDPName + "&sub=" + oidcUpstreamSubjectQueryEscaped,
wantDownstreamIDTokenUsername: oidcUpstreamUsername,
wantDownstreamIDTokenGroups: nil, // groups scope was not requested
wantDownstreamRequestedScopes: []string{"openid", "username", "offline_access"},
@@ -924,21 +920,21 @@ func TestCallbackEndpoint(t *testing.T) {
wantDownstreamPKCEChallengeMethod: downstreamPKCEChallengeMethod,
wantDownstreamCustomSessionData: happyDownstreamCustomSessionData,
wantOIDCAuthcodeExchangeCall: &expectedOIDCAuthcodeExchange{
- performedByUpstreamName: happyUpstreamIDPName,
- args: happyExchangeAndValidateTokensArgs,
+ performedByUpstreamName: happyOIDCUpstreamIDPName,
+ args: happyOIDCUpstreamExchangeAuthcodeAndValidateTokenArgs,
},
},
{
name: "using identity transformations which modify the username and group names",
idps: testidplister.NewUpstreamIDPListerBuilder().
- WithOIDC(happyUpstream().WithTransformsForFederationDomain(prefixUsernameAndGroupsPipeline).Build()),
+ WithOIDC(happyOIDCUpstream().WithTransformsForFederationDomain(prefixUsernameAndGroupsPipeline).Build()),
method: http.MethodGet,
path: newRequestPath().WithState(happyState).String(),
csrfCookie: happyCSRFCookie,
wantStatus: http.StatusSeeOther,
wantRedirectLocationRegexp: happyDownstreamRedirectLocationRegexp,
wantBody: "",
- wantDownstreamIDTokenSubject: oidcUpstreamIssuer + "?idpName=" + happyUpstreamIDPName + "&sub=" + oidcUpstreamSubjectQueryEscaped,
+ wantDownstreamIDTokenSubject: oidcUpstreamIssuer + "?idpName=" + happyOIDCUpstreamIDPName + "&sub=" + oidcUpstreamSubjectQueryEscaped,
wantDownstreamIDTokenUsername: transformationUsernamePrefix + oidcUpstreamUsername,
wantDownstreamIDTokenGroups: testutil.AddPrefixToEach(transformationGroupsPrefix, oidcUpstreamGroupMembership),
wantDownstreamRequestedScopes: happyDownstreamScopesRequested,
@@ -953,15 +949,15 @@ func TestCallbackEndpoint(t *testing.T) {
oidcUpstreamGroupMembership,
),
wantOIDCAuthcodeExchangeCall: &expectedOIDCAuthcodeExchange{
- performedByUpstreamName: happyUpstreamIDPName,
- args: happyExchangeAndValidateTokensArgs,
+ performedByUpstreamName: happyOIDCUpstreamIDPName,
+ args: happyOIDCUpstreamExchangeAuthcodeAndValidateTokenArgs,
},
},
// Pre-upstream-exchange verification
{
name: "PUT method is invalid",
- idps: testidplister.NewUpstreamIDPListerBuilder().WithOIDC(happyUpstream().Build()),
+ idps: testidplister.NewUpstreamIDPListerBuilder().WithOIDC(happyOIDCUpstream().Build()),
method: http.MethodPut,
path: newRequestPath().String(),
wantStatus: http.StatusMethodNotAllowed,
@@ -970,7 +966,7 @@ func TestCallbackEndpoint(t *testing.T) {
},
{
name: "POST method is invalid",
- idps: testidplister.NewUpstreamIDPListerBuilder().WithOIDC(happyUpstream().Build()),
+ idps: testidplister.NewUpstreamIDPListerBuilder().WithOIDC(happyOIDCUpstream().Build()),
method: http.MethodPost,
path: newRequestPath().String(),
wantStatus: http.StatusMethodNotAllowed,
@@ -979,7 +975,7 @@ func TestCallbackEndpoint(t *testing.T) {
},
{
name: "PATCH method is invalid",
- idps: testidplister.NewUpstreamIDPListerBuilder().WithOIDC(happyUpstream().Build()),
+ idps: testidplister.NewUpstreamIDPListerBuilder().WithOIDC(happyOIDCUpstream().Build()),
method: http.MethodPatch,
path: newRequestPath().String(),
wantStatus: http.StatusMethodNotAllowed,
@@ -988,7 +984,7 @@ func TestCallbackEndpoint(t *testing.T) {
},
{
name: "DELETE method is invalid",
- idps: testidplister.NewUpstreamIDPListerBuilder().WithOIDC(happyUpstream().Build()),
+ idps: testidplister.NewUpstreamIDPListerBuilder().WithOIDC(happyOIDCUpstream().Build()),
method: http.MethodDelete,
path: newRequestPath().String(),
wantStatus: http.StatusMethodNotAllowed,
@@ -997,7 +993,7 @@ func TestCallbackEndpoint(t *testing.T) {
},
{
name: "code param was not included on request",
- idps: testidplister.NewUpstreamIDPListerBuilder().WithOIDC(happyUpstream().Build()),
+ idps: testidplister.NewUpstreamIDPListerBuilder().WithOIDC(happyOIDCUpstream().Build()),
method: http.MethodGet,
path: newRequestPath().WithState(happyState).WithoutCode().String(),
csrfCookie: happyCSRFCookie,
@@ -1007,7 +1003,7 @@ func TestCallbackEndpoint(t *testing.T) {
},
{
name: "state param was not included on request",
- idps: testidplister.NewUpstreamIDPListerBuilder().WithOIDC(happyUpstream().Build()),
+ idps: testidplister.NewUpstreamIDPListerBuilder().WithOIDC(happyOIDCUpstream().Build()),
method: http.MethodGet,
path: newRequestPath().WithoutState().String(),
csrfCookie: happyCSRFCookie,
@@ -1017,7 +1013,7 @@ func TestCallbackEndpoint(t *testing.T) {
},
{
name: "state param was not signed correctly, has expired, or otherwise cannot be decoded for any reason",
- idps: testidplister.NewUpstreamIDPListerBuilder().WithOIDC(happyUpstream().Build()),
+ idps: testidplister.NewUpstreamIDPListerBuilder().WithOIDC(happyOIDCUpstream().Build()),
method: http.MethodGet,
path: newRequestPath().WithState("this-will-not-decode").String(),
csrfCookie: happyCSRFCookie,
@@ -1029,18 +1025,18 @@ func TestCallbackEndpoint(t *testing.T) {
// This shouldn't happen in practice because the authorize endpoint should have already run the same
// validations, but we would like to test the error handling in this endpoint anyway.
name: "state param contains authorization request params which fail validation",
- idps: testidplister.NewUpstreamIDPListerBuilder().WithOIDC(happyUpstream().Build()),
+ idps: testidplister.NewUpstreamIDPListerBuilder().WithOIDC(happyOIDCUpstream().Build()),
method: http.MethodGet,
path: newRequestPath().WithState(
- happyUpstreamStateParam().
+ happyOIDCUpstreamStateParam().
WithAuthorizeRequestParams(shallowCopyAndModifyQuery(happyDownstreamRequestParamsQuery,
map[string]string{"prompt": "none login"}).Encode()).
Build(t, happyStateCodec),
).String(),
csrfCookie: happyCSRFCookie,
wantOIDCAuthcodeExchangeCall: &expectedOIDCAuthcodeExchange{
- performedByUpstreamName: happyUpstreamIDPName,
- args: happyExchangeAndValidateTokensArgs,
+ performedByUpstreamName: happyOIDCUpstreamIDPName,
+ args: happyOIDCUpstreamExchangeAuthcodeAndValidateTokenArgs,
},
wantStatus: http.StatusInternalServerError,
@@ -1049,9 +1045,9 @@ func TestCallbackEndpoint(t *testing.T) {
},
{
name: "state's internal version does not match what we want",
- idps: testidplister.NewUpstreamIDPListerBuilder().WithOIDC(happyUpstream().Build()),
+ idps: testidplister.NewUpstreamIDPListerBuilder().WithOIDC(happyOIDCUpstream().Build()),
method: http.MethodGet,
- path: newRequestPath().WithState(happyUpstreamStateParam().WithStateVersion("wrong-state-version").Build(t, happyStateCodec)).String(),
+ path: newRequestPath().WithState(happyOIDCUpstreamStateParam().WithStateVersion("wrong-state-version").Build(t, happyStateCodec)).String(),
csrfCookie: happyCSRFCookie,
wantStatus: http.StatusUnprocessableEntity,
wantContentType: htmlContentType,
@@ -1059,9 +1055,9 @@ func TestCallbackEndpoint(t *testing.T) {
},
{
name: "state's downstream auth params element is invalid",
- idps: testidplister.NewUpstreamIDPListerBuilder().WithOIDC(happyUpstream().Build()),
+ idps: testidplister.NewUpstreamIDPListerBuilder().WithOIDC(happyOIDCUpstream().Build()),
method: http.MethodGet,
- path: newRequestPath().WithState(happyUpstreamStateParam().
+ path: newRequestPath().WithState(happyOIDCUpstreamStateParam().
WithAuthorizeRequestParams("the following is an invalid url encoding token, and therefore this is an invalid param: %z").
Build(t, happyStateCodec)).String(),
csrfCookie: happyCSRFCookie,
@@ -1071,10 +1067,10 @@ func TestCallbackEndpoint(t *testing.T) {
},
{
name: "state's downstream auth params are missing required value (e.g., client_id)",
- idps: testidplister.NewUpstreamIDPListerBuilder().WithOIDC(happyUpstream().Build()),
+ idps: testidplister.NewUpstreamIDPListerBuilder().WithOIDC(happyOIDCUpstream().Build()),
method: http.MethodGet,
path: newRequestPath().WithState(
- happyUpstreamStateParam().
+ happyOIDCUpstreamStateParam().
WithAuthorizeRequestParams(shallowCopyAndModifyQuery(happyDownstreamRequestParamsQuery,
map[string]string{"client_id": ""}).Encode()).
Build(t, happyStateCodec),
@@ -1086,10 +1082,10 @@ func TestCallbackEndpoint(t *testing.T) {
},
{
name: "state's downstream auth params have invalid client_id",
- idps: testidplister.NewUpstreamIDPListerBuilder().WithOIDC(happyUpstream().Build()),
+ idps: testidplister.NewUpstreamIDPListerBuilder().WithOIDC(happyOIDCUpstream().Build()),
method: http.MethodGet,
path: newRequestPath().WithState(
- happyUpstreamStateParam().
+ happyOIDCUpstreamStateParam().
WithAuthorizeRequestParams(shallowCopyAndModifyQuery(happyDownstreamRequestParamsQuery,
map[string]string{"client_id": "bogus"}).Encode()).
Build(t, happyStateCodec),
@@ -1101,11 +1097,11 @@ func TestCallbackEndpoint(t *testing.T) {
},
{
name: "dynamic clients do not allow response_mode=form_post",
- idps: testidplister.NewUpstreamIDPListerBuilder().WithOIDC(happyUpstream().Build()),
+ idps: testidplister.NewUpstreamIDPListerBuilder().WithOIDC(happyOIDCUpstream().Build()),
kubeResources: addFullyCapableDynamicClientAndSecretToKubeResources,
method: http.MethodGet,
path: newRequestPath().WithState(
- happyUpstreamStateParam().WithAuthorizeRequestParams(
+ happyOIDCUpstreamStateParam().WithAuthorizeRequestParams(
shallowCopyAndModifyQuery(
happyDownstreamRequestParamsQuery,
map[string]string{
@@ -1123,7 +1119,7 @@ func TestCallbackEndpoint(t *testing.T) {
},
{
name: "using dynamic client which is not allowed to request username scope in authorize request but requests it anyway",
- idps: testidplister.NewUpstreamIDPListerBuilder().WithOIDC(happyUpstream().Build()),
+ idps: testidplister.NewUpstreamIDPListerBuilder().WithOIDC(happyOIDCUpstream().Build()),
kubeResources: func(t *testing.T, supervisorClient *supervisorfake.Clientset, kubeClient *fake.Clientset) {
oidcClient, secret := testutil.OIDCClientAndStorageSecret(t,
"some-namespace", downstreamDynamicClientID, downstreamDynamicClientUID,
@@ -1135,7 +1131,7 @@ func TestCallbackEndpoint(t *testing.T) {
},
method: http.MethodGet,
path: newRequestPath().WithState(
- happyUpstreamStateParam().WithAuthorizeRequestParams(
+ happyOIDCUpstreamStateParam().WithAuthorizeRequestParams(
shallowCopyAndModifyQuery(
happyDownstreamRequestParamsQuery,
map[string]string{
@@ -1152,7 +1148,7 @@ func TestCallbackEndpoint(t *testing.T) {
},
{
name: "using dynamic client which is not allowed to request groups scope in authorize request but requests it anyway",
- idps: testidplister.NewUpstreamIDPListerBuilder().WithOIDC(happyUpstream().Build()),
+ idps: testidplister.NewUpstreamIDPListerBuilder().WithOIDC(happyOIDCUpstream().Build()),
kubeResources: func(t *testing.T, supervisorClient *supervisorfake.Clientset, kubeClient *fake.Clientset) {
oidcClient, secret := testutil.OIDCClientAndStorageSecret(t,
"some-namespace", downstreamDynamicClientID, downstreamDynamicClientUID,
@@ -1164,7 +1160,7 @@ func TestCallbackEndpoint(t *testing.T) {
},
method: http.MethodGet,
path: newRequestPath().WithState(
- happyUpstreamStateParam().WithAuthorizeRequestParams(
+ happyOIDCUpstreamStateParam().WithAuthorizeRequestParams(
shallowCopyAndModifyQuery(
happyDownstreamRequestParamsQuery,
map[string]string{
@@ -1181,11 +1177,11 @@ func TestCallbackEndpoint(t *testing.T) {
},
{
name: "state's downstream auth params does not contain openid scope",
- idps: testidplister.NewUpstreamIDPListerBuilder().WithOIDC(happyUpstream().Build()),
+ idps: testidplister.NewUpstreamIDPListerBuilder().WithOIDC(happyOIDCUpstream().Build()),
method: http.MethodGet,
path: newRequestPath().
WithState(
- happyUpstreamStateParam().
+ happyOIDCUpstreamStateParam().
WithAuthorizeRequestParams(shallowCopyAndModifyQuery(happyDownstreamRequestParamsQuery,
map[string]string{"scope": "profile username email groups"}).Encode()).
Build(t, happyStateCodec),
@@ -1194,7 +1190,7 @@ func TestCallbackEndpoint(t *testing.T) {
wantStatus: http.StatusSeeOther,
wantRedirectLocationRegexp: downstreamRedirectURI + `\?code=([^&]+)&scope=username\+groups&state=` + happyDownstreamState,
wantDownstreamIDTokenUsername: oidcUpstreamUsername,
- wantDownstreamIDTokenSubject: oidcUpstreamIssuer + "?idpName=" + happyUpstreamIDPName + "&sub=" + oidcUpstreamSubjectQueryEscaped,
+ wantDownstreamIDTokenSubject: oidcUpstreamIssuer + "?idpName=" + happyOIDCUpstreamIDPName + "&sub=" + oidcUpstreamSubjectQueryEscaped,
wantDownstreamRequestedScopes: []string{"profile", "email", "username", "groups"},
wantDownstreamGrantedScopes: []string{"username", "groups"},
wantDownstreamIDTokenGroups: oidcUpstreamGroupMembership,
@@ -1204,17 +1200,17 @@ func TestCallbackEndpoint(t *testing.T) {
wantDownstreamPKCEChallengeMethod: downstreamPKCEChallengeMethod,
wantDownstreamCustomSessionData: happyDownstreamCustomSessionData,
wantOIDCAuthcodeExchangeCall: &expectedOIDCAuthcodeExchange{
- performedByUpstreamName: happyUpstreamIDPName,
- args: happyExchangeAndValidateTokensArgs,
+ performedByUpstreamName: happyOIDCUpstreamIDPName,
+ args: happyOIDCUpstreamExchangeAuthcodeAndValidateTokenArgs,
},
},
{
name: "state's downstream auth params does not contain openid, username, or groups scope",
- idps: testidplister.NewUpstreamIDPListerBuilder().WithOIDC(happyUpstream().Build()),
+ idps: testidplister.NewUpstreamIDPListerBuilder().WithOIDC(happyOIDCUpstream().Build()),
method: http.MethodGet,
path: newRequestPath().
WithState(
- happyUpstreamStateParam().
+ happyOIDCUpstreamStateParam().
WithAuthorizeRequestParams(shallowCopyAndModifyQuery(happyDownstreamRequestParamsQuery,
map[string]string{"scope": "profile email"}).Encode()).
Build(t, happyStateCodec),
@@ -1224,7 +1220,7 @@ func TestCallbackEndpoint(t *testing.T) {
wantRedirectLocationRegexp: downstreamRedirectURI + `\?code=([^&]+)&scope=username\+groups&state=` + happyDownstreamState,
wantDownstreamIDTokenUsername: oidcUpstreamUsername,
wantDownstreamIDTokenGroups: oidcUpstreamGroupMembership,
- wantDownstreamIDTokenSubject: oidcUpstreamIssuer + "?idpName=" + happyUpstreamIDPName + "&sub=" + oidcUpstreamSubjectQueryEscaped,
+ wantDownstreamIDTokenSubject: oidcUpstreamIssuer + "?idpName=" + happyOIDCUpstreamIDPName + "&sub=" + oidcUpstreamSubjectQueryEscaped,
wantDownstreamRequestedScopes: []string{"profile", "email"},
// username and groups scopes were not requested but are granted anyway for the pinniped-cli client for backwards compatibility
wantDownstreamGrantedScopes: []string{"username", "groups"},
@@ -1234,17 +1230,17 @@ func TestCallbackEndpoint(t *testing.T) {
wantDownstreamPKCEChallengeMethod: downstreamPKCEChallengeMethod,
wantDownstreamCustomSessionData: happyDownstreamCustomSessionData,
wantOIDCAuthcodeExchangeCall: &expectedOIDCAuthcodeExchange{
- performedByUpstreamName: happyUpstreamIDPName,
- args: happyExchangeAndValidateTokensArgs,
+ performedByUpstreamName: happyOIDCUpstreamIDPName,
+ args: happyOIDCUpstreamExchangeAuthcodeAndValidateTokenArgs,
},
},
{
name: "state's downstream auth params also included offline_access scope",
- idps: testidplister.NewUpstreamIDPListerBuilder().WithOIDC(happyUpstream().Build()),
+ idps: testidplister.NewUpstreamIDPListerBuilder().WithOIDC(happyOIDCUpstream().Build()),
method: http.MethodGet,
path: newRequestPath().
WithState(
- happyUpstreamStateParam().
+ happyOIDCUpstreamStateParam().
WithAuthorizeRequestParams(shallowCopyAndModifyQuery(happyDownstreamRequestParamsQuery,
map[string]string{"scope": "openid offline_access username groups"}).Encode()).
Build(t, happyStateCodec),
@@ -1253,7 +1249,7 @@ func TestCallbackEndpoint(t *testing.T) {
wantStatus: http.StatusSeeOther,
wantRedirectLocationRegexp: downstreamRedirectURI + `\?code=([^&]+)&scope=openid\+offline_access\+username\+groups&state=` + happyDownstreamState,
wantDownstreamIDTokenUsername: oidcUpstreamUsername,
- wantDownstreamIDTokenSubject: oidcUpstreamIssuer + "?idpName=" + happyUpstreamIDPName + "&sub=" + oidcUpstreamSubjectQueryEscaped,
+ wantDownstreamIDTokenSubject: oidcUpstreamIssuer + "?idpName=" + happyOIDCUpstreamIDPName + "&sub=" + oidcUpstreamSubjectQueryEscaped,
wantDownstreamRequestedScopes: []string{"openid", "offline_access", "username", "groups"},
wantDownstreamGrantedScopes: []string{"openid", "offline_access", "username", "groups"},
wantDownstreamIDTokenGroups: oidcUpstreamGroupMembership,
@@ -1263,8 +1259,8 @@ func TestCallbackEndpoint(t *testing.T) {
wantDownstreamPKCEChallengeMethod: downstreamPKCEChallengeMethod,
wantDownstreamCustomSessionData: happyDownstreamCustomSessionData,
wantOIDCAuthcodeExchangeCall: &expectedOIDCAuthcodeExchange{
- performedByUpstreamName: happyUpstreamIDPName,
- args: happyExchangeAndValidateTokensArgs,
+ performedByUpstreamName: happyOIDCUpstreamIDPName,
+ args: happyOIDCUpstreamExchangeAuthcodeAndValidateTokenArgs,
},
},
{
@@ -1280,8 +1276,8 @@ func TestCallbackEndpoint(t *testing.T) {
Build()),
method: http.MethodGet,
path: newRequestPath().WithState(
- happyUpstreamStateParam().
- WithUpstreamIDPName(githubIDPName).
+ happyOIDCUpstreamStateParam().
+ WithUpstreamIDPName(happyGithubIDPName).
WithUpstreamIDPType(idpdiscoveryv1alpha1.IDPTypeGitHub).
WithAuthorizeRequestParams(
happyDownstreamRequestParamsQuery.Encode(),
@@ -1302,8 +1298,8 @@ func TestCallbackEndpoint(t *testing.T) {
wantDownstreamPKCEChallengeMethod: downstreamPKCEChallengeMethod,
wantDownstreamCustomSessionData: happyDownstreamGitHubCustomSessionData,
wantGitHubAuthcodeExchangeCall: &expectedGitHubAuthcodeExchange{
- performedByUpstreamName: githubIDPName,
- args: happyGitHubExchangeAuthcodeArgs,
+ performedByUpstreamName: happyGithubIDPName,
+ args: happyGitHubUpstreamExchangeAuthcodeArgs,
},
},
{
@@ -1320,8 +1316,8 @@ func TestCallbackEndpoint(t *testing.T) {
method: http.MethodGet,
kubeResources: addFullyCapableDynamicClientAndSecretToKubeResources,
path: newRequestPath().WithState(
- happyUpstreamStateParam().
- WithUpstreamIDPName(githubIDPName).
+ happyOIDCUpstreamStateParam().
+ WithUpstreamIDPName(happyGithubIDPName).
WithUpstreamIDPType(idpdiscoveryv1alpha1.IDPTypeGitHub).
WithAuthorizeRequestParams(
shallowCopyAndModifyQuery(
@@ -1347,8 +1343,8 @@ func TestCallbackEndpoint(t *testing.T) {
wantDownstreamPKCEChallengeMethod: downstreamPKCEChallengeMethod,
wantDownstreamCustomSessionData: happyDownstreamGitHubCustomSessionData,
wantGitHubAuthcodeExchangeCall: &expectedGitHubAuthcodeExchange{
- performedByUpstreamName: githubIDPName,
- args: happyGitHubExchangeAuthcodeArgs,
+ performedByUpstreamName: happyGithubIDPName,
+ args: happyGitHubUpstreamExchangeAuthcodeArgs,
},
},
{
@@ -1363,7 +1359,7 @@ func TestCallbackEndpoint(t *testing.T) {
},
{
name: "the CSRF cookie does not exist on request",
- idps: testidplister.NewUpstreamIDPListerBuilder().WithOIDC(happyUpstream().Build()),
+ idps: testidplister.NewUpstreamIDPListerBuilder().WithOIDC(happyOIDCUpstream().Build()),
method: http.MethodGet,
path: newRequestPath().WithState(happyState).String(),
wantStatus: http.StatusForbidden,
@@ -1372,7 +1368,7 @@ func TestCallbackEndpoint(t *testing.T) {
},
{
name: "cookie was not signed correctly, has expired, or otherwise cannot be decoded for any reason",
- idps: testidplister.NewUpstreamIDPListerBuilder().WithOIDC(happyUpstream().Build()),
+ idps: testidplister.NewUpstreamIDPListerBuilder().WithOIDC(happyOIDCUpstream().Build()),
method: http.MethodGet,
path: newRequestPath().WithState(happyState).String(),
csrfCookie: "__Host-pinniped-csrf=this-value-was-not-signed-by-pinniped",
@@ -1382,9 +1378,9 @@ func TestCallbackEndpoint(t *testing.T) {
},
{
name: "cookie csrf value does not match state csrf value",
- idps: testidplister.NewUpstreamIDPListerBuilder().WithOIDC(happyUpstream().Build()),
+ idps: testidplister.NewUpstreamIDPListerBuilder().WithOIDC(happyOIDCUpstream().Build()),
method: http.MethodGet,
- path: newRequestPath().WithState(happyUpstreamStateParam().WithCSRF("wrong-csrf-value").Build(t, happyStateCodec)).String(),
+ path: newRequestPath().WithState(happyOIDCUpstreamStateParam().WithCSRF("wrong-csrf-value").Build(t, happyStateCodec)).String(),
csrfCookie: happyCSRFCookie,
wantStatus: http.StatusForbidden,
wantContentType: htmlContentType,
@@ -1395,7 +1391,7 @@ func TestCallbackEndpoint(t *testing.T) {
{
name: "upstream auth code exchange fails",
idps: testidplister.NewUpstreamIDPListerBuilder().WithOIDC(
- happyUpstream().WithUpstreamAuthcodeExchangeError(errors.New("some error")).Build(),
+ happyOIDCUpstream().WithUpstreamAuthcodeExchangeError(errors.New("some error")).Build(),
),
method: http.MethodGet,
path: newRequestPath().WithState(happyState).String(),
@@ -1404,14 +1400,14 @@ func TestCallbackEndpoint(t *testing.T) {
wantBody: "Bad Gateway: error exchanging and validating upstream tokens\n",
wantContentType: htmlContentType,
wantOIDCAuthcodeExchangeCall: &expectedOIDCAuthcodeExchange{
- performedByUpstreamName: happyUpstreamIDPName,
- args: happyExchangeAndValidateTokensArgs,
+ performedByUpstreamName: happyOIDCUpstreamIDPName,
+ args: happyOIDCUpstreamExchangeAuthcodeAndValidateTokenArgs,
},
},
{
name: "upstream ID token does not contain requested username claim",
idps: testidplister.NewUpstreamIDPListerBuilder().WithOIDC(
- happyUpstream().WithoutIDTokenClaim(oidcUpstreamUsernameClaim).Build(),
+ happyOIDCUpstream().WithoutIDTokenClaim(oidcUpstreamUsernameClaim).Build(),
),
method: http.MethodGet,
path: newRequestPath().WithState(happyState).String(),
@@ -1420,14 +1416,14 @@ func TestCallbackEndpoint(t *testing.T) {
wantBody: "Unprocessable Entity: required claim in upstream ID token missing\n",
wantContentType: htmlContentType,
wantOIDCAuthcodeExchangeCall: &expectedOIDCAuthcodeExchange{
- performedByUpstreamName: happyUpstreamIDPName,
- args: happyExchangeAndValidateTokensArgs,
+ performedByUpstreamName: happyOIDCUpstreamIDPName,
+ args: happyOIDCUpstreamExchangeAuthcodeAndValidateTokenArgs,
},
},
{
name: "upstream ID token does not contain requested groups claim",
idps: testidplister.NewUpstreamIDPListerBuilder().WithOIDC(
- happyUpstream().WithoutIDTokenClaim(oidcUpstreamGroupsClaim).Build(),
+ happyOIDCUpstream().WithoutIDTokenClaim(oidcUpstreamGroupsClaim).Build(),
),
method: http.MethodGet,
path: newRequestPath().WithState(happyState).String(),
@@ -1435,7 +1431,7 @@ func TestCallbackEndpoint(t *testing.T) {
wantStatus: http.StatusSeeOther,
wantRedirectLocationRegexp: happyDownstreamRedirectLocationRegexp,
wantBody: "",
- wantDownstreamIDTokenSubject: oidcUpstreamIssuer + "?idpName=" + happyUpstreamIDPName + "&sub=" + oidcUpstreamSubjectQueryEscaped,
+ wantDownstreamIDTokenSubject: oidcUpstreamIssuer + "?idpName=" + happyOIDCUpstreamIDPName + "&sub=" + oidcUpstreamSubjectQueryEscaped,
wantDownstreamIDTokenUsername: oidcUpstreamUsername,
wantDownstreamRequestedScopes: happyDownstreamScopesRequested,
wantDownstreamGrantedScopes: happyDownstreamScopesGranted,
@@ -1450,14 +1446,14 @@ func TestCallbackEndpoint(t *testing.T) {
nil,
),
wantOIDCAuthcodeExchangeCall: &expectedOIDCAuthcodeExchange{
- performedByUpstreamName: happyUpstreamIDPName,
- args: happyExchangeAndValidateTokensArgs,
+ performedByUpstreamName: happyOIDCUpstreamIDPName,
+ args: happyOIDCUpstreamExchangeAuthcodeAndValidateTokenArgs,
},
},
{
name: "upstream ID token contains username claim with weird format",
idps: testidplister.NewUpstreamIDPListerBuilder().WithOIDC(
- happyUpstream().WithIDTokenClaim(oidcUpstreamUsernameClaim, 42).Build(),
+ happyOIDCUpstream().WithIDTokenClaim(oidcUpstreamUsernameClaim, 42).Build(),
),
method: http.MethodGet,
path: newRequestPath().WithState(happyState).String(),
@@ -1466,14 +1462,14 @@ func TestCallbackEndpoint(t *testing.T) {
wantContentType: htmlContentType,
wantBody: "Unprocessable Entity: required claim in upstream ID token has invalid format\n",
wantOIDCAuthcodeExchangeCall: &expectedOIDCAuthcodeExchange{
- performedByUpstreamName: happyUpstreamIDPName,
- args: happyExchangeAndValidateTokensArgs,
+ performedByUpstreamName: happyOIDCUpstreamIDPName,
+ args: happyOIDCUpstreamExchangeAuthcodeAndValidateTokenArgs,
},
},
{
name: "upstream ID token contains username claim with empty string value",
idps: testidplister.NewUpstreamIDPListerBuilder().WithOIDC(
- happyUpstream().WithIDTokenClaim(oidcUpstreamUsernameClaim, "").Build(),
+ happyOIDCUpstream().WithIDTokenClaim(oidcUpstreamUsernameClaim, "").Build(),
),
method: http.MethodGet,
path: newRequestPath().WithState(happyState).String(),
@@ -1482,14 +1478,14 @@ func TestCallbackEndpoint(t *testing.T) {
wantContentType: htmlContentType,
wantBody: "Unprocessable Entity: required claim in upstream ID token is empty\n",
wantOIDCAuthcodeExchangeCall: &expectedOIDCAuthcodeExchange{
- performedByUpstreamName: happyUpstreamIDPName,
- args: happyExchangeAndValidateTokensArgs,
+ performedByUpstreamName: happyOIDCUpstreamIDPName,
+ args: happyOIDCUpstreamExchangeAuthcodeAndValidateTokenArgs,
},
},
{
name: "upstream ID token does not contain iss claim when using default username claim config",
idps: testidplister.NewUpstreamIDPListerBuilder().WithOIDC(
- happyUpstream().WithoutIDTokenClaim("iss").WithoutUsernameClaim().Build(),
+ happyOIDCUpstream().WithoutIDTokenClaim("iss").WithoutUsernameClaim().Build(),
),
method: http.MethodGet,
path: newRequestPath().WithState(happyState).String(),
@@ -1498,14 +1494,14 @@ func TestCallbackEndpoint(t *testing.T) {
wantContentType: htmlContentType,
wantBody: "Unprocessable Entity: required claim in upstream ID token missing\n",
wantOIDCAuthcodeExchangeCall: &expectedOIDCAuthcodeExchange{
- performedByUpstreamName: happyUpstreamIDPName,
- args: happyExchangeAndValidateTokensArgs,
+ performedByUpstreamName: happyOIDCUpstreamIDPName,
+ args: happyOIDCUpstreamExchangeAuthcodeAndValidateTokenArgs,
},
},
{
name: "upstream ID token does has an empty string value for iss claim when using default username claim config",
idps: testidplister.NewUpstreamIDPListerBuilder().WithOIDC(
- happyUpstream().WithIDTokenClaim("iss", "").WithoutUsernameClaim().Build(),
+ happyOIDCUpstream().WithIDTokenClaim("iss", "").WithoutUsernameClaim().Build(),
),
method: http.MethodGet,
path: newRequestPath().WithState(happyState).String(),
@@ -1514,14 +1510,14 @@ func TestCallbackEndpoint(t *testing.T) {
wantContentType: htmlContentType,
wantBody: "Unprocessable Entity: required claim in upstream ID token is empty\n",
wantOIDCAuthcodeExchangeCall: &expectedOIDCAuthcodeExchange{
- performedByUpstreamName: happyUpstreamIDPName,
- args: happyExchangeAndValidateTokensArgs,
+ performedByUpstreamName: happyOIDCUpstreamIDPName,
+ args: happyOIDCUpstreamExchangeAuthcodeAndValidateTokenArgs,
},
},
{
name: "upstream ID token has an non-string iss claim when using default username claim config",
idps: testidplister.NewUpstreamIDPListerBuilder().WithOIDC(
- happyUpstream().WithIDTokenClaim("iss", 42).WithoutUsernameClaim().Build(),
+ happyOIDCUpstream().WithIDTokenClaim("iss", 42).WithoutUsernameClaim().Build(),
),
method: http.MethodGet,
path: newRequestPath().WithState(happyState).String(),
@@ -1530,14 +1526,14 @@ func TestCallbackEndpoint(t *testing.T) {
wantContentType: htmlContentType,
wantBody: "Unprocessable Entity: required claim in upstream ID token has invalid format\n",
wantOIDCAuthcodeExchangeCall: &expectedOIDCAuthcodeExchange{
- performedByUpstreamName: happyUpstreamIDPName,
- args: happyExchangeAndValidateTokensArgs,
+ performedByUpstreamName: happyOIDCUpstreamIDPName,
+ args: happyOIDCUpstreamExchangeAuthcodeAndValidateTokenArgs,
},
},
{
name: "upstream ID token does not contain sub claim when using default username claim config",
idps: testidplister.NewUpstreamIDPListerBuilder().WithOIDC(
- happyUpstream().WithoutIDTokenClaim("sub").WithoutUsernameClaim().Build(),
+ happyOIDCUpstream().WithoutIDTokenClaim("sub").WithoutUsernameClaim().Build(),
),
method: http.MethodGet,
path: newRequestPath().WithState(happyState).String(),
@@ -1546,14 +1542,14 @@ func TestCallbackEndpoint(t *testing.T) {
wantContentType: htmlContentType,
wantBody: "Unprocessable Entity: required claim in upstream ID token missing\n",
wantOIDCAuthcodeExchangeCall: &expectedOIDCAuthcodeExchange{
- performedByUpstreamName: happyUpstreamIDPName,
- args: happyExchangeAndValidateTokensArgs,
+ performedByUpstreamName: happyOIDCUpstreamIDPName,
+ args: happyOIDCUpstreamExchangeAuthcodeAndValidateTokenArgs,
},
},
{
name: "upstream ID token does has an empty string value for sub claim when using default username claim config",
idps: testidplister.NewUpstreamIDPListerBuilder().WithOIDC(
- happyUpstream().WithIDTokenClaim("sub", "").WithoutUsernameClaim().Build(),
+ happyOIDCUpstream().WithIDTokenClaim("sub", "").WithoutUsernameClaim().Build(),
),
method: http.MethodGet,
path: newRequestPath().WithState(happyState).String(),
@@ -1562,14 +1558,14 @@ func TestCallbackEndpoint(t *testing.T) {
wantContentType: htmlContentType,
wantBody: "Unprocessable Entity: required claim in upstream ID token is empty\n",
wantOIDCAuthcodeExchangeCall: &expectedOIDCAuthcodeExchange{
- performedByUpstreamName: happyUpstreamIDPName,
- args: happyExchangeAndValidateTokensArgs,
+ performedByUpstreamName: happyOIDCUpstreamIDPName,
+ args: happyOIDCUpstreamExchangeAuthcodeAndValidateTokenArgs,
},
},
{
name: "upstream ID token has an non-string sub claim when using default username claim config",
idps: testidplister.NewUpstreamIDPListerBuilder().WithOIDC(
- happyUpstream().WithIDTokenClaim("sub", 42).WithoutUsernameClaim().Build(),
+ happyOIDCUpstream().WithIDTokenClaim("sub", 42).WithoutUsernameClaim().Build(),
),
method: http.MethodGet,
path: newRequestPath().WithState(happyState).String(),
@@ -1578,14 +1574,14 @@ func TestCallbackEndpoint(t *testing.T) {
wantContentType: htmlContentType,
wantBody: "Unprocessable Entity: required claim in upstream ID token has invalid format\n",
wantOIDCAuthcodeExchangeCall: &expectedOIDCAuthcodeExchange{
- performedByUpstreamName: happyUpstreamIDPName,
- args: happyExchangeAndValidateTokensArgs,
+ performedByUpstreamName: happyOIDCUpstreamIDPName,
+ args: happyOIDCUpstreamExchangeAuthcodeAndValidateTokenArgs,
},
},
{
name: "upstream ID token contains groups claim with weird format",
idps: testidplister.NewUpstreamIDPListerBuilder().WithOIDC(
- happyUpstream().WithIDTokenClaim(oidcUpstreamGroupsClaim, 42).Build(),
+ happyOIDCUpstream().WithIDTokenClaim(oidcUpstreamGroupsClaim, 42).Build(),
),
method: http.MethodGet,
path: newRequestPath().WithState(happyState).String(),
@@ -1594,14 +1590,14 @@ func TestCallbackEndpoint(t *testing.T) {
wantContentType: htmlContentType,
wantBody: "Unprocessable Entity: required claim in upstream ID token has invalid format\n",
wantOIDCAuthcodeExchangeCall: &expectedOIDCAuthcodeExchange{
- performedByUpstreamName: happyUpstreamIDPName,
- args: happyExchangeAndValidateTokensArgs,
+ performedByUpstreamName: happyOIDCUpstreamIDPName,
+ args: happyOIDCUpstreamExchangeAuthcodeAndValidateTokenArgs,
},
},
{
name: "upstream ID token contains groups claim where one element is invalid",
idps: testidplister.NewUpstreamIDPListerBuilder().WithOIDC(
- happyUpstream().WithIDTokenClaim(oidcUpstreamGroupsClaim, []interface{}{"foo", 7}).Build(),
+ happyOIDCUpstream().WithIDTokenClaim(oidcUpstreamGroupsClaim, []interface{}{"foo", 7}).Build(),
),
method: http.MethodGet,
path: newRequestPath().WithState(happyState).String(),
@@ -1610,14 +1606,14 @@ func TestCallbackEndpoint(t *testing.T) {
wantContentType: htmlContentType,
wantBody: "Unprocessable Entity: required claim in upstream ID token has invalid format\n",
wantOIDCAuthcodeExchangeCall: &expectedOIDCAuthcodeExchange{
- performedByUpstreamName: happyUpstreamIDPName,
- args: happyExchangeAndValidateTokensArgs,
+ performedByUpstreamName: happyOIDCUpstreamIDPName,
+ args: happyOIDCUpstreamExchangeAuthcodeAndValidateTokenArgs,
},
},
{
name: "upstream ID token contains groups claim with invalid null type",
idps: testidplister.NewUpstreamIDPListerBuilder().WithOIDC(
- happyUpstream().WithIDTokenClaim(oidcUpstreamGroupsClaim, nil).Build(),
+ happyOIDCUpstream().WithIDTokenClaim(oidcUpstreamGroupsClaim, nil).Build(),
),
method: http.MethodGet,
path: newRequestPath().WithState(happyState).String(),
@@ -1626,14 +1622,14 @@ func TestCallbackEndpoint(t *testing.T) {
wantContentType: htmlContentType,
wantBody: "Unprocessable Entity: required claim in upstream ID token has invalid format\n",
wantOIDCAuthcodeExchangeCall: &expectedOIDCAuthcodeExchange{
- performedByUpstreamName: happyUpstreamIDPName,
- args: happyExchangeAndValidateTokensArgs,
+ performedByUpstreamName: happyOIDCUpstreamIDPName,
+ args: happyOIDCUpstreamExchangeAuthcodeAndValidateTokenArgs,
},
},
{
name: "using identity transformations which reject the authentication",
idps: testidplister.NewUpstreamIDPListerBuilder().
- WithOIDC(happyUpstream().WithTransformsForFederationDomain(rejectAuthPipeline).Build()),
+ WithOIDC(happyOIDCUpstream().WithTransformsForFederationDomain(rejectAuthPipeline).Build()),
method: http.MethodGet,
path: newRequestPath().WithState(happyState).String(),
csrfCookie: happyCSRFCookie,
@@ -1641,8 +1637,8 @@ func TestCallbackEndpoint(t *testing.T) {
wantContentType: htmlContentType,
wantBody: "Unprocessable Entity: configured identity policy rejected this authentication: authentication was rejected by a configured policy\n",
wantOIDCAuthcodeExchangeCall: &expectedOIDCAuthcodeExchange{
- performedByUpstreamName: happyUpstreamIDPName,
- args: happyExchangeAndValidateTokensArgs,
+ performedByUpstreamName: happyOIDCUpstreamIDPName,
+ args: happyOIDCUpstreamExchangeAuthcodeAndValidateTokenArgs,
},
},
}
@@ -1816,28 +1812,28 @@ func (r *requestPath) String() string {
return path + params.Encode()
}
-func happyUpstreamStateParam() *oidctestutil.UpstreamStateParamBuilder {
+func happyOIDCUpstreamStateParam() *oidctestutil.UpstreamStateParamBuilder {
return &oidctestutil.UpstreamStateParamBuilder{
- U: happyUpstreamIDPName,
+ U: happyOIDCUpstreamIDPName,
P: happyDownstreamRequestParams,
T: "oidc",
N: happyDownstreamNonce,
C: happyDownstreamCSRF,
- K: happyDownstreamPKCE,
+ K: happyDownstreamPKCEVerifier,
V: happyDownstreamStateVersion,
}
}
-func happyUpstreamStateParamForDynamicClient() *oidctestutil.UpstreamStateParamBuilder {
- p := happyUpstreamStateParam()
+func happyOIDCUpstreamStateParamForDynamicClient() *oidctestutil.UpstreamStateParamBuilder {
+ p := happyOIDCUpstreamStateParam()
p.P = happyDownstreamRequestParamsForDynamicClient
return p
}
-func happyUpstream() *oidctestutil.TestUpstreamOIDCIdentityProviderBuilder {
+func happyOIDCUpstream() *oidctestutil.TestUpstreamOIDCIdentityProviderBuilder {
return oidctestutil.NewTestUpstreamOIDCIdentityProviderBuilder().
- WithName(happyUpstreamIDPName).
- WithResourceUID(happyUpstreamIDPResourceUID).
+ WithName(happyOIDCUpstreamIDPName).
+ WithResourceUID(happyOIDCUpstreamIDPResourceUID).
WithClientID("some-client-id").
WithScopes([]string{"scope1", "scope2"}).
WithUsernameClaim(oidcUpstreamUsernameClaim).
@@ -1852,6 +1848,14 @@ func happyUpstream() *oidctestutil.TestUpstreamOIDCIdentityProviderBuilder {
WithPasswordGrantError(errors.New("the callback endpoint should not use password grants"))
}
+func happyGitHubUpstream() *oidctestutil.TestUpstreamGitHubIdentityProviderBuilder {
+ return oidctestutil.NewTestUpstreamGitHubIdentityProviderBuilder().
+ WithName(happyGithubIDPName).
+ WithResourceUID(happyGithubIDPResourceUID).
+ WithClientID("some-client-id").
+ WithScopes([]string{"these", "scopes", "appear", "unused"})
+}
+
func shallowCopyAndModifyQuery(query url.Values, modifications map[string]string) url.Values {
copied := url.Values{}
for key, value := range query {