Skip to content
This repository has been archived by the owner on Aug 25, 2023. It is now read-only.

Commit

Permalink
Merge pull request #321 from DRK3/FixGNAPMiddlewareHeaderLogic
Browse files Browse the repository at this point in the history
fix: GNAP header inspection bug
  • Loading branch information
Derek Trider authored Jul 19, 2022
2 parents 3a2f412 + 471fd63 commit 671f38b
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 11 deletions.
28 changes: 19 additions & 9 deletions pkg/controller/mw/authmw/gnapmw/gnap_middleware.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,13 +69,12 @@ type HTTPHandler interface {

// Accept checks if the request can be handled by the GNAP middleware.
func (mw *Middleware) Accept(req *http.Request) bool {
if v, ok := req.Header["Authorization"]; ok {
for _, h := range v {
if strings.Contains(h, gnapToken) {
logger.Debugf("Accept: %v is true", v)
v := req.Header.Values("Authorization")
for _, h := range v {
if strings.Contains(h, gnapToken) {
logger.Debugf("Accept: %v is true", v)

return true
}
return true
}
}

Expand Down Expand Up @@ -108,9 +107,20 @@ type gnapHandler struct {

// ServeHTTP authorizes an incoming HTTP request using GNAP.
func (h *gnapHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
tokenHeader := strings.Split(strings.Trim(req.Header.Get("Authorization"), " "), " ")
var tokenHeader string

if len(tokenHeader) < 2 || tokenHeader[0] != gnapToken {
v := req.Header.Values("Authorization")
for _, h := range v {
if strings.Contains(h, gnapToken) {
tokenHeader = h

break
}
}

tokenHeaderSplit := strings.Split(strings.Trim(tokenHeader, " "), " ")

if len(tokenHeaderSplit) < 2 || tokenHeaderSplit[0] != gnapToken {
http.Error(w, "unauthorized", http.StatusUnauthorized)

return
Expand All @@ -121,7 +131,7 @@ func (h *gnapHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
Key: h.clientKey,
},
Proof: proofType,
AccessToken: tokenHeader[1],
AccessToken: tokenHeaderSplit[1],
}

resp, err := h.client.Introspect(introspectReq)
Expand Down
52 changes: 52 additions & 0 deletions pkg/controller/mw/authmw/gnapmw/gnap_middleware_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,58 @@ func TestMiddleware(t *testing.T) {
require.Equal(t, http.StatusOK, rr.Code)
})

t.Run("should call next handler if request is authorized "+
"(GNAP token is second value in Authorization header)", func(t *testing.T) {
ctrl := gomock.NewController(t)

privKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)

privJWK := &jwk.JWK{
JSONWebKey: jose.JSONWebKey{
Key: privKey,
KeyID: "key1",
Algorithm: "ES256",
},
Kty: "EC",
Crv: "P-256",
}

pubJWK := jwk.JWK{
JSONWebKey: privJWK.Public(),
Kty: "EC",
Crv: "P-256",
}

require.NoError(t, err)
client := NewMockGNAPRSClient(ctrl)
client.EXPECT().Introspect(gomock.Any()).Return(&gnap.IntrospectResponse{Active: true, Key: &gnap.ClientKey{
JWK: pubJWK,
}}, nil)

mVerifier := NewMockGNAPVerifier(ctrl)
mVerifier.EXPECT().Verify(gomock.Any()).Times(1)

mw, err := gnapmw.NewMiddleware(client, &pubJWK, func(req *http.Request) gnapmw.GNAPVerifier {
return mVerifier
}, false)
require.NoError(t, err)

next := NewMockHTTPHandler(ctrl)
next.EXPECT().ServeHTTP(gomock.Any(), gomock.Any()).Times(1)

req, err := http.NewRequestWithContext(context.Background(), "", "", nil)
require.NoError(t, err)

req.Header.Add("Authorization", "Some other token")
req.Header.Add("Authorization", "GNAP token")

rr := httptest.NewRecorder()

mw.Middleware()(next).ServeHTTP(rr, req)

require.Equal(t, http.StatusOK, rr.Code)
})

t.Run("should return 401 Unauthorized if request is unauthorized due to signature error", func(t *testing.T) {
ctrl := gomock.NewController(t)

Expand Down
4 changes: 2 additions & 2 deletions pkg/controller/mw/authmw/zcapmw/zcap_middleware.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,9 @@ type Middleware struct {

// Accept checks if middleware can handle auth for the given request.
func (mw *Middleware) Accept(req *http.Request) bool {
_, ok := req.Header["Capability-Invocation"]
headerValues := req.Header.Values("Capability-Invocation")

return ok
return len(headerValues) > 0
}

// Middleware returns middleware func.
Expand Down

0 comments on commit 671f38b

Please sign in to comment.