11package jwk
22
33import (
4+ "bytes"
45 "context"
6+ "fmt"
7+ "sort"
58
69 "github.com/lestrrat-go/iter/arrayiter"
710 "github.com/lestrrat-go/jwx/internal/json"
@@ -11,7 +14,17 @@ import (
1114
1215// NewSet creates and empty `jwk.Set` object
1316func NewSet () Set {
14- return & set {}
17+ return & set {
18+ privateParams : make (map [string ]interface {}),
19+ }
20+ }
21+
22+ func (s * set ) Field (n string ) (interface {}, bool ) {
23+ s .mu .RLock ()
24+ defer s .mu .RUnlock ()
25+
26+ v , ok := s .privateParams [n ]
27+ return v , ok
1528}
1629
1730func (s * set ) Get (idx int ) (Key , bool ) {
@@ -105,10 +118,6 @@ func iterate(ctx context.Context, keys []Key, ch chan *KeyPair) {
105118 }
106119}
107120
108- type keySetMarshalProxy struct {
109- Keys []json.RawMessage `json:"keys"`
110- }
111-
112121func (s * set ) MarshalJSON () ([]byte , error ) {
113122 s .mu .RLock ()
114123 defer s .mu .RUnlock ()
@@ -117,16 +126,36 @@ func (s *set) MarshalJSON() ([]byte, error) {
117126 defer pool .ReleaseBytesBuffer (buf )
118127 enc := json .NewEncoder (buf )
119128
120- buf .WriteString (`{"keys":[` )
121- for i , k := range s .keys {
129+ fields := []string {`keys` }
130+ for k := range s .privateParams {
131+ fields = append (fields , k )
132+ }
133+ sort .Strings (fields )
134+
135+ buf .WriteByte ('{' )
136+ for i , field := range fields {
122137 if i > 0 {
123138 buf .WriteByte (',' )
124139 }
125- if err := enc .Encode (k ); err != nil {
126- return nil , errors .Wrapf (err , `failed to marshal key #%d` , i )
140+ fmt .Fprintf (buf , `%q:` , field )
141+ if field != `keys` {
142+ if err := enc .Encode (s .privateParams [field ]); err != nil {
143+ return nil , errors .Wrapf (err , `failed to marshal field %q` , field )
144+ }
145+ } else {
146+ buf .WriteByte ('[' )
147+ for j , k := range s .keys {
148+ if j > 0 {
149+ buf .WriteByte (',' )
150+ }
151+ if err := enc .Encode (k ); err != nil {
152+ return nil , errors .Wrapf (err , `failed to marshal key #%d` , i )
153+ }
154+ }
155+ buf .WriteByte (']' )
127156 }
128157 }
129- buf .WriteString ( "]}" )
158+ buf .WriteByte ( '}' )
130159
131160 ret := make ([]byte , buf .Len ())
132161 copy (ret , buf .Bytes ())
@@ -137,10 +166,8 @@ func (s *set) UnmarshalJSON(data []byte) error {
137166 s .mu .Lock ()
138167 defer s .mu .Unlock ()
139168
140- var proxy keySetMarshalProxy
141- if err := json .Unmarshal (data , & proxy ); err != nil {
142- return errors .Wrap (err , `failed to unmarshal into Key (proxy)` )
143- }
169+ s .privateParams = make (map [string ]interface {})
170+ s .keys = nil
144171
145172 var options []ParseOption
146173 if dc := s .dc ; dc != nil {
@@ -149,20 +176,61 @@ func (s *set) UnmarshalJSON(data []byte) error {
149176 }
150177 }
151178
152- if len (proxy .Keys ) == 0 {
153- k , err := ParseKey (data , options ... )
179+ var sawKeysField bool
180+ dec := json .NewDecoder (bytes .NewReader (data ))
181+ LOOP:
182+ for {
183+ tok , err := dec .Token ()
154184 if err != nil {
155- return errors .Wrap (err , `failed to unmarshal key from JSON headers ` )
185+ return errors .Wrap (err , `error reading token ` )
156186 }
157- s .keys = append (s .keys , k )
158- } else {
159- for i , buf := range proxy .Keys {
160- k , err := ParseKey ([]byte (buf ), options ... )
161- if err != nil {
162- return errors .Wrapf (err , `failed to unmarshal key #%d (total %d) from multi-key JWK set` , i + 1 , len (proxy .Keys ))
187+
188+ switch tok := tok .(type ) {
189+ case json.Delim :
190+ // Assuming we're doing everything correctly, we should ONLY
191+ // get either '{' or '}' here.
192+ if tok == '}' { // End of object
193+ break LOOP
194+ } else if tok != '{' {
195+ return errors .Errorf (`expected '{', but got '%c'` , tok )
163196 }
164- s .keys = append (s .keys , k )
197+ case string :
198+ switch tok {
199+ case "keys" :
200+ sawKeysField = true
201+ var list []json.RawMessage
202+ if err := dec .Decode (& list ); err != nil {
203+ return errors .Wrap (err , `failed to decode "keys"` )
204+ }
205+
206+ for i , keysrc := range list {
207+ key , err := ParseKey (keysrc , options ... )
208+ if err != nil {
209+ return errors .Wrapf (err , `failed to code key #%d in "keys"` , i )
210+ }
211+ s .keys = append (s .keys , key )
212+ }
213+ default :
214+ var v interface {}
215+ if err := dec .Decode (& v ); err != nil {
216+ return errors .Wrapf (err , `failed to decode value for key %q` , tok )
217+ }
218+ s .privateParams [tok ] = v
219+ }
220+ }
221+ }
222+
223+ // This is really silly, but we can only detect the
224+ // lack of the "keys" field after going through the
225+ // entire object once
226+ // Not checking for len(s.keys) == 0, because it could be
227+ // an empty key set
228+ if ! sawKeysField {
229+ key , err := ParseKey (data , options ... )
230+ if err != nil {
231+ return errors .Wrapf (err , `failed to parse sole key in key set` )
165232 }
233+ s .keys = append (s .keys , key )
166234 }
167235 return nil
168236}
0 commit comments