Skip to content

Commit

Permalink
Add nonce param to MakePostAuthenticationRequest (#36)
Browse files Browse the repository at this point in the history
  • Loading branch information
mgyongyosi authored May 23, 2024
1 parent a6c0e9b commit cc370b9
Show file tree
Hide file tree
Showing 6 changed files with 36 additions and 11 deletions.
5 changes: 3 additions & 2 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
4 changes: 2 additions & 2 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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 ./...
2 changes: 1 addition & 1 deletion samlsp/middleware.go
Original file line number Diff line number Diff line change
Expand Up @@ -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(`<!DOCTYPE html><html><body>`)
buf.Write(authReq.Post(relayState))
buf.Write(authReq.Post(relayState, ""))
buf.WriteString(`</body></html>`)
if _, err := w.Write(buf.Bytes()); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
Expand Down
10 changes: 6 additions & 4 deletions service_provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand All @@ -523,16 +523,18 @@ func (r *AuthnRequest) Post(relayState string) []byte {
`<input type="hidden" name="RelayState" value="{{.RelayState}}" />` +
`<input id="SAMLSubmitButton" type="submit" value="Submit" />` +
`</form>` +
`<script>document.getElementById('SAMLSubmitButton').style.visibility="hidden";` +
`<script{{ if ne .Nonce "" }} nonce="{{ .Nonce }}"{{ end }}>document.getElementById('SAMLSubmitButton').style.visibility="hidden";` +
`document.getElementById('SAMLRequestForm').submit();</script>`))
data := struct {
URL string
SAMLRequest string
RelayState string
Nonce string
}{
URL: r.Destination,
SAMLRequest: encodedReqBuf,
RelayState: relayState,
Nonce: nonce,
}

rv := bytes.Buffer{}
Expand Down
25 changes: 23 additions & 2 deletions service_provider_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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")
}
Expand Down Expand Up @@ -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=\"(.*?)\" /><input`)
rs := rgx.FindStringSubmatch(string(htmlForm))
Expand Down
1 change: 1 addition & 0 deletions testdata/TestSPCanProducePostRequestWithNonce_form
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<form method="post" action="https://idp.testshib.org/idp/profile/SAML2/POST/SSO" id="SAMLRequestForm"><input type="hidden" name="SAMLRequest" value="PHNhbWxwOkF1dGhuUmVxdWVzdCB4bWxuczpzYW1sPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YXNzZXJ0aW9uIiB4bWxuczpzYW1scD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOnByb3RvY29sIiBJRD0iaWQtMDAwMjA0MDYwODBhMGMwZTEwMTIxNDE2MTgxYTFjMWUyMDIyMjQyNiIgVmVyc2lvbj0iMi4wIiBJc3N1ZUluc3RhbnQ9IjIwMTUtMTItMDFUMDE6MzE6MjFaIiBEZXN0aW5hdGlvbj0iaHR0cHM6Ly9pZHAudGVzdHNoaWIub3JnL2lkcC9wcm9maWxlL1NBTUwyL1BPU1QvU1NPIiBBc3NlcnRpb25Db25zdW1lclNlcnZpY2VVUkw9Imh0dHBzOi8vMTU2NjE0NDQubmdyb2suaW8vc2FtbDIvYWNzIiBQcm90b2NvbEJpbmRpbmc9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDpiaW5kaW5nczpIVFRQLVBPU1QiPjxzYW1sOklzc3VlciBGb3JtYXQ9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDpuYW1laWQtZm9ybWF0OmVudGl0eSI&#43;aHR0cHM6Ly8xNTY2MTQ0NC5uZ3Jvay5pby9zYW1sMi9tZXRhZGF0YTwvc2FtbDpJc3N1ZXI&#43;PHNhbWxwOk5hbWVJRFBvbGljeSBGb3JtYXQ9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDpuYW1laWQtZm9ybWF0OnRyYW5zaWVudCIgQWxsb3dDcmVhdGU9InRydWUiLz48L3NhbWxwOkF1dGhuUmVxdWVzdD4=" /><input type="hidden" name="RelayState" value="relayState" /><input id="SAMLSubmitButton" type="submit" value="Submit" /></form><script nonce="nonce-123">document.getElementById('SAMLSubmitButton').style.visibility="hidden";document.getElementById('SAMLRequestForm').submit();</script>

0 comments on commit cc370b9

Please sign in to comment.