URL query escape the upstream OIDC subject in the downstream subject URL
This commit is contained in:
parent
033e1f0399
commit
81148866e0
@ -228,7 +228,7 @@ func getSubjectAndUsernameFromUpstreamIDToken(
|
|||||||
return "", "", httperr.New(http.StatusUnprocessableEntity, "subject claim in upstream ID token has invalid format")
|
return "", "", httperr.New(http.StatusUnprocessableEntity, "subject claim in upstream ID token has invalid format")
|
||||||
}
|
}
|
||||||
|
|
||||||
subject := fmt.Sprintf("%s?%s=%s", upstreamIssuerAsString, oidc.IDTokenSubjectClaim, upstreamSubject)
|
subject := downstreamSubjectFromUpstreamOIDC(upstreamIssuerAsString, upstreamSubject)
|
||||||
|
|
||||||
usernameClaimName := upstreamIDPConfig.GetUsernameClaim()
|
usernameClaimName := upstreamIDPConfig.GetUsernameClaim()
|
||||||
if usernameClaimName == "" {
|
if usernameClaimName == "" {
|
||||||
@ -282,6 +282,10 @@ func getSubjectAndUsernameFromUpstreamIDToken(
|
|||||||
return subject, username, nil
|
return subject, username, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func downstreamSubjectFromUpstreamOIDC(upstreamIssuerAsString string, upstreamSubject string) string {
|
||||||
|
return fmt.Sprintf("%s?%s=%s", upstreamIssuerAsString, oidc.IDTokenSubjectClaim, url.QueryEscape(upstreamSubject))
|
||||||
|
}
|
||||||
|
|
||||||
func getGroupsFromUpstreamIDToken(
|
func getGroupsFromUpstreamIDToken(
|
||||||
upstreamIDPConfig provider.UpstreamOIDCIdentityProviderI,
|
upstreamIDPConfig provider.UpstreamOIDCIdentityProviderI,
|
||||||
idTokenClaims map[string]interface{},
|
idTokenClaims map[string]interface{},
|
||||||
|
@ -29,7 +29,8 @@ const (
|
|||||||
happyUpstreamIDPName = "upstream-idp-name"
|
happyUpstreamIDPName = "upstream-idp-name"
|
||||||
|
|
||||||
upstreamIssuer = "https://my-upstream-issuer.com"
|
upstreamIssuer = "https://my-upstream-issuer.com"
|
||||||
upstreamSubject = "abc123-some-guid"
|
upstreamSubject = "abc123-some guid" // has a space character which should get escaped in URL
|
||||||
|
queryEscapedUpstreamSubject = "abc123-some+guid"
|
||||||
upstreamUsername = "test-pinniped-username"
|
upstreamUsername = "test-pinniped-username"
|
||||||
|
|
||||||
upstreamUsernameClaim = "the-user-claim"
|
upstreamUsernameClaim = "the-user-claim"
|
||||||
@ -141,7 +142,7 @@ func TestCallbackEndpoint(t *testing.T) {
|
|||||||
wantStatus: http.StatusFound,
|
wantStatus: http.StatusFound,
|
||||||
wantRedirectLocationRegexp: happyDownstreamRedirectLocationRegexp,
|
wantRedirectLocationRegexp: happyDownstreamRedirectLocationRegexp,
|
||||||
wantBody: "",
|
wantBody: "",
|
||||||
wantDownstreamIDTokenSubject: upstreamIssuer + "?sub=" + upstreamSubject,
|
wantDownstreamIDTokenSubject: upstreamIssuer + "?sub=" + queryEscapedUpstreamSubject,
|
||||||
wantDownstreamIDTokenUsername: upstreamUsername,
|
wantDownstreamIDTokenUsername: upstreamUsername,
|
||||||
wantDownstreamIDTokenGroups: upstreamGroupMembership,
|
wantDownstreamIDTokenGroups: upstreamGroupMembership,
|
||||||
wantDownstreamRequestedScopes: happyDownstreamScopesRequested,
|
wantDownstreamRequestedScopes: happyDownstreamScopesRequested,
|
||||||
@ -160,8 +161,8 @@ func TestCallbackEndpoint(t *testing.T) {
|
|||||||
wantStatus: http.StatusFound,
|
wantStatus: http.StatusFound,
|
||||||
wantRedirectLocationRegexp: happyDownstreamRedirectLocationRegexp,
|
wantRedirectLocationRegexp: happyDownstreamRedirectLocationRegexp,
|
||||||
wantBody: "",
|
wantBody: "",
|
||||||
wantDownstreamIDTokenSubject: upstreamIssuer + "?sub=" + upstreamSubject,
|
wantDownstreamIDTokenSubject: upstreamIssuer + "?sub=" + queryEscapedUpstreamSubject,
|
||||||
wantDownstreamIDTokenUsername: upstreamIssuer + "?sub=" + upstreamSubject,
|
wantDownstreamIDTokenUsername: upstreamIssuer + "?sub=" + queryEscapedUpstreamSubject,
|
||||||
wantDownstreamIDTokenGroups: []string{},
|
wantDownstreamIDTokenGroups: []string{},
|
||||||
wantDownstreamRequestedScopes: happyDownstreamScopesRequested,
|
wantDownstreamRequestedScopes: happyDownstreamScopesRequested,
|
||||||
wantDownstreamGrantedScopes: happyDownstreamScopesGranted,
|
wantDownstreamGrantedScopes: happyDownstreamScopesGranted,
|
||||||
@ -180,7 +181,7 @@ func TestCallbackEndpoint(t *testing.T) {
|
|||||||
wantStatus: http.StatusFound,
|
wantStatus: http.StatusFound,
|
||||||
wantRedirectLocationRegexp: happyDownstreamRedirectLocationRegexp,
|
wantRedirectLocationRegexp: happyDownstreamRedirectLocationRegexp,
|
||||||
wantBody: "",
|
wantBody: "",
|
||||||
wantDownstreamIDTokenSubject: upstreamIssuer + "?sub=" + upstreamSubject,
|
wantDownstreamIDTokenSubject: upstreamIssuer + "?sub=" + queryEscapedUpstreamSubject,
|
||||||
wantDownstreamIDTokenUsername: "joe@whitehouse.gov",
|
wantDownstreamIDTokenUsername: "joe@whitehouse.gov",
|
||||||
wantDownstreamIDTokenGroups: upstreamGroupMembership,
|
wantDownstreamIDTokenGroups: upstreamGroupMembership,
|
||||||
wantDownstreamRequestedScopes: happyDownstreamScopesRequested,
|
wantDownstreamRequestedScopes: happyDownstreamScopesRequested,
|
||||||
@ -201,7 +202,7 @@ func TestCallbackEndpoint(t *testing.T) {
|
|||||||
wantStatus: http.StatusFound,
|
wantStatus: http.StatusFound,
|
||||||
wantRedirectLocationRegexp: happyDownstreamRedirectLocationRegexp,
|
wantRedirectLocationRegexp: happyDownstreamRedirectLocationRegexp,
|
||||||
wantBody: "",
|
wantBody: "",
|
||||||
wantDownstreamIDTokenSubject: upstreamIssuer + "?sub=" + upstreamSubject,
|
wantDownstreamIDTokenSubject: upstreamIssuer + "?sub=" + queryEscapedUpstreamSubject,
|
||||||
wantDownstreamIDTokenUsername: "joe@whitehouse.gov",
|
wantDownstreamIDTokenUsername: "joe@whitehouse.gov",
|
||||||
wantDownstreamIDTokenGroups: upstreamGroupMembership,
|
wantDownstreamIDTokenGroups: upstreamGroupMembership,
|
||||||
wantDownstreamRequestedScopes: happyDownstreamScopesRequested,
|
wantDownstreamRequestedScopes: happyDownstreamScopesRequested,
|
||||||
@ -223,7 +224,7 @@ func TestCallbackEndpoint(t *testing.T) {
|
|||||||
wantStatus: http.StatusFound, // succeed despite `email_verified=false` because we're not using the email claim for anything
|
wantStatus: http.StatusFound, // succeed despite `email_verified=false` because we're not using the email claim for anything
|
||||||
wantRedirectLocationRegexp: happyDownstreamRedirectLocationRegexp,
|
wantRedirectLocationRegexp: happyDownstreamRedirectLocationRegexp,
|
||||||
wantBody: "",
|
wantBody: "",
|
||||||
wantDownstreamIDTokenSubject: upstreamIssuer + "?sub=" + upstreamSubject,
|
wantDownstreamIDTokenSubject: upstreamIssuer + "?sub=" + queryEscapedUpstreamSubject,
|
||||||
wantDownstreamIDTokenUsername: "joe",
|
wantDownstreamIDTokenUsername: "joe",
|
||||||
wantDownstreamIDTokenGroups: upstreamGroupMembership,
|
wantDownstreamIDTokenGroups: upstreamGroupMembership,
|
||||||
wantDownstreamRequestedScopes: happyDownstreamScopesRequested,
|
wantDownstreamRequestedScopes: happyDownstreamScopesRequested,
|
||||||
@ -268,7 +269,7 @@ func TestCallbackEndpoint(t *testing.T) {
|
|||||||
wantStatus: http.StatusFound,
|
wantStatus: http.StatusFound,
|
||||||
wantRedirectLocationRegexp: happyDownstreamRedirectLocationRegexp,
|
wantRedirectLocationRegexp: happyDownstreamRedirectLocationRegexp,
|
||||||
wantBody: "",
|
wantBody: "",
|
||||||
wantDownstreamIDTokenSubject: upstreamIssuer + "?sub=" + upstreamSubject,
|
wantDownstreamIDTokenSubject: upstreamIssuer + "?sub=" + queryEscapedUpstreamSubject,
|
||||||
wantDownstreamIDTokenUsername: upstreamSubject,
|
wantDownstreamIDTokenUsername: upstreamSubject,
|
||||||
wantDownstreamIDTokenGroups: upstreamGroupMembership,
|
wantDownstreamIDTokenGroups: upstreamGroupMembership,
|
||||||
wantDownstreamRequestedScopes: happyDownstreamScopesRequested,
|
wantDownstreamRequestedScopes: happyDownstreamScopesRequested,
|
||||||
@ -287,7 +288,7 @@ func TestCallbackEndpoint(t *testing.T) {
|
|||||||
wantStatus: http.StatusFound,
|
wantStatus: http.StatusFound,
|
||||||
wantRedirectLocationRegexp: happyDownstreamRedirectLocationRegexp,
|
wantRedirectLocationRegexp: happyDownstreamRedirectLocationRegexp,
|
||||||
wantBody: "",
|
wantBody: "",
|
||||||
wantDownstreamIDTokenSubject: upstreamIssuer + "?sub=" + upstreamSubject,
|
wantDownstreamIDTokenSubject: upstreamIssuer + "?sub=" + queryEscapedUpstreamSubject,
|
||||||
wantDownstreamIDTokenUsername: upstreamUsername,
|
wantDownstreamIDTokenUsername: upstreamUsername,
|
||||||
wantDownstreamIDTokenGroups: []string{"notAnArrayGroup1 notAnArrayGroup2"},
|
wantDownstreamIDTokenGroups: []string{"notAnArrayGroup1 notAnArrayGroup2"},
|
||||||
wantDownstreamRequestedScopes: happyDownstreamScopesRequested,
|
wantDownstreamRequestedScopes: happyDownstreamScopesRequested,
|
||||||
@ -306,7 +307,7 @@ func TestCallbackEndpoint(t *testing.T) {
|
|||||||
wantStatus: http.StatusFound,
|
wantStatus: http.StatusFound,
|
||||||
wantRedirectLocationRegexp: happyDownstreamRedirectLocationRegexp,
|
wantRedirectLocationRegexp: happyDownstreamRedirectLocationRegexp,
|
||||||
wantBody: "",
|
wantBody: "",
|
||||||
wantDownstreamIDTokenSubject: upstreamIssuer + "?sub=" + upstreamSubject,
|
wantDownstreamIDTokenSubject: upstreamIssuer + "?sub=" + queryEscapedUpstreamSubject,
|
||||||
wantDownstreamIDTokenUsername: upstreamUsername,
|
wantDownstreamIDTokenUsername: upstreamUsername,
|
||||||
wantDownstreamIDTokenGroups: []string{"group1", "group2"},
|
wantDownstreamIDTokenGroups: []string{"group1", "group2"},
|
||||||
wantDownstreamRequestedScopes: happyDownstreamScopesRequested,
|
wantDownstreamRequestedScopes: happyDownstreamScopesRequested,
|
||||||
@ -445,7 +446,7 @@ func TestCallbackEndpoint(t *testing.T) {
|
|||||||
wantStatus: http.StatusFound,
|
wantStatus: http.StatusFound,
|
||||||
wantRedirectLocationRegexp: downstreamRedirectURI + `\?code=([^&]+)&scope=&state=` + happyDownstreamState,
|
wantRedirectLocationRegexp: downstreamRedirectURI + `\?code=([^&]+)&scope=&state=` + happyDownstreamState,
|
||||||
wantDownstreamIDTokenUsername: upstreamUsername,
|
wantDownstreamIDTokenUsername: upstreamUsername,
|
||||||
wantDownstreamIDTokenSubject: upstreamIssuer + "?sub=" + upstreamSubject,
|
wantDownstreamIDTokenSubject: upstreamIssuer + "?sub=" + queryEscapedUpstreamSubject,
|
||||||
wantDownstreamRequestedScopes: []string{"profile", "email"},
|
wantDownstreamRequestedScopes: []string{"profile", "email"},
|
||||||
wantDownstreamIDTokenGroups: upstreamGroupMembership,
|
wantDownstreamIDTokenGroups: upstreamGroupMembership,
|
||||||
wantDownstreamNonce: downstreamNonce,
|
wantDownstreamNonce: downstreamNonce,
|
||||||
@ -467,7 +468,7 @@ func TestCallbackEndpoint(t *testing.T) {
|
|||||||
wantStatus: http.StatusFound,
|
wantStatus: http.StatusFound,
|
||||||
wantRedirectLocationRegexp: downstreamRedirectURI + `\?code=([^&]+)&scope=openid\+offline_access&state=` + happyDownstreamState,
|
wantRedirectLocationRegexp: downstreamRedirectURI + `\?code=([^&]+)&scope=openid\+offline_access&state=` + happyDownstreamState,
|
||||||
wantDownstreamIDTokenUsername: upstreamUsername,
|
wantDownstreamIDTokenUsername: upstreamUsername,
|
||||||
wantDownstreamIDTokenSubject: upstreamIssuer + "?sub=" + upstreamSubject,
|
wantDownstreamIDTokenSubject: upstreamIssuer + "?sub=" + queryEscapedUpstreamSubject,
|
||||||
wantDownstreamRequestedScopes: []string{"openid", "offline_access"},
|
wantDownstreamRequestedScopes: []string{"openid", "offline_access"},
|
||||||
wantDownstreamGrantedScopes: []string{"openid", "offline_access"},
|
wantDownstreamGrantedScopes: []string{"openid", "offline_access"},
|
||||||
wantDownstreamIDTokenGroups: upstreamGroupMembership,
|
wantDownstreamIDTokenGroups: upstreamGroupMembership,
|
||||||
@ -548,7 +549,7 @@ func TestCallbackEndpoint(t *testing.T) {
|
|||||||
wantStatus: http.StatusFound,
|
wantStatus: http.StatusFound,
|
||||||
wantRedirectLocationRegexp: happyDownstreamRedirectLocationRegexp,
|
wantRedirectLocationRegexp: happyDownstreamRedirectLocationRegexp,
|
||||||
wantBody: "",
|
wantBody: "",
|
||||||
wantDownstreamIDTokenSubject: upstreamIssuer + "?sub=" + upstreamSubject,
|
wantDownstreamIDTokenSubject: upstreamIssuer + "?sub=" + queryEscapedUpstreamSubject,
|
||||||
wantDownstreamIDTokenUsername: upstreamUsername,
|
wantDownstreamIDTokenUsername: upstreamUsername,
|
||||||
wantDownstreamRequestedScopes: happyDownstreamScopesRequested,
|
wantDownstreamRequestedScopes: happyDownstreamScopesRequested,
|
||||||
wantDownstreamGrantedScopes: happyDownstreamScopesGranted,
|
wantDownstreamGrantedScopes: happyDownstreamScopesGranted,
|
||||||
|
Loading…
Reference in New Issue
Block a user