diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index d6b985d1..bb7c51ec 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -10,8 +10,9 @@ jobs: golangci: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 + - uses: actions/setup-go@v5 - name: golangci-lint - uses: golangci/golangci-lint-action@v3 + uses: golangci/golangci-lint-action@v6 with: version: v1.54.2 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e6e91273..49d68ce8 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -10,10 +10,10 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - go: [ '1.19.x', '1.20.x', '1.21.x'] + go: [ '1.19.x', '1.20.x', '1.21.x', '1.22.x' ] steps: - uses: actions/checkout@v4 - - uses: actions/setup-go@v4 + - uses: actions/setup-go@v5 with: go-version: ${{ matrix.go }} - run: go test -v ./... diff --git a/samlsp/middleware.go b/samlsp/middleware.go index f5eabb16..6f32fa3a 100644 --- a/samlsp/middleware.go +++ b/samlsp/middleware.go @@ -180,7 +180,7 @@ func (m *Middleware) HandleStartAuthFlow(w http.ResponseWriter, r *http.Request) w.Header().Add("Content-type", "text/html") var buf bytes.Buffer buf.WriteString(``) - buf.Write(authReq.Post(relayState)) + buf.Write(authReq.Post(relayState, "")) buf.WriteString(``) if _, err := w.Write(buf.Bytes()); err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) diff --git a/service_provider.go b/service_provider.go index c177601c..51fe618b 100644 --- a/service_provider.go +++ b/service_provider.go @@ -499,16 +499,16 @@ func (sp *ServiceProvider) SignAuthnRequest(req *AuthnRequest) error { // MakePostAuthenticationRequest creates a SAML authentication request using // the HTTP-POST binding. It returns HTML text representing an HTML form that // can be sent presented to a browser to initiate the login process. -func (sp *ServiceProvider) MakePostAuthenticationRequest(relayState string) ([]byte, error) { +func (sp *ServiceProvider) MakePostAuthenticationRequest(relayState, nonce string) ([]byte, error) { req, err := sp.MakeAuthenticationRequest(sp.GetSSOBindingLocation(HTTPPostBinding), HTTPPostBinding, HTTPPostBinding) if err != nil { return nil, err } - return req.Post(relayState), nil + return req.Post(relayState, nonce), nil } // Post returns an HTML form suitable for using the HTTP-POST binding with the request -func (r *AuthnRequest) Post(relayState string) []byte { +func (r *AuthnRequest) Post(relayState, nonce string) []byte { doc := etree.NewDocument() doc.SetRoot(r.Element()) reqBuf, err := doc.WriteToBytes() @@ -523,16 +523,18 @@ func (r *AuthnRequest) Post(relayState string) []byte { `` + `` + `` + - ``)) data := struct { URL string SAMLRequest string RelayState string + Nonce string }{ URL: r.Destination, SAMLRequest: encodedReqBuf, RelayState: relayState, + Nonce: nonce, } rv := bytes.Buffer{} diff --git a/service_provider_test.go b/service_provider_test.go index d4a9943b..cab8c0da 100644 --- a/service_provider_test.go +++ b/service_provider_test.go @@ -261,7 +261,28 @@ func TestSPCanProducePostRequest(t *testing.T) { err := xml.Unmarshal(test.IDPMetadata, &s.IDPMetadata) assert.Check(t, err) - form, err := s.MakePostAuthenticationRequest("relayState") + form, err := s.MakePostAuthenticationRequest("relayState", "") + assert.Check(t, err) + golden.Assert(t, string(form), t.Name()+"_form") +} + +func TestSPCanProducePostRequestWithNonce(t *testing.T) { + test := NewServiceProviderTest(t) + TimeNow = func() time.Time { + rv, _ := time.Parse("Mon Jan 2 15:04:05 UTC 2006", "Mon Dec 1 01:31:21 UTC 2015") + return rv + } + s := ServiceProvider{ + Key: test.Key, + Certificate: test.Certificate, + MetadataURL: mustParseURL("https://15661444.ngrok.io/saml2/metadata"), + AcsURL: mustParseURL("https://15661444.ngrok.io/saml2/acs"), + IDPMetadata: &EntityDescriptor{}, + } + err := xml.Unmarshal(test.IDPMetadata, &s.IDPMetadata) + assert.Check(t, err) + + form, err := s.MakePostAuthenticationRequest("relayState", "nonce-123") assert.Check(t, err) golden.Assert(t, string(form), t.Name()+"_form") } @@ -320,7 +341,7 @@ func TestSPCanProduceSignedRequestPostBinding(t *testing.T) { err := xml.Unmarshal(test.IDPMetadata, &s.IDPMetadata) assert.Check(t, err) - htmlForm, err := s.MakePostAuthenticationRequest("relayState") + htmlForm, err := s.MakePostAuthenticationRequest("relayState", "nonce-123") assert.Check(t, err) rgx := regexp.MustCompile(`\"SAMLRequest\" value=\"(.*?)\" /> \ No newline at end of file