forked from aidantwoods/go-paseto
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathclaims.go
229 lines (190 loc) · 5.68 KB
/
claims.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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
package paseto
import (
"crypto/subtle"
"fmt"
"time"
)
// Rule validates a given token for certain required preconditions (defined by
// the rule itself). If validation fails a Rule MUST return an error, otherwise
// error MUST be nil.
type Rule func(token Token) error
// ForAudience requires that the given audience matches the "aud" field of the
// token.
func ForAudience(audience string) Rule {
return func(token Token) error {
tAud, err := token.GetAudience()
if err != nil {
return err
}
if subtle.ConstantTimeCompare([]byte(tAud), []byte(audience)) == 0 {
return fmt.Errorf("this token is not intended for `%s'. `%s' found", audience, tAud)
}
return nil
}
}
// IdentifiedBy requires that the given identifier matches the "jti" field of
// the token.
func IdentifiedBy(identifier string) Rule {
return func(token Token) error {
tJti, err := token.GetJti()
if err != nil {
return err
}
if subtle.ConstantTimeCompare([]byte(tJti), []byte(identifier)) == 0 {
return fmt.Errorf("this token is not identified by `%s'. `%s' found", identifier, tJti)
}
return nil
}
}
// IssuedBy requires that the given issuer matches the "iss" field of the token.
func IssuedBy(issuer string) Rule {
return func(token Token) error {
tIss, err := token.GetIssuer()
if err != nil {
return err
}
tIssBytes := []byte(tIss)
issBytes := []byte(issuer)
if subtle.ConstantTimeCompare(tIssBytes, issBytes) == 0 {
return fmt.Errorf("this token is not issued by `%s'. `%s' found", issuer, tIss)
}
return nil
}
}
// NotBeforeNbf requires that the token is allowed to be used according to the time
// when this rule is checked and the "nbf" field of a token. Beware that this
// rule does not validate the token's "iat" or "exp" fields, or even require
// their presence.
func NotBeforeNbf() Rule {
return func(token Token) error {
nbf, err := token.GetNotBefore()
if err != nil {
return err
}
if time.Now().Before(nbf) {
return fmt.Errorf("this token is not valid, yet")
}
return nil
}
}
// NotExpired requires that the token has not expired according to the time
// when this rule is checked and the "exp" field of a token. Beware that this
// rule does not validate the token's "iat" or "nbf" fields, or even require
// their presence.
func NotExpired() Rule {
return func(token Token) error {
exp, err := token.GetExpiration()
if err != nil {
return err
}
if time.Now().After(exp) {
return fmt.Errorf("this token has expired")
}
return nil
}
}
// Subject requires that the given subject matches the "sub" field of the token.
func Subject(subject string) Rule {
return func(token Token) error {
tSub, err := token.GetSubject()
if err != nil {
return err
}
if subtle.ConstantTimeCompare([]byte(tSub), []byte(subject)) == 0 {
return fmt.Errorf("this token is not related to `%s'. `%s' found", subject, tSub)
}
return nil
}
}
// ValidAt requires that the token has not expired according to the given time
// and the "exp" field, and that the given time is both after the token's issued
// at time "iat", and the token's not before time "nbf".
func ValidAt(t time.Time) Rule {
return func(token Token) error {
iat, err := token.GetIssuedAt()
if err != nil {
return err
}
if t.Before(iat) {
return fmt.Errorf("the ValidAt time is before this token was issued")
}
nbf, err := token.GetNotBefore()
if err != nil {
return err
}
if t.Before(nbf) {
return fmt.Errorf("the ValidAt time is before this token's not before time")
}
exp, err := token.GetExpiration()
if err != nil {
return err
}
if t.After(exp) {
return fmt.Errorf("the ValidAt time is after this token expires")
}
return nil
}
}
// GetAudience returns the token's "aud" field, or error if not found or not a
// string.
func (t Token) GetAudience() (string, error) {
return t.GetString("aud")
}
// GetExpiration returns the token's "exp" field, or error if not found or not a
// a RFC3339 compliant time.
func (t Token) GetExpiration() (time.Time, error) {
return t.GetTime("exp")
}
// GetIssuedAt returns the token's "iat" field, or error if not found or not a
// a RFC3339 compliant time.
func (t Token) GetIssuedAt() (time.Time, error) {
return t.GetTime("iat")
}
// GetIssuer returns the token's "iss" field, or error if not found or not a
// string.
func (t Token) GetIssuer() (string, error) {
return t.GetString("iss")
}
// GetJti returns the token's "jti" field, or error if not found or not a
// string.
func (t Token) GetJti() (string, error) {
return t.GetString("jti")
}
// GetNotBefore returns the token's "nbf" field, or error if not found or not a
// a RFC3339 compliant time.
func (t Token) GetNotBefore() (time.Time, error) {
return t.GetTime("nbf")
}
// GetSubject returns the token's "sub" field, or error if not found or not a
// string.
func (t Token) GetSubject() (string, error) {
return t.GetString("sub")
}
// SetAudience sets the token's "aud" field.
func (t *Token) SetAudience(audience string) {
t.SetString("aud", audience)
}
// SetExpiration sets the token's "exp" field.
func (t *Token) SetExpiration(exp time.Time) {
t.SetTime("exp", exp)
}
// SetIssuedAt sets the token's "iat" field.
func (t *Token) SetIssuedAt(iat time.Time) {
t.SetTime("iat", iat)
}
// SetIssuer sets the token's "iss" field.
func (t *Token) SetIssuer(issuer string) {
t.SetString("iss", issuer)
}
// SetJti sets the token's "jti" field.
func (t *Token) SetJti(identifier string) {
t.SetString("jti", identifier)
}
// SetNotBefore sets the token's "nbf" field.
func (t *Token) SetNotBefore(nbf time.Time) {
t.SetTime("nbf", nbf)
}
// SetSubject sets the token's "sub" field.
func (t *Token) SetSubject(subject string) {
t.SetString("sub", subject)
}