diff --git a/CHANGELOG.md b/CHANGELOG.md index c52d9c88..f318bc0b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [unreleased] +## [0.22.1] - 2024-07-09 + +### Changes + +- `refreshPOST` and `RefreshSession` now clears all user tokens upon CSRF failures and if no tokens are found. See the latest comment on https://github.com/supertokens/supertokens-node/issues/141 for more details. + ## [0.22.0] - 2024-06-24 ### Breaking change diff --git a/recipe/emailpassword/authMode_test.go b/recipe/emailpassword/authMode_test.go index 10a7c4ea..a4415fff 100644 --- a/recipe/emailpassword/authMode_test.go +++ b/recipe/emailpassword/authMode_test.go @@ -1145,14 +1145,14 @@ func TestRefreshTokenBehaviour(t *testing.T) { setTokens string clearedTokens string }{ - {getTokenTransferMethodRes: "any", authHeader: false, authCookie: false, output: "unauthorised", setTokens: "none", clearedTokens: "none"}, - {getTokenTransferMethodRes: "header", authHeader: false, authCookie: false, output: "unauthorised", setTokens: "none", clearedTokens: "none"}, - {getTokenTransferMethodRes: "cookie", authHeader: false, authCookie: false, output: "unauthorised", setTokens: "none", clearedTokens: "none"}, + {getTokenTransferMethodRes: "any", authHeader: false, authCookie: false, output: "unauthorised", setTokens: "none", clearedTokens: "both"}, + {getTokenTransferMethodRes: "header", authHeader: false, authCookie: false, output: "unauthorised", setTokens: "none", clearedTokens: "both"}, + {getTokenTransferMethodRes: "cookie", authHeader: false, authCookie: false, output: "unauthorised", setTokens: "none", clearedTokens: "both"}, {getTokenTransferMethodRes: "any", authHeader: false, authCookie: true, output: "validatecookie", setTokens: "cookies", clearedTokens: "none"}, - {getTokenTransferMethodRes: "header", authHeader: false, authCookie: true, output: "unauthorised", setTokens: "none", clearedTokens: "none"}, + {getTokenTransferMethodRes: "header", authHeader: false, authCookie: true, output: "unauthorised", setTokens: "none", clearedTokens: "both"}, {getTokenTransferMethodRes: "cookie", authHeader: false, authCookie: true, output: "validatecookie", setTokens: "cookies", clearedTokens: "none"}, {getTokenTransferMethodRes: "any", authHeader: true, authCookie: false, output: "validateheader", setTokens: "headers", clearedTokens: "none"}, - {getTokenTransferMethodRes: "header", authHeader: true, authCookie: false, output: "validateheader", setTokens: "headers", clearedTokens: "none"}, + {getTokenTransferMethodRes: "header", authHeader: true, authCookie: false, output: "validateheader", setTokens: "headers", clearedTokens: "both"}, {getTokenTransferMethodRes: "cookie", authHeader: true, authCookie: false, output: "unauthorised", setTokens: "none", clearedTokens: "none"}, {getTokenTransferMethodRes: "any", authHeader: true, authCookie: true, output: "validateheader", setTokens: "headers", clearedTokens: "cookies"}, {getTokenTransferMethodRes: "header", authHeader: true, authCookie: true, output: "validateheader", setTokens: "headers", clearedTokens: "cookies"}, @@ -1224,6 +1224,13 @@ func TestRefreshTokenBehaviour(t *testing.T) { assert.Equal(t, refreshRes["accessTokenExpiry"], "Thu, 01 Jan 1970 00:00:00 GMT") assert.Empty(t, refreshRes["sRefreshToken"]) assert.Equal(t, refreshRes["refreshTokenExpiry"], "Thu, 01 Jan 1970 00:00:00 GMT") + } else if behaviour.clearedTokens == "both" { + assert.Empty(t, refreshRes["accessTokenFromHeader"]) + assert.Empty(t, refreshRes["refreshTokenFromHeader"]) + assert.Empty(t, refreshRes["sAccessToken"]) + assert.Equal(t, refreshRes["accessTokenExpiry"], "Thu, 01 Jan 1970 00:00:00 GMT") + assert.Empty(t, refreshRes["sRefreshToken"]) + assert.Equal(t, refreshRes["refreshTokenExpiry"], "Thu, 01 Jan 1970 00:00:00 GMT") } switch behaviour.setTokens { @@ -1247,17 +1254,18 @@ func TestRefreshTokenBehaviour(t *testing.T) { } } - if behaviour.setTokens != "cookies" && behaviour.clearedTokens != "cookies" { - assert.Equal(t, refreshRes["sAccessToken"], "-not-present-") - assert.Equal(t, refreshRes["accessTokenExpiry"], "-not-present-") - assert.Equal(t, refreshRes["sRefreshToken"], "-not-present-") - assert.Equal(t, refreshRes["refreshTokenExpiry"], "-not-present-") - } - if behaviour.setTokens != "headers" && behaviour.clearedTokens != "headers" { - assert.Equal(t, refreshRes["accessTokenFromHeader"], "-not-present-") - assert.Equal(t, refreshRes["refreshTokenFromHeader"], "-not-present-") + if behaviour.setTokens != "both" { + if behaviour.setTokens != "cookies" && behaviour.clearedTokens != "cookies" { + assert.Equal(t, refreshRes["sAccessToken"], "-not-present-") + assert.Equal(t, refreshRes["accessTokenExpiry"], "-not-present-") + assert.Equal(t, refreshRes["sRefreshToken"], "-not-present-") + assert.Equal(t, refreshRes["refreshTokenExpiry"], "-not-present-") + } + if behaviour.setTokens != "headers" && behaviour.clearedTokens != "headers" { + assert.Equal(t, refreshRes["accessTokenFromHeader"], "-not-present-") + assert.Equal(t, refreshRes["refreshTokenFromHeader"], "-not-present-") + } } - }) t.Run(fmt.Sprintf("behaviour %v with invalid token", behaviour), func(t *testing.T) { diff --git a/recipe/session/sessionRequestFunctions.go b/recipe/session/sessionRequestFunctions.go index e8044d56..ed2f5d39 100644 --- a/recipe/session/sessionRequestFunctions.go +++ b/recipe/session/sessionRequestFunctions.go @@ -386,7 +386,7 @@ func RefreshSessionInRequest(req *http.Request, res http.ResponseWriter, config False := false return nil, errors.UnauthorizedError{ Msg: "Refresh token not found. Are you sending the refresh token in the request as a cookie?", - ClearTokens: &False, + ClearTokens: &True, } } @@ -406,7 +406,7 @@ func RefreshSessionInRequest(req *http.Request, res http.ResponseWriter, config if ridFromHeader == nil { supertokens.LogDebugMessage("refreshSession: Returning UNAUTHORISED because custom header (rid) was not passed") - clearTokens := false + clearTokens := true return nil, errors.UnauthorizedError{ Msg: "anti-csrf check failed. Please pass 'rid: \"session\"' header in the request.", ClearTokens: &clearTokens, diff --git a/supertokens/constants.go b/supertokens/constants.go index b35153d9..0bac26fb 100644 --- a/supertokens/constants.go +++ b/supertokens/constants.go @@ -21,7 +21,7 @@ const ( ) // VERSION current version of the lib -const VERSION = "0.22.0" +const VERSION = "0.22.1" var ( cdiSupported = []string{"3.0"}