Skip to content

Commit

Permalink
feat: use dynamic signing key switching
Browse files Browse the repository at this point in the history
  • Loading branch information
furkansenharputlu committed Apr 25, 2024
1 parent 0eff984 commit 74a8b3b
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 4 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [unreleased]

- `session.CreateNewSession` now defaults to the value of the `st-auth-mode` header (if available) if the configured `config.GetTokenTransferMethod` returns `any`.
- Enable smooth switching between `useDynamicAccessTokenSigningKey` settings by allowing refresh calls to change the signing key type of a session.

## [0.17.5] - 2024-03-14
- Adds a type uint64 to the `accessTokenCookiesExpiryDurationMillis` local variable in `recipe/session/utils.go`. It also removes the redundant `uint64` type forcing needed because of the untyped variable.
Expand Down
2 changes: 1 addition & 1 deletion recipe/session/recipeImplementation.go
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,7 @@ func MakeRecipeImplementation(querier supertokens.Querier, config sessmodels.Typ

supertokens.LogDebugMessage("refreshSession: Started")

response, err := refreshSessionHelper(config, querier, refreshToken, antiCsrfToken, disableAntiCsrf, userContext)
response, err := refreshSessionHelper(config, querier, refreshToken, antiCsrfToken, disableAntiCsrf, config.UseDynamicAccessTokenSigningKey, userContext)
if err != nil {
return nil, err
}
Expand Down
7 changes: 4 additions & 3 deletions recipe/session/sessionFunctions.go
Original file line number Diff line number Diff line change
Expand Up @@ -224,10 +224,11 @@ func getSessionInformationHelper(querier supertokens.Querier, sessionHandle stri
return nil, nil
}

func refreshSessionHelper(config sessmodels.TypeNormalisedInput, querier supertokens.Querier, refreshToken string, antiCsrfToken *string, disableAntiCsrf bool, userContext supertokens.UserContext) (sessmodels.CreateOrRefreshAPIResponse, error) {
func refreshSessionHelper(config sessmodels.TypeNormalisedInput, querier supertokens.Querier, refreshToken string, antiCsrfToken *string, disableAntiCsrf bool, useDynamicAccessTokenSigningKey bool, userContext supertokens.UserContext) (sessmodels.CreateOrRefreshAPIResponse, error) {
requestBody := map[string]interface{}{
"refreshToken": refreshToken,
"enableAntiCsrf": !disableAntiCsrf && config.AntiCsrfFunctionOrString.StrValue == AntiCSRF_VIA_TOKEN,
"refreshToken": refreshToken,
"enableAntiCsrf": !disableAntiCsrf && config.AntiCsrfFunctionOrString.StrValue == AntiCSRF_VIA_TOKEN,
"useDynamicSigningKey": useDynamicAccessTokenSigningKey,
}
if antiCsrfToken != nil {
requestBody["antiCsrfToken"] = *antiCsrfToken
Expand Down
85 changes: 85 additions & 0 deletions recipe/session/sessionHandlingFuncsWithoutReq_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package session

import (
"errors"
"strings"
"testing"

"github.com/stretchr/testify/assert"
Expand Down Expand Up @@ -472,3 +473,87 @@ func TestRefreshShouldReturnErrorForNonTokens(t *testing.T) {
assert.NotNil(t, err2)
assert.True(t, errors.As(err2, &sessionError.UnauthorizedError{}))
}

func TestUseDynamicAccessTokenSigningKey(t *testing.T) {
useDynamicAccessTokenSigningKey := true
configValue := supertokens.TypeInput{
Supertokens: &supertokens.ConnectionInfo{
ConnectionURI: "http://localhost:8080",
},
AppInfo: supertokens.AppInfo{
AppName: "SuperTokens",
WebsiteDomain: "supertokens.io",
APIDomain: "api.supertokens.io",
},
RecipeList: []supertokens.Recipe{
Init(&sessmodels.TypeInput{
UseDynamicAccessTokenSigningKey: &useDynamicAccessTokenSigningKey,
}),
},
}
BeforeEach()
unittesting.StartUpST("localhost", "8080")
defer AfterEach()

checkAccessTokenSigningKeyType := func(t *testing.T, tokens sessmodels.SessionTokens, isDynamic bool) {
t.Helper()

info, err := ParseJWTWithoutSignatureVerification(tokens.AccessToken)
assert.NoError(t, err)

if isDynamic {
assert.True(t, strings.HasPrefix(*info.KID, "d-"))
} else {
assert.True(t, strings.HasPrefix(*info.KID, "s-"))
}
}

err := supertokens.Init(configValue)
assert.NoError(t, err)

res, err := CreateNewSessionWithoutRequestResponse("public", "test-user-id", map[string]interface{}{
"tokenProp": true,
}, map[string]interface{}{
"dbProp": true,
}, nil)

assert.NoError(t, err)

tokens := res.GetAllSessionTokensDangerously()
checkAccessTokenSigningKeyType(t, tokens, true)

resetAll()

// here we change to false
useDynamicAccessTokenSigningKey = false
err = supertokens.Init(configValue)
assert.NoError(t, err)

t.Run("should throw when verifying", func(t *testing.T) {
_, err = GetSessionWithoutRequestResponse(tokens.AccessToken, tokens.AntiCsrfToken, nil)
assert.Equal(t, err.Error(), "The access token doesn't match the useDynamicAccessTokenSigningKey setting")
})

t.Run("should work after refresh", func(t *testing.T) {
disableAntiCsrf := true
refreshedSession, err := RefreshSessionWithoutRequestResponse(*tokens.RefreshToken, &disableAntiCsrf, tokens.AntiCsrfToken)
assert.NoError(t, err)

tokensAfterRefresh := refreshedSession.GetAllSessionTokensDangerously()
assert.True(t, tokensAfterRefresh.AccessAndFrontendTokenUpdated)
checkAccessTokenSigningKeyType(t, tokensAfterRefresh, false)

verifiedSession, err := GetSessionWithoutRequestResponse(tokensAfterRefresh.AccessToken, tokensAfterRefresh.AntiCsrfToken, nil)
assert.NoError(t, err)

tokensAfterVerify := verifiedSession.GetAllSessionTokensDangerously()
assert.True(t, tokensAfterVerify.AccessAndFrontendTokenUpdated)
checkAccessTokenSigningKeyType(t, tokensAfterVerify, false)

verifiedSession2, err := GetSessionWithoutRequestResponse(tokensAfterVerify.AccessToken, tokensAfterVerify.AntiCsrfToken, nil)
assert.NoError(t, err)

tokensAfterVerify2 := verifiedSession2.GetAllSessionTokensDangerously()
assert.False(t, tokensAfterVerify2.AccessAndFrontendTokenUpdated)
})
}

0 comments on commit 74a8b3b

Please sign in to comment.