@@ -17,6 +17,7 @@ import (
1717 "github.com/cozy/cozy-stack/pkg/couchdb"
1818 "github.com/cozy/cozy-stack/pkg/prefixer"
1919 "github.com/cozy/cozy-stack/tests/testutils"
20+ weberrors "github.com/cozy/cozy-stack/web/errors"
2021 "github.com/gavv/httpexpect/v2"
2122 "github.com/labstack/echo/v4"
2223 "github.com/stretchr/testify/assert"
@@ -36,6 +37,7 @@ func TestOauth(t *testing.T) {
3637
3738 setup := testutils .NewSetup (t , t .Name ())
3839 ts := setup .GetTestServer ("/accounts" , Routes , func (r * echo.Echo ) * echo.Echo {
40+ r .HTTPErrorHandler = weberrors .ErrorHandler
3941 r .POST ("/login" , func (c echo.Context ) error {
4042 sess , _ := session .New (testInstance , session .LongRun , "" )
4143 cookie , _ := sess .ToCookie ()
@@ -330,6 +332,58 @@ func TestOauth(t *testing.T) {
330332 res .Cookies ().Length ().Equal (1 )
331333 res .Cookie ("cozysessid" ).Value ().NotEmpty ()
332334 })
335+
336+ t .Run ("RefreshReturnsStructuredInvalidTokenError" , func (t * testing.T ) {
337+ e := testutils .CreateTestClient (t , ts .URL )
338+ _ , token := setup .GetTestClient (consts .Accounts )
339+
340+ service := httptest .NewServer (http .HandlerFunc (func (c http.ResponseWriter , r * http.Request ) {
341+ require .Equal (t , http .MethodPost , r .Method )
342+ require .NoError (t , r .ParseForm ())
343+ assert .Equal (t , "refresh_token" , r .FormValue ("grant_type" ))
344+ assert .Equal (t , "bad-refresh-token" , r .FormValue ("refresh_token" ))
345+ assert .Equal (t , "the-client-id" , r .FormValue ("client_id" ))
346+ assert .Equal (t , "the-client-secret" , r .FormValue ("client_secret" ))
347+ c .Header ().Set ("Content-Type" , "application/json" )
348+ c .WriteHeader (http .StatusUnauthorized )
349+ _ , _ = c .Write ([]byte (`{"error":"invalid_token","error_description":"refresh token rejected"}` ))
350+ }))
351+ t .Cleanup (service .Close )
352+
353+ serviceType := account.AccountType {
354+ DocID : "test-service-refresh" ,
355+ TokenEndpoint : service .URL + "/oauth2/token" ,
356+ ClientID : "the-client-id" ,
357+ ClientSecret : "the-client-secret" ,
358+ }
359+ err := couchdb .CreateNamedDoc (prefixer .SecretsPrefixer , & serviceType )
360+ require .NoError (t , err )
361+ t .Cleanup (func () { _ = couchdb .DeleteDoc (prefixer .SecretsPrefixer , & serviceType ) })
362+
363+ acc := & account.Account {
364+ AccountType : serviceType .DocID ,
365+ Oauth : & account.OauthInfo {
366+ RefreshToken : "bad-refresh-token" ,
367+ },
368+ }
369+ require .NoError (t , couchdb .CreateDoc (testInstance , acc ))
370+ t .Cleanup (func () {
371+ acc .ManualCleaning = true
372+ _ = couchdb .DeleteDoc (testInstance , acc )
373+ })
374+
375+ obj := e .POST ("/accounts/test-service-refresh/" + acc .ID ()+ "/refresh" ).
376+ WithHeader ("Authorization" , "Bearer " + token ).
377+ Expect ().Status (http .StatusUnauthorized ).
378+ JSON (httpexpect.ContentOpts {MediaType : "application/vnd.api+json" }).
379+ Object ()
380+
381+ errObj := obj .Value ("errors" ).Array ().First ().Object ()
382+ errObj .ValueEqual ("status" , "401" )
383+ errObj .ValueEqual ("title" , "Unauthorized" )
384+ errObj .ValueEqual ("code" , account .RefreshOAuthErrorCodeInvalidToken )
385+ errObj .ValueEqual ("detail" , "OAuth refresh token is invalid or expired; reconnect account." )
386+ })
333387}
334388
335389func makeTestRedirectURLService (redirectURI string ) * httptest.Server {
0 commit comments