Repository: labstack/echo (go)

Issue:
Allow KeyLookup in Cookie for KeyAuth middleware
### Issue Description

It would be great if we could specify a cookie name for KeyLookup in the KeyAuth middleware config.
This way a user could pass the key credentials via a cookie, whereas now it is restricted to http headers, query params, and form fields.

Disclaimer: There might be good - security-related - reasons not to do this.

### Checklist


- [x] Dependencies installed
- [x] No typos
- [x] Searched existing issues and docs

### Expected behaviour

I can specify 
```
KeyLookup: "cookie:<name>"
```
when defining KetAuthWithConfig, so the middleware reads the key from a cookie.

e.g.:

```
e := echo.New()
e.Use(middleware.KeyAuthWithConfig(middleware.KeyAuthConfig{
  KeyLookup: "cookie:api-key",
  Validator: func(key string, c echo.Context) (bool, error) {
               return key == "valid-key", nil
     },
}))
```

### Actual behaviour

Currently only following KeyLookup methods are allowed
```
"header:<name>"
"query:<name>"
"form:<name>"	
```

### Steps to reproduce
n.A.

### Working code to debug

n.A.

### Version/commit
v4.3.0/7846e3f


Pull request:
Add Cookie to KeyAuth middleware's KeyLookup
Closes #1885 

Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 892d709..02eb36f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,28 @@
 # Changelog
 
+## v4.5.0 - 2021-08-01
+
+**Important notes**
+
+A **BREAKING CHANGE** is introduced for JWT middleware users.
+The JWT library used for the JWT middleware had to be changed from [github.com/dgrijalva/jwt-go](https://github.com/dgrijalva/jwt-go) to
+[github.com/golang-jwt/jwt](https://github.com/golang-jwt/jwt) due former library being unmaintained and affected by security
+issues.
+The [github.com/golang-jwt/jwt](https://github.com/golang-jwt/jwt) project is a drop-in replacement, but supports only the latest 2 Go versions.
+So for JWT middleware users Go 1.15+ is required. For detailed information please read [#1940](https://github.com/labstack/echo/discussions/)
+
+To change the library imports in all .go files in your project replace all occurrences of `dgrijalva/jwt-go` with `golang-jwt/jwt`.
+
+For Linux CLI you can use:
+```bash
+find -type f -name "*.go" -exec sed -i "s/dgrijalva\/jwt-go/golang-jwt\/jwt/g" {} \;
+go mod tidy
+```
+
+**Fixes**
+
+* Change JWT library to `github.com/golang-jwt/jwt` [#1946](https://github.com/labstack/echo/pull/1946)
+
 ## v4.4.0 - 2021-07-12
 
 **Fixes**
diff --git a/echo.go b/echo.go
index 406e806..246a622 100644
--- a/echo.go
+++ b/echo.go
@@ -241,7 +241,7 @@ const (
 
 const (
 	// Version of Echo
-	Version = "4.4.0"
+	Version = "4.5.0"
 	website = "https://echo.labstack.com"
 	// http://patorjk.com/software/taag/#p=display&f=Small%20Slant&t=Echo
 	banner = `
diff --git a/go.mod b/go.mod
index 2510d10..9cd3529 100644
--- a/go.mod
+++ b/go.mod
@@ -3,7 +3,7 @@ module github.com/labstack/echo/v4
 go 1.15
 
 require (
-	github.com/dgrijalva/jwt-go v3.2.0+incompatible
+	github.com/golang-jwt/jwt v3.2.2+incompatible
 	github.com/labstack/gommon v0.3.0
 	github.com/mattn/go-colorable v0.1.8 // indirect
 	github.com/stretchr/testify v1.4.0
diff --git a/go.sum b/go.sum
index d18f10f..027e966 100644
--- a/go.sum
+++ b/go.sum
@@ -1,7 +1,7 @@
 github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
-github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
-github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
+github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
+github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
 github.com/labstack/gommon v0.3.0 h1:JEeO0bvc78PKdyHxloTKiF8BD5iGrH8T6MSeGvSgob0=
 github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k=
 github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
diff --git a/middleware/jwt.go b/middleware/jwt.go
index bce4787..c2e7c06 100644
--- a/middleware/jwt.go
+++ b/middleware/jwt.go
@@ -1,3 +1,5 @@
+// +build go1.15
+
 package middleware
 
 import (
@@ -7,7 +9,7 @@ import (
 	"reflect"
 	"strings"
 
-	"github.com/dgrijalva/jwt-go"
+	"github.com/golang-jwt/jwt"
 	"github.com/labstack/echo/v4"
 )
 
@@ -88,7 +90,7 @@ type (
 
 		// ParseTokenFunc defines a user-defined function that parses token from given auth. Returns an error when token
 		// parsing fails or parsed token is invalid.
-		// Defaults to implementation using `github.com/dgrijalva/jwt-go` as JWT implementation library
+		// Defaults to implementation using `github.com/golang-jwt/jwt` as JWT implementation library
 		ParseTokenFunc func(auth string, c echo.Context) (interface{}, error)
 	}
 
diff --git a/middleware/key_auth.go b/middleware/key_auth.go
index fd169aa..54f3b47 100644
--- a/middleware/key_auth.go
+++ b/middleware/key_auth.go
@@ -2,6 +2,7 @@ package middleware
 
 import (
 	"errors"
+	"fmt"
 	"net/http"
 	"strings"
 
@@ -21,6 +22,7 @@ type (
 		// - "header:<name>"
 		// - "query:<name>"
 		// - "form:<name>"
+		// - "cookie:<name>"
 		KeyLookup string `yaml:"key_lookup"`
 
 		// AuthScheme to be used in the Authorization header.
@@ -91,6 +93,8 @@ func KeyAuthWithConfig(config KeyAuthConfig) echo.MiddlewareFunc {
 		extractor = keyFromQuery(parts[1])
 	case "form":
 		extractor = keyFromForm(parts[1])
+	case "cookie":
+		extractor = keyFromCookie(parts[1])
 	}
 
 	return func(next echo.HandlerFunc) echo.HandlerFunc {
@@ -164,3 +168,14 @@ func keyFromForm(param string) keyExtractor {
 		return key, nil
 	}
 }
+
+// keyFromCookie returns a `keyExtractor` that extracts key from the form.
+func keyFromCookie(cookieName string) keyExtractor {
+	return func(c echo.Context) (string, error) {
+		key, err := c.Cookie(cookieName)
+		if err != nil {
+			return "", fmt.Errorf("missing key in cookies: %w", err)
+		}
+		return key.Value, nil
+	}
+}


Test patch:
diff --git a/middleware/jwt_test.go b/middleware/jwt_test.go
index 9af4c83..393fd93 100644
--- a/middleware/jwt_test.go
+++ b/middleware/jwt_test.go
@@ -1,3 +1,5 @@
+// +build go1.15
+
 package middleware
 
 import (
@@ -9,7 +11,7 @@ import (
 	"strings"
 	"testing"
 
-	"github.com/dgrijalva/jwt-go"
+	"github.com/golang-jwt/jwt"
 	"github.com/labstack/echo/v4"
 	"github.com/stretchr/testify/assert"
 )
@@ -562,7 +564,7 @@ func TestJWTConfig_custom_ParseTokenFunc_Keyfunc(t *testing.T) {
 		return c.String(http.StatusTeapot, "test")
 	})
 
-	// example of minimal custom ParseTokenFunc implementation. Allows you to use different versions of `github.com/dgrijalva/jwt-go`
+	// example of minimal custom ParseTokenFunc implementation. Allows you to use different versions of `github.com/golang-jwt/jwt`
 	// with current JWT middleware
 	signingKey := []byte("secret")
 
diff --git a/middleware/key_auth_test.go b/middleware/key_auth_test.go
index 476b402..0cc513a 100644
--- a/middleware/key_auth_test.go
+++ b/middleware/key_auth_test.go
@@ -157,6 +157,30 @@ func TestKeyAuthWithConfig(t *testing.T) {
 			expectHandlerCalled: false,
 			expectError:         "code=400, message=missing key in the form",
 		},
+		{
+			name: "ok, custom key lookup, cookie",
+			givenRequest: func(req *http.Request) {
+				req.AddCookie(&http.Cookie{
+					Name:  "key",
+					Value: "valid-key",
+				})
+				q := req.URL.Query()
+				q.Add("key", "valid-key")
+				req.URL.RawQuery = q.Encode()
+			},
+			whenConfig: func(conf *KeyAuthConfig) {
+				conf.KeyLookup = "cookie:key"
+			},
+			expectHandlerCalled: true,
+		},
+		{
+			name: "nok, custom key lookup, missing cookie param",
+			whenConfig: func(conf *KeyAuthConfig) {
+				conf.KeyLookup = "cookie:key"
+			},
+			expectHandlerCalled: false,
+			expectError:         "code=400, message=missing key in cookies: http: named cookie not present",
+		},
 		{
 			name: "nok, custom errorHandler, error from extractor",
 			whenConfig: func(conf *KeyAuthConfig) {