-
-
Notifications
You must be signed in to change notification settings - Fork 17
/
parser.go
161 lines (140 loc) · 5.6 KB
/
parser.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
package paseto
import (
"time"
t "aidanwoods.dev/go-result"
)
type TokenDecoder[T any] func(TokenClaimsAndFooter) (*T, error)
// Parser is used to verify or decrypt a token, and can be provided with
// a set of rules.
type Parser[T any] struct {
rules []Rule[T]
decode TokenDecoder[T]
}
// NewParser returns a parser with NotExpired rule preloaded.
func NewParser() Parser[Token] {
return Parser[Token]{
rules: []Rule[Token]{NotExpired()},
decode: StdDecoder,
}
}
// NewParser returns a parser with NotExpired rule preloaded.
func NewParserT[T TokenExpiration](decoder TokenDecoder[T]) Parser[T] {
return Parser[T]{
rules: []Rule[T]{NotExpiredT[T]()},
decode: decoder,
}
}
// NewParserWithoutExpiryCheck returns a parser with no currently set rules.
func NewParserWithoutExpiryCheck() Parser[Token] {
return Parser[Token]{
rules: []Rule[Token]{},
decode: StdDecoder,
}
}
// NewParserForValidNow returns a parser that will require parsed tokens to be
// valid "now".
func NewParserForValidNow() Parser[Token] {
return Parser[Token]{
rules: []Rule[Token]{ValidAt(time.Now())},
decode: StdDecoder,
}
}
// MakeParser allows a parser to be constructed with a specified set of rules.
func MakeParser(rules []Rule[Token]) Parser[Token] {
return Parser[Token]{
rules: rules,
decode: StdDecoder,
}
}
// MakeParser allows a parser to be constructed with a specified set of rules.
func MakeParserT[T any](decoder TokenDecoder[T], rules []Rule[T]) Parser[T] {
return Parser[T]{
rules: rules,
decode: decoder,
}
}
// ParseV2Local will parse and decrypt a v2 local paseto and validate against
// any parser rules. Error if parsing, decryption, or any rule fails.
func (p Parser[T]) ParseV2Local(key V2SymmetricKey, tainted string) (*T, error) {
return t.Chain3[T, T, TokenClaimsAndFooter](
newMessage(V2Local, tainted)).
AndThen(func(m message) t.Result[TokenClaimsAndFooter] { return m.v2Decrypt(key) }).
AndThen(func(caf TokenClaimsAndFooter) t.Result[T] { return t.NewPtrResult(p.decode(caf)) }).
AndThen(p.validate).
Results()
}
// ParseV2Public will parse and verify a v2 public paseto and validate against
// any parser rules. Error if parsing, verification, or any rule fails.
func (p Parser[T]) ParseV2Public(key V2AsymmetricPublicKey, tainted string) (*T, error) {
return t.Chain3[T, T, TokenClaimsAndFooter](
newMessage(V2Public, tainted)).
AndThen(func(m message) t.Result[TokenClaimsAndFooter] { return m.v2Verify(key) }).
AndThen(func(caf TokenClaimsAndFooter) t.Result[T] { return t.NewPtrResult(p.decode(caf)) }).
AndThen(p.validate).
Results()
}
// ParseV3Local will parse and decrypt a v3 local paseto and validate against
// any parser rules. Error if parsing, decryption, or any rule fails.
func (p Parser[T]) ParseV3Local(key V3SymmetricKey, tainted string, implicit []byte) (*T, error) {
return t.Chain3[T, T, TokenClaimsAndFooter](
newMessage(V3Local, tainted)).
AndThen(func(m message) t.Result[TokenClaimsAndFooter] { return m.v3Decrypt(key, implicit) }).
AndThen(func(caf TokenClaimsAndFooter) t.Result[T] { return t.NewPtrResult(p.decode(caf)) }).
AndThen(p.validate).
Results()
}
// ParseV3Public will parse and verify a v3 public paseto and validate against
// any parser rules. Error if parsing, verification, or any rule fails.
func (p Parser[T]) ParseV3Public(key V3AsymmetricPublicKey, tainted string, implicit []byte) (*T, error) {
return t.Chain3[T, T, TokenClaimsAndFooter](
newMessage(V3Public, tainted)).
AndThen(func(m message) t.Result[TokenClaimsAndFooter] { return m.v3Verify(key, implicit) }).
AndThen(func(caf TokenClaimsAndFooter) t.Result[T] { return t.NewPtrResult(p.decode(caf)) }).
AndThen(p.validate).
Results()
}
// ParseV4Local will parse and decrypt a v4 local paseto and validate against
// any parser rules. Error if parsing, decryption, or any rule fails.
func (p Parser[T]) ParseV4Local(key V4SymmetricKey, tainted string, implicit []byte) (*T, error) {
return t.Chain3[T, T, TokenClaimsAndFooter](
newMessage(V4Local, tainted)).
AndThen(func(m message) t.Result[TokenClaimsAndFooter] { return m.v4Decrypt(key, implicit) }).
AndThen(func(caf TokenClaimsAndFooter) t.Result[T] { return t.NewPtrResult(p.decode(caf)) }).
AndThen(p.validate).
Results()
}
// ParseV4Public will parse and verify a v4 public paseto and validate against
// any parser rules. Error if parsing, verification, or any rule fails.
func (p Parser[T]) ParseV4Public(key V4AsymmetricPublicKey, tainted string, implicit []byte) (*T, error) {
return t.Chain3[T, T, TokenClaimsAndFooter](
newMessage(V4Public, tainted)).
AndThen(func(m message) t.Result[TokenClaimsAndFooter] { return m.v4Verify(key, implicit) }).
AndThen(func(caf TokenClaimsAndFooter) t.Result[T] { return t.NewPtrResult(p.decode(caf)) }).
AndThen(p.validate).
Results()
}
// UnsafeParseFooter returns the footer of a Paseto message. Beware that this
// footer is not cryptographically verified at this stage, nor are any claims
// validated.
func (p Parser[T]) UnsafeParseFooter(protocol Protocol, tainted string) ([]byte, error) {
return t.Chain[[]byte](
newMessage(protocol, tainted)).
Map(message.unsafeFooter).
ResultsMappingEmpty()
}
// SetRules will overwrite any currently set rules with those specified.
func (p *Parser[T]) SetRules(rules []Rule[T]) {
p.rules = rules
}
// AddRule will add the given rule(s) to any already specified.
func (p *Parser[T]) AddRule(rule ...Rule[T]) {
p.rules = append(p.rules, rule...)
}
func (p Parser[T]) validate(token T) t.Result[T] {
for _, rule := range p.rules {
if err := rule(token); err != nil {
return t.Err[T](newRuleError(err))
}
}
return t.Ok(token)
}