Skip to content

Instantly share code, notes, and snippets.

@chrsmith
Created February 5, 2019 07:11
Show Gist options
  • Save chrsmith/b76ab1718f68fb3988adfb45af11e16c to your computer and use it in GitHub Desktop.
Save chrsmith/b76ab1718f68fb3988adfb45af11e16c to your computer and use it in GitHub Desktop.
WIP - IDP-initiated login tests
// TestIdentityProviderInitiated covers the cases where the SAML login is initiated by the identity provider.
//
// IDP-initiated requests are seen as an unexpected POST request to the AcsURL. It is tricky
// because there may be no "id" found in the claims in the SAML assertions, and the relay state
// may not match what is stored in the middleware's client state.
func (test *MiddlewareTest) TestIdentityProviderInitiated(c *C) {
// This test modifies the AllowIDPInitiated flag for some scenarios. Confirm this is the
// expected default state, and keep it that way after the test completes.
c.Assert(test.Middleware.AllowIDPInitiated, Equals, false)
defer func() {
test.Middleware.AllowIDPInitiated = false
}()
// Modify the test SAML response, removing the "InResponseTo" value, since for
// the IDP-initiated case it will be blank.
idpInitiatedResponse := strings.Replace(
test.SamlResponse,
`InResponseTo="id-9e61753d64e928af5a7a341a97f420c9"`,
`InResponseTo=""`, -1)
scenarios := []idpInitiatedTestScenario{
// If AllowIDPInitiated isn't supported, return a 403.
{AllowIDPInitiated: false, RequestRelayState: "", WantCode: 403},
// If AllowIDPInitiated is, with no relay state, redirect to "/".
{AllowIDPInitiated: true, RequestRelayState: "", WantCode: 302},
// If AllowIDPInitiated is, with relay state, we return a 403. (Not trusting the IDP-provided value.)
{AllowIDPInitiated: true, RequestRelayState: "foo", WantCode: 403},
}
for i, scenario := range scenarios {
c.Logf("=== Starting IDP-iniated test scenario %d\n", i)
test.Middleware.ServiceProvider.Logger.Printf("=== Starting IDP-iniated test scenario %d\n", i)
test.Middleware.AllowIDPInitiated = scenario.AllowIDPInitiated
// Simulate a POST request with the SAML response, but no relay state matching it with
// a sign-in request.
v := &url.Values{}
v.Set("SAMLResponse", base64.StdEncoding.EncodeToString([]byte(idpInitiatedResponse)))
v.Set("RelayState", scenario.RequestRelayState)
req, _ := http.NewRequest("POST", "/saml2/acs", bytes.NewReader([]byte(v.Encode())))
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
resp := httptest.NewRecorder()
test.Middleware.ServeHTTP(resp, req)
c.Assert(resp.Code, Equals, scenario.WantCode)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment