Skip to content

Commit

Permalink
Add support for stale directive for digest authenticator (#80)
Browse files Browse the repository at this point in the history
* Improve digest authenticator to handle stale directive
  • Loading branch information
hustern authored Jul 23, 2024
1 parent f9157db commit bce1461
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 1 deletion.
21 changes: 20 additions & 1 deletion digestAuth.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,12 @@ func (d *DigestAuth) Authorize(c *http.Client, rq *http.Request, path string) er
// Verify checks for authentication issues and may trigger a re-authentication
func (d *DigestAuth) Verify(c *http.Client, rs *http.Response, path string) (redo bool, err error) {
if rs.StatusCode == 401 {
err = NewPathError("Authorize", path, rs.StatusCode)
if isStaled(rs) {
redo = true
err = ErrAuthChanged
} else {
err = NewPathError("Authorize", path, rs.StatusCode)
}
}
return
}
Expand Down Expand Up @@ -162,3 +167,17 @@ func getDigestAuthorization(digestParts map[string]string) string {

return authorization
}

func isStaled(rs *http.Response) bool {
header := rs.Header.Get("Www-Authenticate")
if len(header) > 0 {
directives := strings.Split(header, ",")
for i := range directives {
name, value, _ := strings.Cut(strings.Trim(directives[i], " "), "=")
if strings.EqualFold(name, "stale") {
return strings.EqualFold(value, "true")
}
}
}
return false
}
40 changes: 40 additions & 0 deletions digestAuth_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package gowebdav

import (
"errors"
"net/http"
"strings"
"testing"
Expand Down Expand Up @@ -33,3 +34,42 @@ func TestDigestAuthAuthorize(t *testing.T) {
t.Error("got wrong Authorization header: " + rq.Header.Get("Authorization"))
}
}

func TestDigestAuthVerify(t *testing.T) {
a := &DigestAuth{user: "user", pw: "password", digestParts: make(map[string]string, 0)}

// Nominal test: 200 OK response
rs := &http.Response{
Status: "200 OK",
StatusCode: http.StatusOK,
}

redo, err := a.Verify(nil, rs, "/")

if err != nil {
t.Errorf("got error: %v, want nil", err)
}

if redo {
t.Errorf("got redo: %t, want false", redo)
}

// Digest expiration test: 401 Unauthorized response with stale directive in WWW-Authenticate header
rs = &http.Response{
Status: "401 Unauthorized",
StatusCode: http.StatusUnauthorized,
Header: http.Header{
"Www-Authenticate": []string{"Digest realm=\"webdav\", nonce=\"YVvALpkdBgA=931bbf2b6fa9dda227361dba38a735f005fd9f97\", algorithm=MD5, qop=\"auth\", stale=true"},
},
}

redo, err = a.Verify(nil, rs, "/")

if !errors.Is(err, ErrAuthChanged) {
t.Errorf("got error: %v, want ErrAuthChanged", err)
}

if !redo {
t.Errorf("got redo: %t, want true", redo)
}
}

0 comments on commit bce1461

Please sign in to comment.