Skip to content

Commit 6eb1a2f

Browse files
authored
Add RegisteredClaims (#15)
1 parent 51901bf commit 6eb1a2f

File tree

4 files changed

+121
-0
lines changed

4 files changed

+121
-0
lines changed

claims.go

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package paseto
2+
3+
type RegisteredClaims struct {
4+
ID string `json:"jti,omitempty"`
5+
Audience string `json:"aud,omitempty"`
6+
Issuer string `json:"iss,omitempty"`
7+
Subject string `json:"sub,omitempty"`
8+
ExpiresAt *NumericDate `json:"exp,omitempty"`
9+
IssuedAt *NumericDate `json:"iat,omitempty"`
10+
NotBefore *NumericDate `json:"nbf,omitempty"`
11+
}

errors.go

+1
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,5 @@ var (
77
ErrInvalidTokenAuth = errors.New("invalid token authentication")
88
ErrIncorrectTokenFormat = errors.New("incorrect token format")
99
ErrIncorrectTokenHeader = errors.New("incorrect token header")
10+
ErrDateInvalidFormat = errors.New("date is not valid")
1011
)

numeric_date.go

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package paseto
2+
3+
import (
4+
"encoding/json"
5+
"math"
6+
"strconv"
7+
"time"
8+
)
9+
10+
type NumericDate struct {
11+
time.Time
12+
}
13+
14+
func NewNumericDate(t time.Time) *NumericDate {
15+
return &NumericDate{t}
16+
}
17+
18+
func (t NumericDate) MarshalJSON() ([]byte, error) {
19+
if t.IsZero() {
20+
return []byte("null"), nil
21+
}
22+
return []byte(strconv.FormatInt(t.Unix(), 10)), nil
23+
}
24+
25+
func (t *NumericDate) UnmarshalJSON(data []byte) error {
26+
var value json.Number
27+
if err := json.Unmarshal(data, &value); err != nil {
28+
return ErrDateInvalidFormat
29+
}
30+
f, err := value.Float64()
31+
if err != nil {
32+
return ErrDateInvalidFormat
33+
}
34+
sec, dec := math.Modf(f)
35+
ts := time.Unix(int64(sec), int64(dec*1e9))
36+
*t = NumericDate{ts}
37+
return nil
38+
}

numeric_date_test.go

+71
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
package paseto
2+
3+
import (
4+
"strconv"
5+
"testing"
6+
"time"
7+
)
8+
9+
func TestNumericDateMarshal(t *testing.T) {
10+
now := time.Now()
11+
nowTS := now.Unix()
12+
13+
testCases := []struct {
14+
value *NumericDate
15+
want string
16+
}{
17+
{NewNumericDate(time.Time{}), `null`},
18+
{NewNumericDate(now), strconv.Itoa(int(nowTS))},
19+
}
20+
21+
for _, tc := range testCases {
22+
raw, err := tc.value.MarshalJSON()
23+
mustOk(t, err)
24+
mustEqual(t, string(raw), tc.want)
25+
}
26+
}
27+
28+
func TestNumericDateUnmarshal(t *testing.T) {
29+
testCases := []struct {
30+
s string
31+
want NumericDate
32+
}{
33+
{`1588707274`, asNumericDate(1588707274)},
34+
{`1588707274.3769999`, asNumericDate(1588707274)},
35+
{`"12345"`, asNumericDate(12345)},
36+
}
37+
38+
for _, tc := range testCases {
39+
var have NumericDate
40+
err := have.UnmarshalJSON([]byte(tc.s))
41+
mustOk(t, err)
42+
mustEqual(t, have.Unix(), tc.want.Unix())
43+
}
44+
}
45+
46+
func TestNumericDateUnmarshalMalformed(t *testing.T) {
47+
testCases := []struct {
48+
value string
49+
}{
50+
{``},
51+
{`{}`},
52+
{`[{}]`},
53+
{`abc12`},
54+
{`"abc"`},
55+
{`["admin",{}]`},
56+
{`["admin",123]`},
57+
{`{}`},
58+
{`[]`},
59+
{`1e+309`},
60+
}
61+
62+
for _, tc := range testCases {
63+
var nd NumericDate
64+
err := nd.UnmarshalJSON([]byte(tc.value))
65+
mustFail(t, err)
66+
}
67+
}
68+
69+
func asNumericDate(n int64) NumericDate {
70+
return *NewNumericDate(time.Unix(n, 0))
71+
}

0 commit comments

Comments
 (0)