@@ -314,6 +314,103 @@ func TestAuthorize_Manual_AuthCode(t *testing.T) {
314314 }
315315}
316316
317+ func TestAuthorize_Manual_AuthURL_RequireStateMissing (t * testing.T ) {
318+ origRead := readClientCredentials
319+ origEndpoint := oauthEndpoint
320+
321+ t .Cleanup (func () {
322+ readClientCredentials = origRead
323+ oauthEndpoint = origEndpoint
324+ })
325+ useTempManualStatePath (t )
326+
327+ readClientCredentials = func (string ) (config.ClientCredentials , error ) {
328+ return config.ClientCredentials {ClientID : "id" , ClientSecret : "secret" }, nil
329+ }
330+ oauthEndpoint = oauth2EndpointForTest ("http://example.com" )
331+
332+ _ , err := Authorize (context .Background (), AuthorizeOptions {
333+ Scopes : []string {"s1" },
334+ Manual : true ,
335+ AuthURL : "http://localhost:1/?code=abc" ,
336+ RequireState : true ,
337+ Client : "default" ,
338+ Timeout : 2 * time .Second ,
339+ })
340+ if err == nil {
341+ t .Fatalf ("expected error" )
342+ }
343+ if ! errors .Is (err , errMissingState ) {
344+ t .Fatalf ("expected missing state error, got: %v" , err )
345+ }
346+ }
347+
348+ func TestAuthorize_Manual_AuthURL_RequireStateMissingCache (t * testing.T ) {
349+ origRead := readClientCredentials
350+ origEndpoint := oauthEndpoint
351+
352+ t .Cleanup (func () {
353+ readClientCredentials = origRead
354+ oauthEndpoint = origEndpoint
355+ })
356+ useTempManualStatePath (t )
357+
358+ readClientCredentials = func (string ) (config.ClientCredentials , error ) {
359+ return config.ClientCredentials {ClientID : "id" , ClientSecret : "secret" }, nil
360+ }
361+ oauthEndpoint = oauth2EndpointForTest ("http://example.com" )
362+
363+ _ , err := Authorize (context .Background (), AuthorizeOptions {
364+ Scopes : []string {"s1" },
365+ Manual : true ,
366+ AuthURL : "http://localhost:1/?code=abc&state=state123" ,
367+ RequireState : true ,
368+ Client : "default" ,
369+ Timeout : 2 * time .Second ,
370+ })
371+ if err == nil {
372+ t .Fatalf ("expected error" )
373+ }
374+ if ! errors .Is (err , errManualStateMissing ) {
375+ t .Fatalf ("expected manual state missing error, got: %v" , err )
376+ }
377+ }
378+
379+ func TestAuthorize_Manual_AuthURL_RequireStateMismatch (t * testing.T ) {
380+ origRead := readClientCredentials
381+ origEndpoint := oauthEndpoint
382+
383+ t .Cleanup (func () {
384+ readClientCredentials = origRead
385+ oauthEndpoint = origEndpoint
386+ })
387+ useTempManualStatePath (t )
388+
389+ readClientCredentials = func (string ) (config.ClientCredentials , error ) {
390+ return config.ClientCredentials {ClientID : "id" , ClientSecret : "secret" }, nil
391+ }
392+ oauthEndpoint = oauth2EndpointForTest ("http://example.com" )
393+
394+ if err := saveManualState ("default" , []string {"s1" }, false , "state123" ); err != nil {
395+ t .Fatalf ("save manual state: %v" , err )
396+ }
397+
398+ _ , err := Authorize (context .Background (), AuthorizeOptions {
399+ Scopes : []string {"s1" },
400+ Manual : true ,
401+ AuthURL : "http://localhost:1/?code=abc&state=DIFFERENT" ,
402+ RequireState : true ,
403+ Client : "default" ,
404+ Timeout : 2 * time .Second ,
405+ })
406+ if err == nil {
407+ t .Fatalf ("expected error" )
408+ }
409+ if ! errors .Is (err , errManualStateMismatch ) {
410+ t .Fatalf ("expected manual state mismatch error, got: %v" , err )
411+ }
412+ }
413+
317414func TestAuthorize_ServerFlow_Success (t * testing.T ) {
318415 origRead := readClientCredentials
319416 origEndpoint := oauthEndpoint
0 commit comments