Skip to content

Commit

Permalink
fix cached bugs
Browse files Browse the repository at this point in the history
  • Loading branch information
shaj13 committed Jun 24, 2020
1 parent 6b86b7d commit e640016
Show file tree
Hide file tree
Showing 4 changed files with 160 additions and 15 deletions.
43 changes: 34 additions & 9 deletions auth/strategies/digest/cached.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import (
"github.com/shaj13/go-guardian/store"
)

const extensionKey = "x-go-guardian-digest"

// CachedStrategy caches digest strategy authentication response based on authorization nonce field.
type CachedStrategy struct {
*Strategy
Expand All @@ -28,20 +30,43 @@ func (c *CachedStrategy) Authenticate(ctx context.Context, r *http.Request) (aut
}

if !ok {
info, err = c.Strategy.Authenticate(ctx, r)
if err == nil {
// cache result
err = c.Cache.Store(h.Nonce(), info, r)
info, err := c.Strategy.Authenticate(ctx, r)

if err != nil {
return nil, err
}
}

if err != nil {
return nil, err
ext := info.Extensions()
if ext == nil {
ext = make(map[string][]string)
}

ext[extensionKey] = []string{h.String()}
info.SetExtensions(ext)

// cache result
err = c.Cache.Store(h.Nonce(), info, r)

return info, err
}

if _, ok := info.(auth.Info); !ok {
v, ok := info.(auth.Info)

if !ok {
return nil, errors.NewInvalidType((*auth.Info)(nil), info)
}

return info.(auth.Info), nil
sh := make(Header)
_ = sh.Parse(v.Extensions()[extensionKey][0])

h.SetNC("00000001")
h.SetURI(r.RequestURI)
sh.SetNC("00000001")
sh.SetURI(r.RequestURI)

if err := sh.Compare(h); err != nil {
return nil, err
}

return v, nil
}
35 changes: 29 additions & 6 deletions auth/strategies/digest/cached_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,31 +20,53 @@ func TestNewCahced(t *testing.T) {
name string
expectedErr bool
info interface{}
key string
header string
}{
{
name: "it return error when cache load return error",
expectedErr: true,
header: "error",
header: "Digest nonce=error",
info: nil,
},
{
name: "it return error when user authenticate func return error",
expectedErr: true,
header: "ignore",
header: "Digest nonce=ignore",
info: nil,
},
{
name: "it return error when cache store return error",
expectedErr: true,
header: `Digest username="store-error", realm="t", nonce="1", uri="/", cnonce="1=", nc=00000001, qop=auth, response="a43f3d765159a7248cce617eaaf7c07f", opaque="1"`,
header: `Digest username="a", realm="t", nonce="store-error", uri="/", cnonce="1=", nc=00000001, qop=auth, response="14979b5053904998faf57bc72a1d7a56", opaque="1"`,
info: nil,
},
{
name: "it return error when cache return invalid type",
expectedErr: true,
info: "sample-data",
header: "invalid",
header: "Digest nonce=invalid",
key: "invalid",
},
{
name: "it authinticate user",
expectedErr: false,
info: nil,
header: `Digest username="a", realm="t", nonce="150", uri="/", cnonce="1=", nc=00000001, qop=auth, response="22b46269226822f5edde5a52985679ad", opaque="1"`,
},
{
name: "it authinticate user even if nc, uri changed and load it from cache",
expectedErr: false,
info: auth.NewDefaultUser(
"test",
"1",
nil,
map[string][]string{
extensionKey: {`Digest username="a", realm="t", nonce="150", uri="/abc", cnonce="1=", nc=00000001, qop=auth, response="22b46269226822f5edde5a52985679ad", opaque="1"`},
},
),
key: "150",
header: `Digest username="a", realm="t", nonce="150", uri="/", cnonce="1=", nc=00000002, qop=auth, response="22b46269226822f5edde5a52985679ad", opaque="1"`,
},
}

Expand All @@ -60,7 +82,7 @@ func TestNewCahced(t *testing.T) {
if userName == "error" {
return "", nil, fmt.Errorf("Error #L 51")
}
return "", nil, nil
return "", auth.NewDefaultUser("test", "1", nil, nil), nil
},
Hash: func(algo string) hash.Hash {
return md5.New()
Expand All @@ -71,7 +93,8 @@ func TestNewCahced(t *testing.T) {

r, _ := http.NewRequest("GET", "/", nil)
r.Header.Set("Authorization", tt.header)
_ = cache.Store(tt.header, tt.info, r)

_ = cache.Store(tt.key, tt.info, r)

_, err := s.Authenticate(r.Context(), r)

Expand Down
22 changes: 22 additions & 0 deletions auth/strategies/digest/header.go
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,28 @@ func (h Header) WWWAuthenticate() (string, error) {
return s, nil
}

// Compare server header vs client header returns error if any diff found.
func (h Header) Compare(ch Header) error {
for k, v := range h {
cv := ch[k]
if cv != v {
return fmt.Errorf("Digest: %s Does not match value in provided header", k)
}
}
return nil
}

// String describe header as a string
func (h Header) String() string {
str := "Digest "

for k, v := range h {
str = str + k + "=" + v + ", "
}

return str[:len(str)-2]
}

func secretKey() (string, error) {
secret := make([]byte, 16)
_, err := rand.Read(secret)
Expand Down
75 changes: 75 additions & 0 deletions auth/strategies/digest/header_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,81 @@ func TestParams(t *testing.T) {
}
}

//nolint: lll
func TestCompare(t *testing.T) {
table := []struct {
serverHeader string
clientHeader string
expectedErr bool
}{
{
serverHeader: `Digest username="a", realm="t", nonce="1", uri="/", cnonce="1=", nc=00000001, qop=auth, response="22cf307b29e6318dafba1fc1d564fc12", opaque="1"`,
clientHeader: `Digest username="a", realm="t", nonce="1", uri="/", cnonce="1=", nc=00000001, qop=auth, response="22cf307b29e6318dafba1fc1d564fc12", opaque="1"`,
expectedErr: false,
},
{
serverHeader: `Digest username="a", realm="t", nonce="1", uri="/", cnonce="1=", nc=00000001, qop=auth, response="22cf307b29e6318dafba1fc1d564fc12", opaque="1"`,
clientHeader: `Digest username="b", realm="t", nonce="1", uri="/", cnonce="1=", nc=00000001, qop=auth, response="22cf307b29e6318dafba1fc1d564fc12", opaque="1"`,
expectedErr: true,
},
{
serverHeader: `Digest username="a", realm="c", nonce="1", uri="/", cnonce="1=", nc=00000001, qop=auth, response="22cf307b29e6318dafba1fc1d564fc12", opaque="1"`,
clientHeader: `Digest username="a", realm="t", nonce="1", uri="/", cnonce="1=", nc=00000001, qop=auth, response="22cf307b29e6318dafba1fc1d564fc12", opaque="1"`,
expectedErr: true,
},
{
serverHeader: `Digest username="a", realm="t", nonce="1", uri="/", cnonce="1=", nc=00000001, qop=auth, response="22cf307b29e6318dafba1fc1d564fc12", opaque="1"`,
clientHeader: `Digest username="a", realm="t", nonce="2", uri="/", cnonce="1=", nc=00000001, qop=auth, response="22cf307b29e6318dafba1fc1d564fc12", opaque="1"`,
expectedErr: true,
},
{
serverHeader: `Digest username="a", realm="t", nonce="1", uri="/a", cnonce="1=", nc=00000001, qop=auth, response="22cf307b29e6318dafba1fc1d564fc12", opaque="1"`,
clientHeader: `Digest username="a", realm="t", nonce="1", uri="/", cnonce="1=", nc=00000001, qop=auth, response="22cf307b29e6318dafba1fc1d564fc12", opaque="1"`,
expectedErr: true,
},
{
serverHeader: `Digest username="a", realm="t", nonce="1", uri="/", cnonce="1", nc=00000001, qop=auth, response="22cf307b29e6318dafba1fc1d564fc12", opaque="1"`,
clientHeader: `Digest username="a", realm="t", nonce="1", uri="/", cnonce="1=", nc=00000001, qop=auth, response="22cf307b29e6318dafba1fc1d564fc12", opaque="1"`,
expectedErr: true,
},
{
serverHeader: `Digest username="a", realm="t", nonce="1", uri="/", cnonce="1=", nc=00000001, qop=auth, response="22cf307b29e6318dafba1fc1d564fc12", opaque="1"`,
clientHeader: `Digest username="a", realm="t", nonce="1", uri="/", cnonce="1=", nc=00000002, qop=auth, response="22cf307b29e6318dafba1fc1d564fc12", opaque="1"`,
expectedErr: true,
},
{
serverHeader: `Digest username="a", realm="t", nonce="1", uri="/", cnonce="1=", nc=00000001, qop=auth-i, response="22cf307b29e6318dafba1fc1d564fc12", opaque="1"`,
clientHeader: `Digest username="a", realm="t", nonce="1", uri="/", cnonce="1=", nc=00000001, qop=auth, response="22cf307b29e6318dafba1fc1d564fc12", opaque="1"`,
expectedErr: true,
},
{
serverHeader: `Digest username="a", realm="t", nonce="1", uri="/", cnonce="1=", nc=00000001, qop=auth, response="22cf307b29e6318dafba1fc1d564fc13", opaque="1"`,
clientHeader: `Digest username="a", realm="t", nonce="1", uri="/", cnonce="1=", nc=00000001, qop=auth, response="22cf307b29e6318dafba1fc1d564fc12", opaque="2"`,
expectedErr: true,
},
}

for _, tt := range table {
sh := make(Header)
ch := make(Header)

_ = sh.Parse(tt.serverHeader)
_ = ch.Parse(tt.clientHeader)

err := sh.Compare(ch)

assert.Equal(t, tt.expectedErr, err != nil)
}
}

func TestString(t *testing.T) {
h := make(Header)
h.SetUserName("test")
h.SetNC("00000001")

assert.Equal(t, "Digest username=test, nc=00000001", h.String())
}

func TestParse(t *testing.T) {
h := make(Header)

Expand Down

0 comments on commit e640016

Please sign in to comment.