Skip to content

Commit 139454a

Browse files
committed
add jwt middleware for authentication
1 parent 24d5a70 commit 139454a

File tree

5 files changed

+89
-17
lines changed

5 files changed

+89
-17
lines changed

common/erros.go

+24-17
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package common
33
// got error handling idea from https://medium.com/ki-labs-engineering/rest-api-error-handling-in-go-behavioral-type-assertion-509d93636afd
44

55
import (
6-
"fmt"
76
"github.com/asaskevich/govalidator"
87
"github.com/labstack/echo/v4"
98
"net/http"
@@ -35,14 +34,13 @@ func NewError() *Error {
3534
type RequestError struct {
3635
Cause error
3736
Detail string
38-
Type string
3937
Status int
4038
}
4139

4240
// NewBindingError creates an error with given data. "bindingType" is the type that is being bound
4341
// provide short description for "detail" to display to user as error message
44-
func NewBindingError(detail, bindingType string, err error, statusCode int) *RequestError {
45-
return &RequestError{err, detail, bindingType, statusCode}
42+
func NewRequestError(detail string, err error, statusCode int) *RequestError {
43+
return &RequestError{err, detail, statusCode}
4644
}
4745
func (se *RequestError) Error() string {
4846
if se.Cause == nil {
@@ -52,8 +50,7 @@ func (se *RequestError) Error() string {
5250
}
5351
func (se *RequestError) ErrorBody() Error {
5452
body := NewError()
55-
body.Body["type"] = fmt.Sprintf("Error parsing request of type %s", se.Type)
56-
body.Body["detail"] = se.Detail
53+
body.Body["body"] = se.Detail
5754
return *body
5855
}
5956

@@ -88,16 +85,26 @@ func (e *ValidationError) ErrorBody() Error {
8885
// CustomHTTPErrorHandler, here we define what to do with each types of errors
8986
func CustomHTTPErrorHandler(err error, c echo.Context) {
9087
code := http.StatusInternalServerError
91-
cErr := err.(ClientError)
92-
switch e := cErr.(type) {
93-
case *RequestError:
94-
code = e.Status
95-
case *ValidationError:
96-
code = http.StatusBadRequest
97-
}
98-
e := c.JSON(code, cErr.ErrorBody())
99-
if e != nil {
100-
c.Logger().Error(e)
88+
switch err.(type) {
89+
case ClientError:
90+
ce := err.(ClientError)
91+
e := c.JSON(code, ce.ErrorBody())
92+
if e != nil {
93+
c.Logger().Error(e)
94+
}
95+
96+
c.Logger().Error(ce)
97+
switch e := ce.(type) {
98+
case *RequestError:
99+
code = e.Status
100+
case *ValidationError:
101+
code = http.StatusBadRequest
102+
}
103+
case *echo.HTTPError:
104+
e := c.JSON(err.(*echo.HTTPError).Code, err.(*echo.HTTPError).Message)
105+
if e != nil {
106+
c.Logger().Error(e)
107+
}
108+
c.Logger().Error(err)
101109
}
102-
c.Logger().Error(cErr)
103110
}

common/jwt.go

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package common
2+
3+
import (
4+
"github.com/dgrijalva/jwt-go"
5+
"net/http"
6+
"time"
7+
)
8+
9+
var JWTSecret = []byte("SuperSecret")
10+
11+
func GenerateJWT(id int) (string, error) {
12+
token := jwt.New(jwt.SigningMethodHS256)
13+
claims := token.Claims.(jwt.MapClaims)
14+
claims["id"] = id
15+
claims["exp"] = time.Now().Add(time.Hour * 72).Unix()
16+
t, err := token.SignedString(JWTSecret)
17+
if err != nil {
18+
return "", NewRequestError("Error generating JWT token", err, http.StatusInternalServerError)
19+
}
20+
return t, nil
21+
}

go.mod

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ go 1.12
44

55
require (
66
github.com/asaskevich/govalidator v0.0.0-20200108200545-475eaeb16496
7+
github.com/dgrijalva/jwt-go v3.2.0+incompatible
78
github.com/gammazero/workerpool v0.0.0-20200108033143-79b2336fad7a
89
github.com/jinzhu/gorm v1.9.11
910
github.com/kr/pretty v0.2.0 // indirect

go.sum

+1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
1717
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
1818
github.com/denisenkom/go-mssqldb v0.0.0-20190515213511-eb9f6a1743f3 h1:tkum0XDgfR0jcVVXuTsYv/erY2NnEDqwRojbxR1rBYA=
1919
github.com/denisenkom/go-mssqldb v0.0.0-20190515213511-eb9f6a1743f3/go.mod h1:zAg7JM8CkOJ43xKXIj7eRO9kmWm/TW578qo+oDO6tuM=
20+
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
2021
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
2122
github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
2223
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=

middleware/jwt.go

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// codes from https://github.com/labstack/echo/blob/master/middleware/jwt.go
2+
package middleware
3+
4+
import (
5+
"github.com/labstack/echo/v4"
6+
"github.com/labstack/echo/v4/middleware"
7+
"strings"
8+
)
9+
10+
type whiteList struct {
11+
path string
12+
method string
13+
}
14+
15+
// authWhiteList specifies paths to be skipped by jwt authentication middleware
16+
var authWhiteList []whiteList
17+
18+
// AddToWhiteList is used to add a path to skipper white list
19+
// provide path relative to api version like /api/your/path/here as skipper uses strings.Contains to find whether
20+
// it is in context path or not
21+
func AddToWhiteList(path string, method string) {
22+
if authWhiteList == nil {
23+
authWhiteList = make([]whiteList, 0)
24+
}
25+
authWhiteList = append(authWhiteList, whiteList{path, method})
26+
}
27+
28+
func skipper(c echo.Context) bool {
29+
for _, v := range authWhiteList {
30+
if strings.Contains(c.Path(), v.path) && c.Request().Method == v.method {
31+
return true
32+
}
33+
}
34+
return false
35+
}
36+
37+
func JWT(key interface{}) echo.MiddlewareFunc {
38+
c := middleware.DefaultJWTConfig
39+
c.SigningKey = key
40+
c.Skipper = skipper
41+
return middleware.JWTWithConfig(c)
42+
}

0 commit comments

Comments
 (0)