...
1
21
22 package jwt
23
24 import (
25 "strings"
26 "time"
27
28 "github.com/pborman/uuid"
29 )
30
31
32 type JWTScopeFieldEnum int
33
34 const (
35 JWTScopeFieldUnset JWTScopeFieldEnum = iota
36 JWTScopeFieldList
37 JWTScopeFieldString
38 JWTScopeFieldBoth
39 )
40
41 type JWTClaimsDefaults struct {
42 ExpiresAt time.Time
43 IssuedAt time.Time
44 Issuer string
45 Scope []string
46 }
47
48 type JWTClaimsContainer interface {
49
50 With(expiry time.Time, scope, audience []string) JWTClaimsContainer
51
52
53
54 WithDefaults(iat time.Time, issuer string) JWTClaimsContainer
55
56
57 WithScopeField(scopeField JWTScopeFieldEnum) JWTClaimsContainer
58
59
60 ToMapClaims() MapClaims
61 }
62
63
64 type JWTClaims struct {
65 Subject string
66 Issuer string
67 Audience []string
68 JTI string
69 IssuedAt time.Time
70 NotBefore time.Time
71 ExpiresAt time.Time
72 Scope []string
73 Extra map[string]interface{}
74 ScopeField JWTScopeFieldEnum
75 }
76
77 func (c *JWTClaims) With(expiry time.Time, scope, audience []string) JWTClaimsContainer {
78 c.ExpiresAt = expiry
79 c.Scope = scope
80 c.Audience = audience
81 return c
82 }
83
84 func (c *JWTClaims) WithDefaults(iat time.Time, issuer string) JWTClaimsContainer {
85 if c.IssuedAt.IsZero() {
86 c.IssuedAt = iat
87 }
88
89 if c.Issuer == "" {
90 c.Issuer = issuer
91 }
92 return c
93 }
94
95 func (c *JWTClaims) WithScopeField(scopeField JWTScopeFieldEnum) JWTClaimsContainer {
96 c.ScopeField = scopeField
97 return c
98 }
99
100
101 func (c *JWTClaims) ToMap() map[string]interface{} {
102 var ret = Copy(c.Extra)
103
104 if c.Subject != "" {
105 ret["sub"] = c.Subject
106 } else {
107 delete(ret, "sub")
108 }
109
110 if c.Issuer != "" {
111 ret["iss"] = c.Issuer
112 } else {
113 delete(ret, "iss")
114 }
115
116 if c.JTI != "" {
117 ret["jti"] = c.JTI
118 } else {
119 ret["jti"] = uuid.New()
120 }
121
122 if len(c.Audience) > 0 {
123 ret["aud"] = c.Audience
124 } else {
125 ret["aud"] = []string{}
126 }
127
128 if !c.IssuedAt.IsZero() {
129 ret["iat"] = c.IssuedAt.Unix()
130 } else {
131 delete(ret, "iat")
132 }
133
134 if !c.NotBefore.IsZero() {
135 ret["nbf"] = c.NotBefore.Unix()
136 } else {
137 delete(ret, "nbf")
138 }
139
140 if !c.ExpiresAt.IsZero() {
141 ret["exp"] = c.ExpiresAt.Unix()
142 } else {
143 delete(ret, "exp")
144 }
145
146 if c.Scope != nil {
147
148 if c.ScopeField == JWTScopeFieldUnset || c.ScopeField == JWTScopeFieldList || c.ScopeField == JWTScopeFieldBoth {
149 ret["scp"] = c.Scope
150 }
151 if c.ScopeField == JWTScopeFieldString || c.ScopeField == JWTScopeFieldBoth {
152 ret["scope"] = strings.Join(c.Scope, " ")
153 }
154 } else {
155 delete(ret, "scp")
156 delete(ret, "scope")
157 }
158
159 return ret
160 }
161
162
163 func (c *JWTClaims) FromMap(m map[string]interface{}) {
164 c.Extra = make(map[string]interface{})
165 for k, v := range m {
166 switch k {
167 case "jti":
168 if s, ok := v.(string); ok {
169 c.JTI = s
170 }
171 case "sub":
172 if s, ok := v.(string); ok {
173 c.Subject = s
174 }
175 case "iss":
176 if s, ok := v.(string); ok {
177 c.Issuer = s
178 }
179 case "aud":
180 if s, ok := v.(string); ok {
181 c.Audience = []string{s}
182 } else if s, ok := v.([]string); ok {
183 c.Audience = s
184 }
185 case "iat":
186 c.IssuedAt = toTime(v, c.IssuedAt)
187 case "nbf":
188 c.NotBefore = toTime(v, c.NotBefore)
189 case "exp":
190 c.ExpiresAt = toTime(v, c.ExpiresAt)
191 case "scp":
192 switch s := v.(type) {
193 case []string:
194 c.Scope = s
195 if c.ScopeField == JWTScopeFieldString {
196 c.ScopeField = JWTScopeFieldBoth
197 } else if c.ScopeField == JWTScopeFieldUnset {
198 c.ScopeField = JWTScopeFieldList
199 }
200 case []interface{}:
201 c.Scope = make([]string, len(s))
202 for i, vi := range s {
203 if s, ok := vi.(string); ok {
204 c.Scope[i] = s
205 }
206 }
207 if c.ScopeField == JWTScopeFieldString {
208 c.ScopeField = JWTScopeFieldBoth
209 } else if c.ScopeField == JWTScopeFieldUnset {
210 c.ScopeField = JWTScopeFieldList
211 }
212 }
213 case "scope":
214 if s, ok := v.(string); ok {
215 c.Scope = strings.Split(s, " ")
216 if c.ScopeField == JWTScopeFieldList {
217 c.ScopeField = JWTScopeFieldBoth
218 } else if c.ScopeField == JWTScopeFieldUnset {
219 c.ScopeField = JWTScopeFieldString
220 }
221 }
222 default:
223 c.Extra[k] = v
224 }
225 }
226 }
227
228 func toTime(v interface{}, def time.Time) (t time.Time) {
229 t = def
230 switch a := v.(type) {
231 case float64:
232 t = time.Unix(int64(a), 0).UTC()
233 case int64:
234 t = time.Unix(a, 0).UTC()
235 }
236 return
237 }
238
239
240 func (c *JWTClaims) Add(key string, value interface{}) {
241 if c.Extra == nil {
242 c.Extra = make(map[string]interface{})
243 }
244 c.Extra[key] = value
245 }
246
247
248 func (c JWTClaims) Get(key string) interface{} {
249 return c.ToMap()[key]
250 }
251
252
253 func (c JWTClaims) ToMapClaims() MapClaims {
254 return c.ToMap()
255 }
256
257
258 func (c *JWTClaims) FromMapClaims(mc MapClaims) {
259 c.FromMap(mc)
260 }
261
View as plain text