Skip to content

Commit 90bfa5e

Browse files
Kolawole SegunKolawole Segun
authored andcommitted
covert validatior to functional style
1 parent 9629854 commit 90bfa5e

File tree

5 files changed

+60
-79
lines changed

5 files changed

+60
-79
lines changed

claims.go

Lines changed: 31 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import (
99
// Claims must just have a Valid method that determines
1010
// if the token is invalid for any supported reason
1111
type Claims interface {
12-
Valid(options ...*ValidatorOptions) error
12+
Valid(options ...ValidatorOption) error
1313
}
1414

1515
// RegisteredClaims are a structured version of the JWT Claims Set,
@@ -48,14 +48,13 @@ type RegisteredClaims struct {
4848
// There is no accounting for clock skew.
4949
// As well, if any of the above claims are not in the token, it will still
5050
// be considered a valid claim.
51-
func (c RegisteredClaims) Valid(opts ...*ValidatorOptions) error {
51+
func (c RegisteredClaims) Valid(opts ...ValidatorOption) error {
5252
vErr := new(ValidationError)
5353
now := TimeFunc()
54-
o := MergeValidatorOptions(opts...)
5554

5655
// The claims below are optional, by default, so if they are set to the
5756
// default value in Go, let's not fail the verification for them.
58-
if !c.VerifyExpiresAt(now, false, o) {
57+
if !c.VerifyExpiresAt(now, false, opts...) {
5958
delta := now.Sub(c.ExpiresAt.Time)
6059
vErr.Inner = fmt.Errorf("%s by %v", delta, ErrTokenExpired)
6160
vErr.Errors |= ValidationErrorExpired
@@ -66,7 +65,7 @@ func (c RegisteredClaims) Valid(opts ...*ValidatorOptions) error {
6665
vErr.Errors |= ValidationErrorIssuedAt
6766
}
6867

69-
if !c.VerifyNotBefore(now, false, o) {
68+
if !c.VerifyNotBefore(now, false, opts...) {
7069
vErr.Inner = ErrTokenNotValidYet
7170
vErr.Errors |= ValidationErrorNotValidYet
7271
}
@@ -86,17 +85,16 @@ func (c *RegisteredClaims) VerifyAudience(cmp string, req bool) bool {
8685

8786
// VerifyExpiresAt compares the exp claim against cmp (cmp < exp).
8887
// If req is false, it will return true, if exp is unset.
89-
func (c *RegisteredClaims) VerifyExpiresAt(cmp time.Time, req bool, opts ...*ValidatorOptions) bool {
90-
var s time.Duration
91-
o := MergeValidatorOptions(opts...)
92-
if o != nil {
93-
s = o.leeway
88+
func (c *RegisteredClaims) VerifyExpiresAt(cmp time.Time, req bool, opts ...ValidatorOption) bool {
89+
validator := ValidatorOptions{}
90+
for _, o := range opts {
91+
o(&validator)
9492
}
9593
if c.ExpiresAt == nil {
96-
return verifyExp(nil, cmp, req, s)
94+
return verifyExp(nil, cmp, req, validator.leeway)
9795
}
9896

99-
return verifyExp(&c.ExpiresAt.Time, cmp, req, s)
97+
return verifyExp(&c.ExpiresAt.Time, cmp, req, validator.leeway)
10098
}
10199

102100
// VerifyIssuedAt compares the iat claim against cmp (cmp >= iat).
@@ -111,17 +109,16 @@ func (c *RegisteredClaims) VerifyIssuedAt(cmp time.Time, req bool) bool {
111109

112110
// VerifyNotBefore compares the nbf claim against cmp (cmp >= nbf).
113111
// If req is false, it will return true, if nbf is unset.
114-
func (c *RegisteredClaims) VerifyNotBefore(cmp time.Time, req bool, opts ...*ValidatorOptions) bool {
115-
var s time.Duration
116-
o := MergeValidatorOptions(opts...)
117-
if o != nil {
118-
s = o.leeway
112+
func (c *RegisteredClaims) VerifyNotBefore(cmp time.Time, req bool, opts ...ValidatorOption) bool {
113+
validator := ValidatorOptions{}
114+
for _, o := range opts {
115+
o(&validator)
119116
}
120117
if c.NotBefore == nil {
121-
return verifyNbf(nil, cmp, req, s)
118+
return verifyNbf(nil, cmp, req, validator.leeway)
122119
}
123120

124-
return verifyNbf(&c.NotBefore.Time, cmp, req, s)
121+
return verifyNbf(&c.NotBefore.Time, cmp, req, validator.leeway)
125122
}
126123

127124
// VerifyIssuer compares the iss claim against cmp.
@@ -152,14 +149,13 @@ type StandardClaims struct {
152149
// Valid validates time based claims "exp, iat, nbf". There is no accounting for clock skew.
153150
// As well, if any of the above claims are not in the token, it will still
154151
// be considered a valid claim.
155-
func (c StandardClaims) Valid(opts ...*ValidatorOptions) error {
152+
func (c StandardClaims) Valid(opts ...ValidatorOption) error {
156153
vErr := new(ValidationError)
157154
now := TimeFunc().Unix()
158-
o := MergeValidatorOptions(opts...)
159155

160156
// The claims below are optional, by default, so if they are set to the
161157
// default value in Go, let's not fail the verification for them.
162-
if !c.VerifyExpiresAt(now, false, o) {
158+
if !c.VerifyExpiresAt(now, false, opts...) {
163159
delta := time.Unix(now, 0).Sub(time.Unix(c.ExpiresAt, 0))
164160
vErr.Inner = fmt.Errorf("%s by %v", delta, ErrTokenExpired)
165161
vErr.Errors |= ValidationErrorExpired
@@ -170,7 +166,7 @@ func (c StandardClaims) Valid(opts ...*ValidatorOptions) error {
170166
vErr.Errors |= ValidationErrorIssuedAt
171167
}
172168

173-
if !c.VerifyNotBefore(now, false, o) {
169+
if !c.VerifyNotBefore(now, false, opts...) {
174170
vErr.Inner = ErrTokenNotValidYet
175171
vErr.Errors |= ValidationErrorNotValidYet
176172
}
@@ -190,18 +186,17 @@ func (c *StandardClaims) VerifyAudience(cmp string, req bool) bool {
190186

191187
// VerifyExpiresAt compares the exp claim against cmp (cmp < exp).
192188
// If req is false, it will return true, if exp is unset.
193-
func (c *StandardClaims) VerifyExpiresAt(cmp int64, req bool, opts ...*ValidatorOptions) bool {
194-
var s time.Duration
195-
o := MergeValidatorOptions(opts...)
196-
if o != nil {
197-
s = o.leeway
189+
func (c *StandardClaims) VerifyExpiresAt(cmp int64, req bool, opts ...ValidatorOption) bool {
190+
validator := ValidatorOptions{}
191+
for _, o := range opts {
192+
o(&validator)
198193
}
199194
if c.ExpiresAt == 0 {
200-
return verifyExp(nil, time.Unix(cmp, 0), req, s)
195+
return verifyExp(nil, time.Unix(cmp, 0), req, validator.leeway)
201196
}
202197

203198
t := time.Unix(c.ExpiresAt, 0)
204-
return verifyExp(&t, time.Unix(cmp, 0), req, s)
199+
return verifyExp(&t, time.Unix(cmp, 0), req, validator.leeway)
205200
}
206201

207202
// VerifyIssuedAt compares the iat claim against cmp (cmp >= iat).
@@ -217,18 +212,17 @@ func (c *StandardClaims) VerifyIssuedAt(cmp int64, req bool) bool {
217212

218213
// VerifyNotBefore compares the nbf claim against cmp (cmp >= nbf).
219214
// If req is false, it will return true, if nbf is unset.
220-
func (c *StandardClaims) VerifyNotBefore(cmp int64, req bool, opts ...*ValidatorOptions) bool {
221-
var s time.Duration
222-
o := MergeValidatorOptions(opts...)
223-
if o != nil {
224-
s = o.leeway
215+
func (c *StandardClaims) VerifyNotBefore(cmp int64, req bool, opts ...ValidatorOption) bool {
216+
validator := ValidatorOptions{}
217+
for _, o := range opts {
218+
o(&validator)
225219
}
226220
if c.NotBefore == 0 {
227-
return verifyNbf(nil, time.Unix(cmp, 0), req, s)
221+
return verifyNbf(nil, time.Unix(cmp, 0), req, validator.leeway)
228222
}
229223

230224
t := time.Unix(c.NotBefore, 0)
231-
return verifyNbf(&t, time.Unix(cmp, 0), req, s)
225+
return verifyNbf(&t, time.Unix(cmp, 0), req, validator.leeway)
232226
}
233227

234228
// VerifyIssuer compares the iss claim against cmp.

map_claims.go

Lines changed: 17 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -34,31 +34,30 @@ func (m MapClaims) VerifyAudience(cmp string, req bool) bool {
3434

3535
// VerifyExpiresAt compares the exp claim against cmp (cmp <= exp).
3636
// If req is false, it will return true, if exp is unset.
37-
func (m MapClaims) VerifyExpiresAt(cmp int64, req bool, opts ...*ValidatorOptions) bool {
37+
func (m MapClaims) VerifyExpiresAt(cmp int64, req bool, opts ...ValidatorOption) bool {
3838
cmpTime := time.Unix(cmp, 0)
3939

4040
v, ok := m["exp"]
4141
if !ok {
4242
return !req
4343
}
4444

45-
var s time.Duration
46-
o := MergeValidatorOptions(opts...)
47-
if o != nil {
48-
s = o.leeway
45+
validator := ValidatorOptions{}
46+
for _, o := range opts {
47+
o(&validator)
4948
}
5049

5150
switch exp := v.(type) {
5251
case float64:
5352
if exp == 0 {
54-
return verifyExp(nil, cmpTime, req, s)
53+
return verifyExp(nil, cmpTime, req, validator.leeway)
5554
}
5655

57-
return verifyExp(&newNumericDateFromSeconds(exp).Time, cmpTime, req, s)
56+
return verifyExp(&newNumericDateFromSeconds(exp).Time, cmpTime, req, validator.leeway)
5857
case json.Number:
5958
v, _ := exp.Float64()
6059

61-
return verifyExp(&newNumericDateFromSeconds(v).Time, cmpTime, req, s)
60+
return verifyExp(&newNumericDateFromSeconds(v).Time, cmpTime, req, validator.leeway)
6261
}
6362

6463
return false
@@ -92,31 +91,30 @@ func (m MapClaims) VerifyIssuedAt(cmp int64, req bool) bool {
9291

9392
// VerifyNotBefore compares the nbf claim against cmp (cmp >= nbf).
9493
// If req is false, it will return true, if nbf is unset.
95-
func (m MapClaims) VerifyNotBefore(cmp int64, req bool, opts ...*ValidatorOptions) bool {
94+
func (m MapClaims) VerifyNotBefore(cmp int64, req bool, opts ...ValidatorOption) bool {
9695
cmpTime := time.Unix(cmp, 0)
9796

9897
v, ok := m["nbf"]
9998
if !ok {
10099
return !req
101100
}
102101

103-
var s time.Duration
104-
o := MergeValidatorOptions(opts...)
105-
if o != nil {
106-
s = o.leeway
102+
validator := ValidatorOptions{}
103+
for _, o := range opts {
104+
o(&validator)
107105
}
108106

109107
switch nbf := v.(type) {
110108
case float64:
111109
if nbf == 0 {
112-
return verifyNbf(nil, cmpTime, req, s)
110+
return verifyNbf(nil, cmpTime, req, validator.leeway)
113111
}
114112

115-
return verifyNbf(&newNumericDateFromSeconds(nbf).Time, cmpTime, req, s)
113+
return verifyNbf(&newNumericDateFromSeconds(nbf).Time, cmpTime, req, validator.leeway)
116114
case json.Number:
117115
v, _ := nbf.Float64()
118116

119-
return verifyNbf(&newNumericDateFromSeconds(v).Time, cmpTime, req, s)
117+
return verifyNbf(&newNumericDateFromSeconds(v).Time, cmpTime, req, validator.leeway)
120118
}
121119

122120
return false
@@ -133,12 +131,11 @@ func (m MapClaims) VerifyIssuer(cmp string, req bool) bool {
133131
// There is no accounting for clock skew.
134132
// As well, if any of the above claims are not in the token, it will still
135133
// be considered a valid claim.
136-
func (m MapClaims) Valid(opts ...*ValidatorOptions) error {
134+
func (m MapClaims) Valid(opts ...ValidatorOption) error {
137135
vErr := new(ValidationError)
138136
now := TimeFunc().Unix()
139-
o := MergeValidatorOptions(opts...)
140137

141-
if !m.VerifyExpiresAt(now, false, o) {
138+
if !m.VerifyExpiresAt(now, false, opts...) {
142139
// TODO(oxisto): this should be replaced with ErrTokenExpired
143140
vErr.Inner = errors.New("Token is expired")
144141
vErr.Errors |= ValidationErrorExpired
@@ -150,7 +147,7 @@ func (m MapClaims) Valid(opts ...*ValidatorOptions) error {
150147
vErr.Errors |= ValidationErrorIssuedAt
151148
}
152149

153-
if !m.VerifyNotBefore(now, false, o) {
150+
if !m.VerifyNotBefore(now, false, opts...) {
154151
// TODO(oxisto): this should be replaced with ErrTokenNotValidYet
155152
vErr.Inner = errors.New("Token is not valid yet")
156153
vErr.Errors |= ValidationErrorNotValidYet

parser.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ type Parser struct {
2323
// Deprecated: In future releases, this field will not be exported anymore and should be set with an option to NewParser instead.
2424
SkipClaimsValidation bool
2525

26-
options []*ValidatorOptions
26+
options []ValidatorOption
2727
}
2828

2929
// NewParser creates a new Parser with the specified options

parser_option.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,6 @@ func WithoutClaimsValidation() ParserOption {
3333
// WithLeeway returns the ParserOption for specifying the leeway window.
3434
func WithLeeway(d time.Duration) ParserOption {
3535
return func(p *Parser) {
36-
p.options = append(p.options, &ValidatorOptions{leeway: d})
36+
p.options = append(p.options, WithLeewayValidator(d))
3737
}
3838
}

validator_option.go

Lines changed: 10 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,30 +2,20 @@ package jwt
22

33
import "time"
44

5+
// ValidatorOption is used to implement functional-style options that modify the behavior of the parser. To add
6+
// new options, just create a function (ideally beginning with With or Without) that returns an anonymous function that
7+
// takes a *ValidatorOptions type as input and manipulates its configuration accordingly.
8+
type ValidatorOption func(*ValidatorOptions)
9+
510
// ValidatorOptions represents options that can be used for claims validation
611
type ValidatorOptions struct {
7-
leeway time.Duration // Leeway to provide when validating time values
8-
}
9-
10-
func Validator() *ValidatorOptions {
11-
return &ValidatorOptions{}
12+
leeway time.Duration // Leeway to provide when validating time values
1213
}
1314

14-
func (v *ValidatorOptions) SetLeeway(d time.Duration) {
15-
v.leeway = d
16-
}
1715

18-
// MergeValidatorOptions combines the given ValidatorOptions instances into a single ValidatorOptions
19-
// in a last-one-wins fashion
20-
func MergeValidatorOptions(opts ...*ValidatorOptions) *ValidatorOptions {
21-
v := Validator()
22-
for _, opt := range opts {
23-
if opt == nil {
24-
continue
25-
}
26-
if opt.leeway != 0 {
27-
v.SetLeeway(opt.leeway)
28-
}
16+
// WithLeewayValidator is an option to set the clock skew (leeway) windows
17+
func WithLeewayValidator(d time.Duration) ValidatorOption {
18+
return func(v *ValidatorOptions) {
19+
v.leeway = d
2920
}
30-
return v
3121
}

0 commit comments

Comments
 (0)