...
1 package jwt
2
3 import (
4 "crypto/subtle"
5 "fmt"
6 "time"
7 )
8
9
10
11 type Claims interface {
12 Valid() error
13 }
14
15
16
17
18 type StandardClaims struct {
19 Audience string `json:"aud,omitempty"`
20 ExpiresAt int64 `json:"exp,omitempty"`
21 Id string `json:"jti,omitempty"`
22 IssuedAt int64 `json:"iat,omitempty"`
23 Issuer string `json:"iss,omitempty"`
24 NotBefore int64 `json:"nbf,omitempty"`
25 Subject string `json:"sub,omitempty"`
26 }
27
28
29
30
31
32 func (c StandardClaims) Valid() error {
33 vErr := new(ValidationError)
34 now := TimeFunc().Unix()
35
36
37
38 if !c.VerifyExpiresAt(now, false) {
39 delta := time.Unix(now, 0).Sub(time.Unix(c.ExpiresAt, 0))
40 vErr.Inner = fmt.Errorf("token is expired by %v", delta)
41 vErr.Errors |= ValidationErrorExpired
42 }
43
44 if !c.VerifyIssuedAt(now, false) {
45 vErr.Inner = fmt.Errorf("Token used before issued")
46 vErr.Errors |= ValidationErrorIssuedAt
47 }
48
49 if !c.VerifyNotBefore(now, false) {
50 vErr.Inner = fmt.Errorf("token is not valid yet")
51 vErr.Errors |= ValidationErrorNotValidYet
52 }
53
54 if vErr.valid() {
55 return nil
56 }
57
58 return vErr
59 }
60
61
62
63 func (c *StandardClaims) VerifyAudience(cmp string, req bool) bool {
64 return verifyAud([]string{c.Audience}, cmp, req)
65 }
66
67
68
69 func (c *StandardClaims) VerifyExpiresAt(cmp int64, req bool) bool {
70 return verifyExp(c.ExpiresAt, cmp, req)
71 }
72
73
74
75 func (c *StandardClaims) VerifyIssuedAt(cmp int64, req bool) bool {
76 return verifyIat(c.IssuedAt, cmp, req)
77 }
78
79
80
81 func (c *StandardClaims) VerifyIssuer(cmp string, req bool) bool {
82 return verifyIss(c.Issuer, cmp, req)
83 }
84
85
86
87 func (c *StandardClaims) VerifyNotBefore(cmp int64, req bool) bool {
88 return verifyNbf(c.NotBefore, cmp, req)
89 }
90
91
92
93 func verifyAud(aud []string, cmp string, required bool) bool {
94 if len(aud) == 0 {
95 return !required
96 }
97
98 result := false
99
100 var stringClaims string
101 for _, a := range aud {
102 if subtle.ConstantTimeCompare([]byte(a), []byte(cmp)) != 0 {
103 result = true
104 }
105 stringClaims = stringClaims + a
106 }
107
108
109 if len(stringClaims) == 0 {
110 return !required
111 }
112
113 return result
114 }
115
116 func verifyExp(exp int64, now int64, required bool) bool {
117 if exp == 0 {
118 return !required
119 }
120 return now <= exp
121 }
122
123 func verifyIat(iat int64, now int64, required bool) bool {
124 if iat == 0 {
125 return !required
126 }
127 return now >= iat
128 }
129
130 func verifyIss(iss string, cmp string, required bool) bool {
131 if iss == "" {
132 return !required
133 }
134 if subtle.ConstantTimeCompare([]byte(iss), []byte(cmp)) != 0 {
135 return true
136 } else {
137 return false
138 }
139 }
140
141 func verifyNbf(nbf int64, now int64, required bool) bool {
142 if nbf == 0 {
143 return !required
144 }
145 return now >= nbf
146 }
147
View as plain text