forked from SermoDigital/jose
-
Notifications
You must be signed in to change notification settings - Fork 0
/
claims.go
112 lines (93 loc) · 2.41 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
package jwt
import (
"encoding/json"
"github.com/SermoDigital/jose"
)
// Claims implements a set of JOSE Claims with the addition of some helper
// methods, similar to net/url.Values.
type Claims map[string]interface{}
// Validate validates the Claims per the claims found in
// https://tools.ietf.org/html/rfc7519#section-4.1
func (c Claims) Validate(now, expLeeway, nbfLeeway int64) error {
if exp, ok := c.expiration(); ok {
if !within(exp, expLeeway, now) {
return ErrTokenIsExpired
}
}
if nbf, ok := c.notBefore(); ok {
if !within(nbf, nbfLeeway, now) {
return ErrTokenNotYetValid
}
}
return nil
}
func (c Claims) expiration() (int64, bool) {
v, ok := c.Get("exp").(int64)
return v, ok
}
func (c Claims) notBefore() (int64, bool) {
v, ok := c.Get("nbf").(int64)
return v, ok
}
func within(cur, delta, max int64) bool {
return cur+delta < max || cur-delta < max
}
// Get retrieves the value corresponding with key from the Claims.
func (c Claims) Get(key string) interface{} {
if c == nil {
return nil
}
return c[key]
}
// Set sets Claims[key] = val. It'll overwrite without warning.
func (c Claims) Set(key string, val interface{}) {
c[key] = val
}
// Del removes the value that corresponds with key from the Claims.
func (c Claims) Del(key string) {
delete(c, key)
}
// Has returns true if a value for the given key exists inside the Claims.
func (c Claims) Has(key string) bool {
_, ok := c[key]
return ok
}
// MarshalJSON implements json.Marshaler for Claims.
func (c Claims) MarshalJSON() ([]byte, error) {
if c == nil || len(c) == 0 {
return nil, nil
}
b, err := json.Marshal(map[string]interface{}(c))
if err != nil {
return nil, err
}
return jose.EncodeEscape(b), nil
}
// Base64 implements the Encoder interface.
func (c Claims) Base64() ([]byte, error) {
return c.MarshalJSON()
}
// UnmarshalJSON implements json.Unmarshaler for Claims.
func (c *Claims) UnmarshalJSON(b []byte) error {
if b == nil {
return nil
}
b, err := jose.DecodeEscaped(b)
if err != nil {
return err
}
// Since json.Unmarshal calls UnmarshalJSON,
// calling json.Unmarshal on *p would be infinitely recursive
// A temp variable is needed because &map[string]interface{}(*p) is
// invalid Go.
tmp := map[string]interface{}(*c)
if err = json.Unmarshal(b, &tmp); err != nil {
return err
}
*c = Claims(tmp)
return nil
}
var (
_ json.Marshaler = (Claims)(nil)
_ json.Unmarshaler = (*Claims)(nil)
)