@@ -42,6 +42,8 @@ func TestNewAccessRequest(t *testing.T) {
4242 ctrl := gomock .NewController (t )
4343 store := internal .NewMockStorage (ctrl )
4444 handler := internal .NewMockTokenEndpointHandler (ctrl )
45+ handler .EXPECT ().CanHandleTokenEndpointRequest (gomock .Any ()).Return (true ).AnyTimes ()
46+ handler .EXPECT ().CanSkipClientAuth (gomock .Any ()).Return (false ).AnyTimes ()
4547 hasher := internal .NewMockHasher (ctrl )
4648 defer ctrl .Finish ()
4749
@@ -94,6 +96,7 @@ func TestNewAccessRequest(t *testing.T) {
9496 mock : func () {
9597 store .EXPECT ().GetClient (gomock .Any (), gomock .Eq ("foo" )).Return (nil , errors .New ("" ))
9698 },
99+ handlers : TokenEndpointHandlers {handler },
97100 },
98101 {
99102 header : http.Header {
@@ -118,6 +121,7 @@ func TestNewAccessRequest(t *testing.T) {
118121 mock : func () {
119122 store .EXPECT ().GetClient (gomock .Any (), gomock .Eq ("foo" )).Return (nil , errors .New ("" ))
120123 },
124+ handlers : TokenEndpointHandlers {handler },
121125 },
122126 {
123127 header : http.Header {
@@ -134,6 +138,7 @@ func TestNewAccessRequest(t *testing.T) {
134138 client .Secret = []byte ("foo" )
135139 hasher .EXPECT ().Compare (context .TODO (), gomock .Eq ([]byte ("foo" )), gomock .Eq ([]byte ("bar" ))).Return (errors .New ("" ))
136140 },
141+ handlers : TokenEndpointHandlers {handler },
137142 },
138143 {
139144 header : http.Header {
@@ -221,6 +226,239 @@ func TestNewAccessRequest(t *testing.T) {
221226 }
222227}
223228
229+ func TestNewAccessRequestWithoutClientAuth (t * testing.T ) {
230+ ctrl := gomock .NewController (t )
231+ store := internal .NewMockStorage (ctrl )
232+ handler := internal .NewMockTokenEndpointHandler (ctrl )
233+ handler .EXPECT ().CanHandleTokenEndpointRequest (gomock .Any ()).Return (true ).AnyTimes ()
234+ handler .EXPECT ().CanSkipClientAuth (gomock .Any ()).Return (true ).AnyTimes ()
235+ hasher := internal .NewMockHasher (ctrl )
236+ defer ctrl .Finish ()
237+
238+ client := & DefaultClient {}
239+ anotherClient := & DefaultClient {ID : "another" }
240+ fosite := & Fosite {Store : store , Hasher : hasher , AudienceMatchingStrategy : DefaultAudienceMatchingStrategy }
241+ for k , c := range []struct {
242+ header http.Header
243+ form url.Values
244+ mock func ()
245+ method string
246+ expectErr error
247+ expect * AccessRequest
248+ handlers TokenEndpointHandlers
249+ }{
250+ // No grant type -> error
251+ {
252+ form : url.Values {},
253+ mock : func () {
254+ store .EXPECT ().GetClient (gomock .Any (), gomock .Any ()).Times (0 )
255+ },
256+ method : "POST" ,
257+ expectErr : ErrInvalidRequest ,
258+ },
259+ // No registered handlers -> error
260+ {
261+ form : url.Values {
262+ "grant_type" : {"foo" },
263+ },
264+ mock : func () {
265+ store .EXPECT ().GetClient (gomock .Any (), gomock .Any ()).Times (0 )
266+ },
267+ method : "POST" ,
268+ expectErr : ErrInvalidRequest ,
269+ handlers : TokenEndpointHandlers {},
270+ },
271+ // Handler can skip client auth and ignores missing client.
272+ {
273+ header : http.Header {
274+ "Authorization" : {basicAuth ("foo" , "bar" )},
275+ },
276+ form : url.Values {
277+ "grant_type" : {"foo" },
278+ },
279+ mock : func () {
280+ // despite error from storage, we should success, because client auth is not required
281+ store .EXPECT ().GetClient (gomock .Any (), "foo" ).Return (nil , errors .New ("no client" )).Times (1 )
282+ handler .EXPECT ().HandleTokenEndpointRequest (gomock .Any (), gomock .Any ()).Return (nil )
283+ },
284+ method : "POST" ,
285+ expect : & AccessRequest {
286+ GrantTypes : Arguments {"foo" },
287+ Request : Request {
288+ Client : client ,
289+ },
290+ },
291+ handlers : TokenEndpointHandlers {handler },
292+ },
293+ // Should pass if no auth is set in the header and can skip!
294+ {
295+ form : url.Values {
296+ "grant_type" : {"foo" },
297+ },
298+ mock : func () {
299+ handler .EXPECT ().HandleTokenEndpointRequest (gomock .Any (), gomock .Any ()).Return (nil )
300+ },
301+ method : "POST" ,
302+ expect : & AccessRequest {
303+ GrantTypes : Arguments {"foo" },
304+ Request : Request {
305+ Client : client ,
306+ },
307+ },
308+ handlers : TokenEndpointHandlers {handler },
309+ },
310+ // Should also pass if client auth is set!
311+ {
312+ header : http.Header {
313+ "Authorization" : {basicAuth ("foo" , "bar" )},
314+ },
315+ form : url.Values {
316+ "grant_type" : {"foo" },
317+ },
318+ mock : func () {
319+ store .EXPECT ().GetClient (gomock .Any (), "foo" ).Return (anotherClient , nil ).Times (1 )
320+ hasher .EXPECT ().Compare (gomock .Any (), gomock .Any (), gomock .Any ()).Return (nil ).Times (1 )
321+ handler .EXPECT ().HandleTokenEndpointRequest (gomock .Any (), gomock .Any ()).Return (nil )
322+ },
323+ method : "POST" ,
324+ expect : & AccessRequest {
325+ GrantTypes : Arguments {"foo" },
326+ Request : Request {
327+ Client : anotherClient ,
328+ },
329+ },
330+ handlers : TokenEndpointHandlers {handler },
331+ },
332+ } {
333+ t .Run (fmt .Sprintf ("case=%d" , k ), func (t * testing.T ) {
334+ r := & http.Request {
335+ Header : c .header ,
336+ PostForm : c .form ,
337+ Form : c .form ,
338+ Method : c .method ,
339+ }
340+ c .mock ()
341+ ctx := NewContext ()
342+ fosite .TokenEndpointHandlers = c .handlers
343+ ar , err := fosite .NewAccessRequest (ctx , r , new (DefaultSession ))
344+
345+ if c .expectErr != nil {
346+ assert .EqualError (t , err , c .expectErr .Error ())
347+ } else {
348+ require .NoError (t , err )
349+ AssertObjectKeysEqual (t , c .expect , ar , "GrantTypes" , "Client" )
350+ assert .NotNil (t , ar .GetRequestedAt ())
351+ }
352+ })
353+ }
354+ }
355+
356+ // In this test case one handler requires client auth and another handler not.
357+ func TestNewAccessRequestWithMixedClientAuth (t * testing.T ) {
358+ ctrl := gomock .NewController (t )
359+ store := internal .NewMockStorage (ctrl )
360+
361+ handlerWithClientAuth := internal .NewMockTokenEndpointHandler (ctrl )
362+ handlerWithClientAuth .EXPECT ().CanHandleTokenEndpointRequest (gomock .Any ()).Return (true ).AnyTimes ()
363+ handlerWithClientAuth .EXPECT ().CanSkipClientAuth (gomock .Any ()).Return (false ).AnyTimes ()
364+
365+ handlerWithoutClientAuth := internal .NewMockTokenEndpointHandler (ctrl )
366+ handlerWithoutClientAuth .EXPECT ().CanHandleTokenEndpointRequest (gomock .Any ()).Return (true ).AnyTimes ()
367+ handlerWithoutClientAuth .EXPECT ().CanSkipClientAuth (gomock .Any ()).Return (true ).AnyTimes ()
368+
369+ hasher := internal .NewMockHasher (ctrl )
370+ defer ctrl .Finish ()
371+
372+ client := & DefaultClient {}
373+ fosite := & Fosite {Store : store , Hasher : hasher , AudienceMatchingStrategy : DefaultAudienceMatchingStrategy }
374+ for k , c := range []struct {
375+ header http.Header
376+ form url.Values
377+ mock func ()
378+ method string
379+ expectErr error
380+ expect * AccessRequest
381+ handlers TokenEndpointHandlers
382+ }{
383+ {
384+ header : http.Header {
385+ "Authorization" : {basicAuth ("foo" , "bar" )},
386+ },
387+ form : url.Values {
388+ "grant_type" : {"foo" },
389+ },
390+ mock : func () {
391+ store .EXPECT ().GetClient (gomock .Any (), gomock .Eq ("foo" )).Return (client , nil )
392+ client .Public = false
393+ client .Secret = []byte ("foo" )
394+ hasher .EXPECT ().Compare (context .TODO (), gomock .Eq ([]byte ("foo" )), gomock .Eq ([]byte ("bar" ))).Return (errors .New ("hash err" ))
395+ handlerWithoutClientAuth .EXPECT ().HandleTokenEndpointRequest (gomock .Any (), gomock .Any ()).Return (nil )
396+ },
397+ method : "POST" ,
398+ expectErr : ErrInvalidClient ,
399+ handlers : TokenEndpointHandlers {handlerWithoutClientAuth , handlerWithClientAuth },
400+ },
401+ {
402+ header : http.Header {
403+ "Authorization" : {basicAuth ("foo" , "bar" )},
404+ },
405+ form : url.Values {
406+ "grant_type" : {"foo" },
407+ },
408+ mock : func () {
409+ store .EXPECT ().GetClient (gomock .Any (), gomock .Eq ("foo" )).Return (client , nil )
410+ client .Public = false
411+ client .Secret = []byte ("foo" )
412+ hasher .EXPECT ().Compare (context .TODO (), gomock .Eq ([]byte ("foo" )), gomock .Eq ([]byte ("bar" ))).Return (nil )
413+ handlerWithoutClientAuth .EXPECT ().HandleTokenEndpointRequest (gomock .Any (), gomock .Any ()).Return (nil )
414+ handlerWithClientAuth .EXPECT ().HandleTokenEndpointRequest (gomock .Any (), gomock .Any ()).Return (nil )
415+ },
416+ method : "POST" ,
417+ expect : & AccessRequest {
418+ GrantTypes : Arguments {"foo" },
419+ Request : Request {
420+ Client : client ,
421+ },
422+ },
423+ handlers : TokenEndpointHandlers {handlerWithoutClientAuth , handlerWithClientAuth },
424+ },
425+ {
426+ header : http.Header {},
427+ form : url.Values {
428+ "grant_type" : {"foo" },
429+ },
430+ mock : func () {
431+ store .EXPECT ().GetClient (gomock .Any (), gomock .Any ()).Times (0 )
432+ handlerWithoutClientAuth .EXPECT ().HandleTokenEndpointRequest (gomock .Any (), gomock .Any ()).Return (nil )
433+ },
434+ method : "POST" ,
435+ expectErr : ErrInvalidRequest ,
436+ handlers : TokenEndpointHandlers {handlerWithoutClientAuth , handlerWithClientAuth },
437+ },
438+ } {
439+ t .Run (fmt .Sprintf ("case=%d" , k ), func (t * testing.T ) {
440+ r := & http.Request {
441+ Header : c .header ,
442+ PostForm : c .form ,
443+ Form : c .form ,
444+ Method : c .method ,
445+ }
446+ c .mock ()
447+ ctx := NewContext ()
448+ fosite .TokenEndpointHandlers = c .handlers
449+ ar , err := fosite .NewAccessRequest (ctx , r , new (DefaultSession ))
450+
451+ if c .expectErr != nil {
452+ assert .EqualError (t , err , c .expectErr .Error ())
453+ } else {
454+ require .NoError (t , err )
455+ AssertObjectKeysEqual (t , c .expect , ar , "GrantTypes" , "Client" )
456+ assert .NotNil (t , ar .GetRequestedAt ())
457+ }
458+ })
459+ }
460+ }
461+
224462func basicAuth (username , password string ) string {
225463 return "Basic " + base64 .StdEncoding .EncodeToString ([]byte (fmt .Sprintf ("%s:%s" , username , password )))
226464}
0 commit comments