-
Notifications
You must be signed in to change notification settings - Fork 1
/
jwtauth.go
114 lines (97 loc) · 2.5 KB
/
jwtauth.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
package jwtauth
import (
"errors"
"net/http"
"strings"
"github.com/dgrijalva/jwt-go"
"github.com/zenazn/goji/web"
)
var (
errUnauthorized = errors.New("unauthorized token")
)
type JwtAuth struct {
signKey []byte
verifyKey []byte
signer jwt.SigningMethod
}
// verifyKey is only for RSA
func New(alg string, signKey []byte, verifyKey []byte) *JwtAuth {
return &JwtAuth{
signKey: signKey,
verifyKey: verifyKey,
signer: jwt.GetSigningMethod(alg),
}
}
func (ja *JwtAuth) Handle(paramAliases ...string) func(*web.C, http.Handler) http.Handler {
f := func(c *web.C, h http.Handler) http.Handler {
fn := func(w http.ResponseWriter, r *http.Request) {
if c != nil && c.Env == nil {
c.Env = make(map[interface{}]interface{})
}
var tokenStr string
var err error
// Get token from query params
tokenStr = r.URL.Query().Get("jwt")
// Get token from other query param aliases
if tokenStr == "" && paramAliases != nil && len(paramAliases) > 0 {
for _, p := range paramAliases {
tokenStr = r.URL.Query().Get(p)
if tokenStr != "" {
break
}
}
}
// Get token from authorization header
if tokenStr == "" {
bearer := r.Header.Get("Authorization")
if len(bearer) > 7 && strings.ToUpper(bearer[0:6]) == "BEARER" {
tokenStr = bearer[7:]
}
}
// Get token from cookie
if tokenStr == "" {
cookie, err := r.Cookie("jwt")
if err == nil {
tokenStr = cookie.Value
}
}
// Token is required, cya
if tokenStr == "" {
err = errUnauthorized
}
// Verify the token
token, err := ja.Decode(tokenStr)
if err != nil || !token.Valid || token.Method != ja.signer {
http.Error(w, errUnauthorized.Error(), 401)
return
}
// Token is valid! save it in the context
if c != nil {
c.Env["token"] = token
c.Env["jwt"] = token.Raw
}
h.ServeHTTP(w, r)
}
return http.HandlerFunc(fn)
}
return f
}
func (ja *JwtAuth) Handler(c *web.C, h http.Handler) http.Handler {
return ja.Handle("")(c, h)
}
func (ja *JwtAuth) Encode(claims map[string]interface{}) (t *jwt.Token, tokenString string, err error) {
t = jwt.New(ja.signer)
t.Claims = claims
tokenString, err = t.SignedString(ja.signKey)
t.Raw = tokenString
return
}
func (ja *JwtAuth) Decode(tokenString string) (t *jwt.Token, err error) {
return jwt.Parse(tokenString, func(t *jwt.Token) (interface{}, error) {
if ja.verifyKey != nil && len(ja.verifyKey) > 0 {
return ja.verifyKey, nil
} else {
return ja.signKey, nil
}
})
}