-
Notifications
You must be signed in to change notification settings - Fork 4
/
jwt.go
111 lines (90 loc) · 2.39 KB
/
jwt.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
package jwt
import (
"fmt"
"time"
"github.com/ribice/twisk/model"
jwt "github.com/dgrijalva/jwt-go"
)
// New instantiates new JWT service
func New(key string, duration int, algo string) *JWT {
signingMethod := jwt.GetSigningMethod(algo)
if signingMethod == nil {
panic("invalid signing method")
}
return &JWT{
key: []byte(key),
duration: time.Duration(duration) * time.Minute,
algo: signingMethod,
}
}
// JWT contains data necessery for jwt auth
type JWT struct {
// Secret key used for signing.
key []byte
// Duration for which the jwt token is valid.
duration time.Duration
// JWT signing algorithm
algo jwt.SigningMethod
}
// GenerateToken generates new jwt token
func (j *JWT) GenerateToken(u *twisk.AuthUser) (string, error) {
t := jwt.NewWithClaims(j.algo, jwt.MapClaims{
"id": u.ID,
"t": u.TenantID,
"u": u.Username,
"e": u.Email,
"r": u.Role,
"exp": time.Now().Add(j.duration).Unix(),
})
return t.SignedString(j.key)
}
// ParseToken parses the bearer token
func (j *JWT) ParseToken(token string) (*twisk.AuthUser, error) {
claims, err := j.verifyToken(token)
if err != nil {
return nil, err
}
id, ok := claims["id"]
if !ok {
return nil, fmt.Errorf("unauthorized: no id claim present")
}
tenantID, ok := claims["t"]
if !ok {
return nil, fmt.Errorf("unauthorized: no tenant_id claim present")
}
username, ok := claims["u"]
if !ok {
return nil, fmt.Errorf("unauthorized: no username claim present")
}
email, ok := claims["e"]
if !ok {
return nil, fmt.Errorf("unauthorized: no email claim present")
}
role, ok := claims["r"]
if !ok {
return nil, fmt.Errorf("unauthorized: no role claim present")
}
return &twisk.AuthUser{
ID: int64(id.(float64)),
TenantID: int32(tenantID.(float64)),
Username: username.(string),
Email: email.(string),
Role: twisk.AccessRole(role.(float64)),
}, nil
}
func (j *JWT) verifyToken(token string) (map[string]interface{}, error) {
t, err := jwt.Parse(token, func(token *jwt.Token) (interface{}, error) {
if token.Method != j.algo {
return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"])
}
return j.key, nil
})
if err != nil {
fmt.Println(err)
return nil, fmt.Errorf("could not parse provided token")
}
if claims, ok := t.Claims.(jwt.MapClaims); ok && t.Valid {
return claims, nil
}
return nil, fmt.Errorf("jwt token could not be verified")
}