1 package jwt
2 3 import (
4 "encoding/json"
5 "fmt"
6 )
7 8 // MapClaims is a claims type that uses the map[string]any for JSON
9 // decoding. This is the default claims type if you don't supply one
10 type MapClaims map[string]any
11 12 // GetExpirationTime implements the Claims interface.
13 func (m MapClaims) GetExpirationTime() (*NumericDate, error) {
14 return m.parseNumericDate("exp")
15 }
16 17 // GetNotBefore implements the Claims interface.
18 func (m MapClaims) GetNotBefore() (*NumericDate, error) {
19 return m.parseNumericDate("nbf")
20 }
21 22 // GetIssuedAt implements the Claims interface.
23 func (m MapClaims) GetIssuedAt() (*NumericDate, error) {
24 return m.parseNumericDate("iat")
25 }
26 27 // GetAudience implements the Claims interface.
28 func (m MapClaims) GetAudience() (ClaimStrings, error) {
29 return m.parseClaimsString("aud")
30 }
31 32 // GetIssuer implements the Claims interface.
33 func (m MapClaims) GetIssuer() (string, error) {
34 return m.parseString("iss")
35 }
36 37 // GetSubject implements the Claims interface.
38 func (m MapClaims) GetSubject() (string, error) {
39 return m.parseString("sub")
40 }
41 42 // parseNumericDate tries to parse a key in the map claims type as a number
43 // date. This will succeed, if the underlying type is either a [float64] or a
44 // [json.Number]. Otherwise, nil will be returned.
45 func (m MapClaims) parseNumericDate(key string) (*NumericDate, error) {
46 v, ok := m[key]
47 if !ok {
48 return nil, nil
49 }
50 51 switch exp := v.(type) {
52 case float64:
53 if exp == 0 {
54 return nil, nil
55 }
56 57 return newNumericDateFromSeconds(exp), nil
58 case json.Number:
59 v, _ := exp.Float64()
60 61 return newNumericDateFromSeconds(v), nil
62 }
63 64 return nil, newError(fmt.Sprintf("%s is invalid", key), ErrInvalidType)
65 }
66 67 // parseClaimsString tries to parse a key in the map claims type as a
68 // [ClaimsStrings] type, which can either be a string or an array of string.
69 func (m MapClaims) parseClaimsString(key string) (ClaimStrings, error) {
70 var cs []string
71 switch v := m[key].(type) {
72 case string:
73 cs = append(cs, v)
74 case []string:
75 cs = v
76 case []any:
77 for _, a := range v {
78 vs, ok := a.(string)
79 if !ok {
80 return nil, newError(fmt.Sprintf("%s is invalid", key), ErrInvalidType)
81 }
82 cs = append(cs, vs)
83 }
84 }
85 86 return cs, nil
87 }
88 89 // parseString tries to parse a key in the map claims type as a [string] type.
90 // If the key does not exist, an empty string is returned. If the key has the
91 // wrong type, an error is returned.
92 func (m MapClaims) parseString(key string) (string, error) {
93 var (
94 ok bool
95 raw any
96 iss string
97 )
98 raw, ok = m[key]
99 if !ok {
100 return "", nil
101 }
102 103 iss, ok = raw.(string)
104 if !ok {
105 return "", newError(fmt.Sprintf("%s is invalid", key), ErrInvalidType)
106 }
107 108 return iss, nil
109 }
110