-
Notifications
You must be signed in to change notification settings - Fork 87
/
jwt.go
144 lines (124 loc) · 4 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
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
package jwt
import (
"time"
"github.com/SermoDigital/jose/crypto"
)
// JWT represents a JWT per RFC 7519.
// It's described as an interface instead of a physical structure
// because both JWS and JWEs can be JWTs. So, in order to use either,
// import one of those two packages and use their "NewJWT" (and other)
// functions.
type JWT interface {
// Claims returns the set of Claims.
Claims() Claims
// Validate returns an error describing any issues found while
// validating the JWT. For info on the fn parameter, see the
// comment on ValidateFunc.
Validate(key interface{}, method crypto.SigningMethod, v ...*Validator) error
// Serialize serializes the JWT into its on-the-wire
// representation.
Serialize(key interface{}) ([]byte, error)
}
// ValidateFunc is a function that provides access to the JWT
// and allows for custom validation. Keep in mind that the Verify
// methods in the JWS/JWE sibling packages call ValidateFunc *after*
// validating the JWS/JWE, but *before* any validation per the JWT
// RFC. Therefore, the ValidateFunc can be used to short-circuit
// verification, but cannot be used to circumvent the RFC.
// Custom JWT implementations are free to abuse this, but it is
// not recommended.
type ValidateFunc func(Claims) error
// Validator represents some of the validation options.
type Validator struct {
Expected Claims // If non-nil, these are required to match.
EXP time.Duration // EXPLeeway
NBF time.Duration // NBFLeeway
Fn ValidateFunc // See ValidateFunc for more information.
_ struct{} // Require explicitly-named struct fields.
}
// Validate validates the JWT based on the expected claims in v.
// Note: it only validates the registered claims per
// https://tools.ietf.org/html/rfc7519#section-4.1
//
// Custom claims should be validated using v's Fn member.
func (v *Validator) Validate(j JWT) error {
if iss, ok := v.Expected.Issuer(); ok &&
j.Claims().Get("iss") != iss {
return ErrInvalidISSClaim
}
if sub, ok := v.Expected.Subject(); ok &&
j.Claims().Get("sub") != sub {
return ErrInvalidSUBClaim
}
if iat, ok := v.Expected.IssuedAt(); ok {
if t, ok := j.Claims().GetTime("iat"); !t.Equal(iat) || !ok {
return ErrInvalidIATClaim
}
}
if jti, ok := v.Expected.JWTID(); ok &&
j.Claims().Get("jti") != jti {
return ErrInvalidJTIClaim
}
if aud, ok := v.Expected.Audience(); ok {
aud2, ok := j.Claims().Audience()
if !ok || !ValidAudience(aud, aud2) {
return ErrInvalidAUDClaim
}
}
if v.Fn != nil {
return v.Fn(j.Claims())
}
return nil
}
// SetClaim sets the claim with the given val.
func (v *Validator) SetClaim(claim string, val interface{}) {
v.expect()
v.Expected.Set(claim, val)
}
// SetIssuer sets the "iss" claim per
// https://tools.ietf.org/html/rfc7519#section-4.1.1
func (v *Validator) SetIssuer(iss string) {
v.expect()
v.Expected.Set("iss", iss)
}
// SetSubject sets the "sub" claim per
// https://tools.ietf.org/html/rfc7519#section-4.1.2
func (v *Validator) SetSubject(sub string) {
v.expect()
v.Expected.Set("sub", sub)
}
// SetAudience sets the "aud" claim per
// https://tools.ietf.org/html/rfc7519#section-4.1.3
func (v *Validator) SetAudience(aud string) {
v.expect()
v.Expected.Set("aud", aud)
}
// SetExpiration sets the "exp" claim per
// https://tools.ietf.org/html/rfc7519#section-4.1.4
func (v *Validator) SetExpiration(exp time.Time) {
v.expect()
v.Expected.Set("exp", exp)
}
// SetNotBefore sets the "nbf" claim per
// https://tools.ietf.org/html/rfc7519#section-4.1.5
func (v *Validator) SetNotBefore(nbf time.Time) {
v.expect()
v.Expected.Set("nbf", nbf)
}
// SetIssuedAt sets the "iat" claim per
// https://tools.ietf.org/html/rfc7519#section-4.1.6
func (v *Validator) SetIssuedAt(iat time.Time) {
v.expect()
v.Expected.Set("iat", iat)
}
// SetJWTID sets the "jti" claim per
// https://tools.ietf.org/html/rfc7519#section-4.1.7
func (v *Validator) SetJWTID(jti string) {
v.expect()
v.Expected.Set("jti", jti)
}
func (v *Validator) expect() {
if v.Expected == nil {
v.Expected = make(Claims)
}
}